一、WebView漏洞持续高居榜首
Webview相关问题早在2012年【2】就已经披露并广泛关注,但到为何到现在还是持续高居漏洞榜首?!
二、Webview是一个什么样的组件
WebView是Android中一个非常实用的组件,它和Safai、Chrome一样都是基于Webkit网页渲染引擎,可以通过加载HTML数据的方式便捷地展现软件的界面。使用WebView开发软件有以下几个优点:
1、 可以打开远程URL页面,也可以加载本地HTML数据;
2、 可以无缝的在java和javascript之间进行交互操作;
3、高度的定制性,可根据开发者的需要进行多样性定制。
三、Webview相关漏洞有哪些?
1、 Webview addJavascriptInterface远程代码执行漏洞,漏洞编号CVE-2012-6636:
Webview是Android系统中为Android App用来渲染网页的,为了便于JS互动展示,一般都会调用addJavascriptInterface接口。用例如下:
mWebView=new WebView(this);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JavaScriptInterface(), " injectedObj ");
mWebView.loadUrl("www.test.com");
setContentView(mWebView);
由于Android API level 16以及之前的版本没有正确限制使用WebView.addJavascriptInterface方法,远程攻击者可通过使用Java Reflection API利用该漏洞执行任意Java对象的方法,简单的说就是通过addJavascriptInterface给WebView加入一个JavaScript桥接接口,JavaScript通过调用这个接口可以直接操作本地的JAVA环境环境,达到命令执行的目的。上面的代码可通过如下方法来执行任意命令:
<html>
<body>
<script>
function execute(cmdArgs)
{
return injectedObj.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
}
var res = execute(["/system/bin/sh", "-c", "ls -al /mnt/sdcard/"]);
document.write(getContents(res.getInputStream()));
</script>
</body>
</html>
2、 Android Webkit内置多个组件同样存在该漏洞:
2014年同时发现在Android系统中Webkit中默认内置的searchBoxJavaBridge_,accessibility,accessibilityTraversal组件都同样能引起类似的远程代码执行漏洞。漏洞编号为CVE-2014-1939、CVE-2014-7224。
3、Webview明文存储密码漏洞:
Webview明文存储密码漏洞是当使用Webview加载登陆页面的时候,如果不设置setSavePassword(false),就会弹出一个对话框询问是否保存密码,一旦用户选择了是,密码就会被明文保存在目录下的databases/webview.db 文件中,存在密码被泄漏的风险。
不过幸运的是在api18之后,该接口已经被google废除。但是在API 17之前,还是存在这个问题。
四、为何此类漏洞数量还高居不下?
出于安全考虑,为了防止Java层的函数被随便调用,Google在4.2版本之后,规定允许被调用的函数必须以@JavascriptInterface进行注解,所以如果某应用限定的最小API Level为17或者以上,就不会受该问题的影响。但是由于多种遗留问题造成漏洞数量还是高居首位:
1、 截止到2015年12月,Android 4.2以下版本的市场占有率还有18.3%左右,很多开发必须兼顾这些用户。
2、引起远程代码执行漏洞的根本原因发生在Android Webkit内部, 开发者无法从API层修复这个问题。只能利用Android API做一些补救, 比如通过限制Webview加载的url只能来自可信域。但都无法从本质上修复和规避这个安全风险。
3、 安全与产品需求的折中,Webview中使用JavaScript几乎是大部分开发中都必须要用到的特性。它直接决定了的某些重要功能能否实现,或是否能大幅度提升用户体验。当安全风险和产品功能相冲突时,产品功能的优先级往往都高于安全。
4、开发人员安全意识的薄弱。产品开发和产品安全虽然是孪生兄弟,但从产品角度看却属于不同分工。一个优秀的开发人员可能对安全风险感知很小或根本就缺乏重视。他们可能会为一个变量命名绞尽脑汁或对一个算法精雕细琢但却对代码安全完全忽略。
5、而Webview明文存储密码漏洞纯粹是开发者安全意识问题。许多开发者认为即使软件中存在有安全风险的代码但如果没有被外部利用的路径就是安全的。 从安全的角度出发代码安全不是静态的。有安全风险的代码存在即是有危险的。 如,开发者Alex开发了某个模块,使用了Webview,但是没有设置setSavePassword(false)。Alex认为自己代码中没有登陆页面,所以不会有问题。一段时间后开发者Bob接手了Alex的工作,因为需求变动Bob增加了一个登陆界面,但是没有检查Alex的代码,就会导致Webview明文存储密码漏洞。
五、修复建议
1、针对WebView远程代码执行漏洞修复建议:
- 继承Webview控件
因为以上5个原因都是来自webview这个控件,那么整体上来说,可以继承系统控件Webview,然后将安全问题全部集中在这个继承类里面解决。比如我们不用的addJavascriptInterface可以重载并抛出异常,移除searchBoxJavaBridge_,accessibility,accessibilityTraversa操作也可以在继承类中进行统一处理。
- 针对API Level等于或高于17的Android系统
出于安全考虑,为了防止Java层的函数被随便调用,Google在4.2版本之后,规定允许被调用的函数必须以@JavascriptInterface进行注解,所以如果某应用依赖的最小API Level为17或者以上,就能自然的避免风险。按照Google官方文档[5]使用示例:
class JsObject {
@JavascriptInterface
public String toString() { return "injectedObject"; }
}
webView.addJavascriptInterface(new JsObject(), "injectedObject");
webView.loadData("", "text/html", null);
webView.loadUrl("javascript:alert(injectedObject.toString())");
建议不要使用addJavascriptInterface接口,以免带来不必要的安全隐患,
如果一定要使用addJavascriptInterface接口,请遵循如下规则:
a、如果使用HTTPS协议加载URL,应进行证书校验防止访问的页面被篡改挂马;
b、如果使用HTTP协议加载URL,应进行白名单过滤、完整性校验等防止访问的页面被篡改;
c、如果加载本地Html,应将html文件内置在APK中,以及进行对html页面完整性的校验。
d、针对searchBoxJavaBridge_ 接口,这是开发者特别容易忽视的一个问题。大部分的远程代码执行问题来自于此。建议开发者一定需要通过以下方式移除该Javascript接口:
removeJavascriptInterface("searchBoxJavaBridge_")
而针对"accessibility" 和"accessibilityTraversal",建议开发者通过以下方式移除该JavaScript接口:
removeJavascriptInterface("accessibility");
removeJavascriptInterface("accessibilityTraversal");
2、 针对WebView明文存储密码漏洞修复建议:
开发者需要在使用webview的地方务必加上setSavePassword(false)。
六、参考:
1,http://jaq.alibaba.com/blog.htm?spm=0.0.0.0.CbH5hR&id=87
2,http://50.56.33.56/blog/?p=314
作者:舟海 呆狐