JS与WebView交互存在的一些问题

作者 隔壁的李小宝 关注

2015.06.09 19:30 字数 2896 阅读 11117评论 3喜欢 35

一、背景概述

2013年Android平台暴露出WebView漏洞。利用该漏洞,攻击者可以通过存在风险的addJavascriptInterface接口函数提供的扩展穿透webkit执行本地Java代码,造成恶意代码在受害人的手机上执行,并可能进一步执行木马。
目前,google公司仅对Android4.2及以上系统提供了规避方法,Android4.2以下所有版本尚无官方解决方案。
本文将就上述漏洞提出相应的解决方案。

Android API level 16以及之前的版本存在远程代码执行安全漏洞,该漏洞源于程序没有正确限制使用WebView.addJavascriptInterface方法,远程攻击者可通过使用Java Reflection API利用该漏洞执行任意Java对象的方法,简单的说就是通过addJavascriptInterface给WebView加入一个JavaScript桥接接口,JavaScript通过调用这个接口可以直接操作本地的JAVA接口。
该漏洞公布的近期,多款Android流行应用曾被曝出高危挂马漏洞:点击消息或朋友社区圈中的一条网址时,用户手机然后就会自动执行被挂马的代码指令,从而导致被安装恶意扣费软件、向好友发送欺诈短信、通讯录和短信被窃取以及被远程控制等严重后果。在乌云漏洞平台上,包括Android版的微信、QQ、腾讯微博、QQ浏览器、快播、百度浏览器、金山浏览器等大批TOP应用均被曝光同类型的漏洞。

不可避免,由于公司中,修旧并行的架构中,涉及很多的WebView和JS交互的功能实现点。安全部已经发布方案,需要我们修改。最近一直在做这方面的研究。
引用:【http://blog.csdn.net/leehong2005/article/details/11808557#】
使用WebView来展示一个网页,现在很多应用为了做到服务端可控,很多结果页都是网页的,而不是本地实现,这样做有很多好处,比如界面的改变不需要重新发布新版本,直接在Server端修改就行了。用网页来展示界面,通常情况下都或多或少都与Java代码有交互,比如点击网页上面的一个按钮,我们需要知道这个按钮点击事件,或者我们要调用某个方法,让页面执行某种动作,为了实现这些交互,我们通常都是使用JS来实现,而WebView已经提供了这样的方法,具体用法如下:
< mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");>

我们向WebView注册一个名叫“jsInterface”的对象,然后在JS中可以访问到jsInterface这个对象,就可以调用这个对象的一些方法,最终可以调用到Java代码中,从而实现了JS与Java代码的交互。
我们一起来看看关于addJavascriptInterface方法在Android官网的描述:

This method can be used to allow JavaScript to control the host application. This is a powerful feature, but also presents a security risk for applications targeted to API level JELLY_BEAN
or below, because JavaScript could use reflection to access an injected object's public fields. Use of this method in a WebView containing untrusted content could allow an attacker to manipulate the host application in unintended ways, executing Java code with the permissions of the host application. Use extreme care when using this method in a WebView which could contain untrusted content.
JavaScript interacts with Java object on a private, background thread of this WebView. Care is therefore required to maintain thread safety.
The Java object's fields are not accessible.

简单地说,就是用addJavascriptInterface可能导致不安全,因为JS可能包含恶意代码。今天我们要说的这个漏洞就是这个,当JS包含恶意代码时,它可以干任何事情。

二、实现方案

1、Android 4.2以上的系统

Android 4.2以上系统,通过在Java的远程方法上面声明@JavascriptInterface可以解决WebView漏洞。如下面代码:

    class JsObject {
@JavascriptInterface
public String toString() { return "injectedObject"; }
}

2、Android 4.2以下的系统

若客户端需要兼容支持Android 4.2以下的系统版本,建议使用本方案规避WebView漏洞。本方案分为两个修改要点,建议对于https和http场景均使用下述方法规避风险。

修改点一:使用安全方法替代addJavascriptInterface

对于Android 4.2以下的系统Google公司官方没有提供解决方案。为替代addJavascriptInterface方法,可以利用prompt方法传参以完成java与js的交互。对应java中的onJsPrompt方法的声明如下:
public boolean onJsPrompt( WebView view, String url, String message, String defaultValue, JsPromptResult result )
通过这个方法,JS能把信息(文本)传递到Java,而Java也能把信息(文本)传递到JS中。

具体实施方法如下:

1)让JS调用一个Javascript方法,在这个方法中调用prompt方法,通过prompt把JS中的信息传递过来,这些信息应该是我们组合成的一段有意义的文本,可能包含:特定标识,参数等。在onJsPrompt方法中,我们去解析传递过来的文本,得到约定好的特定标识,参数等,再通过特定标识调用指定的java方法,并传入参数。具体的Java代码如下:

final class MyWebChromeClient extends WebChromeClient
{
public boolean onJsPrompt( WebView view, String url, String message, String defaultValue, JsPromptResult result )
{
if( message.equals("1") )
{
//解析参数defaultValue
//调用java方法并得到结果
}
//返回结果
result.confirm("result");
return true;
}
}

2)关于返回值,可以通过result返回回去,这样就可以把Java中方法的处理结果返回到Js中。
3)在Javascript方法中,通过调用prompt方法传入标识和参数(依次对应onJsPrompt方法中的message、defaultValue参数),以通知java需要使用的方法及对应参数。prompt方法中第一个参数可以传送约定好的特定方法标识,prompt方法中第二个参数可以传入对应的参数序列。具体的Javascript代码如下:

   function showHtmlcallJava()
{
var ret = prompt( "1", "param1;param2" );
//ret值即为java传回的”result”
//根据返回内容作相应处理
}

修改点二:移除系统开放的JS接口

对于Android 3.0以上版本,Android系统开放了部分JS接口。因此在这个版本范围下,尽管客户端自身没有使用addJavascriptInterface方法,黑客仍可以透过系统开放的JS接口实施恶意操作。
针对上述风险,客户端可通过下面的方法移除风险接口。具体实施方法如下:
1)使用removeJavascriptInterface方法移除操作系统开放的"searchBoxJavaBridge_"、"accessibility"、"accessibilityTraversal"接口。由于removeJavascriptInterface方法只在Android API 11以上版本支持,因此若客户端需要支持Android API 11以下版本,需要在使用该方法时声明目标API。
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void dealJavascriptLeak() {
mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
mWebView.removeJavascriptInterface("accessibility");
mWebView.removeJavascriptInterface("accessibilityTraversal");
}

2)针对Android3.0以上系统版本移除问题接口。
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
dealJavascriptLeak();
}

三、总结

对于https和http协议访问的页面,开发过程中须注意弃用存在漏洞的addJavascriptInterface方法,通过使用prompt方法传参,完成java与js的交互。同时客户端须移除系统开放的JS接口,全面规避WebView漏洞风险。

详细修步骤:

【1】让JS调用一个Javascript方法,这个方法中是调用prompt方法,通过prompt把JS中的信息传递过来,这些信息应该是我们组合成的一段有意义的文本,可能包含:特定标识,方法名称,参数等。在onJsPrompt方法中,我们去解析传递过来的文本,得到方法名,参数等,再通过反射机制,调用指定的方法,从而调用到Java对象的方法。
【2】关于返回值,可以通过prompt返回回去,这样就可以把Java中方法的处理结果返回到Js中。
【3】我们需要动态生成一段声明Javascript方法的JS脚本,通过loadUrl来加载它,从而注册到html页面中,具体的代码如下:

javascript:(function JsAddJavascriptInterface_(){
if (typeof(window.jsInterface)!='undefined') {
console.log('window.jsInterface_js_interface_name is exist!!');}
else {
window.jsInterface = {
onButtonClick:function(arg0) {
return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}));
},
onImageClick:function(arg0,arg1,arg2) { prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}));
},
};
}
}
)()

说明:
1,上面代码中的jsInterface就是要注册的对象名,它注册了两个方法,onButtonClick(arg0)和onImageClick(arg0, arg1, arg2),如果有返回值,就添加上return。
2,prompt中是我们约定的字符串,它包含特定的标识符MyApp:,后面包含了一串JSON字符串,它包含了方法名,参数,对象名等。
3,当JS调用onButtonClick或onImageClick时,就会回调到Java层中的onJsPrompt方法,我们再解析出方法名,参数,对象名,再反射调用方法。
4,window.jsInterface这表示在window上声明了一个Js对象,声明方法的形式是:方法名:function(参数1,参数2)
5,一些思考
以下是在实现这个解决方案过程中遇到的一些问题和思考:
【1】生成Js方法后,加载这段Js的时机是什么?
刚开始时在当WebView正常加载URL后去加载Js,但发现会存在问题,如果当WebView跳转到下一个页面时,之前加载的Js就可能无效了,所以需要再次加载。这个问题经过尝试,需要在以下几个方法中加载Js,它们是WebChromeClient和WebViewClient的方法:
· onLoadResource
· doUpdateVisitedHistory
· onPageStarted
· onPageFinished
· onReceivedTitle
· onProgressChanged
目前测试了这几个地方,没什么问题,这里我也不能完全确保没有问题。

【2】需要过滤掉Object类的方法
由于通过反射的形式来得到指定对象的方法,他会把基类的方法也会得到,最顶层的基类就是Object,所以我们为了不把getClass方法注入到Js中,所以我们需要把Object的公有方法过滤掉。这里严格说来,应该有一个需要过滤方法的列表。目前我的实现中,需要过滤的方法有:
"getClass",
"hashCode",
"notify",
"notifyAll",
"equals",
"toString",
"wait",

【3】通过手动loadUrl来加载一段js,这种方式难道js中的对象就不在window中吗?也就是说,通过遍历window的对象,不能找到我们通过loadUrl注入的js对象吗?
关于这个问题,我们的方法是通过Js声明的,通过loadUrl的形式来注入到页面中,其实本质相当于把我们这动态生成的这一段Js直接写在Html页面中,所以,这些Js中的window中虽然包含了我们声明的对象,但是他们并不是Java对象,他们是通过Js语法声明的,所以不存在getClass之类的方法。本质上他们是Js对象。

【4】在Android 3.0以下,系统自己添加了一个叫searchBoxJavaBridge_的Js接口,要解决这个安全问题,我们也需要把这个接口删除,调用removeJavascriptInterface方法。这个searchBoxJavaBridge_好像是跟google的搜索框相关的。

【5】在实现过程中,我们需要判断系统版本是否在4.2以下,因为在4.2以上,Android修复了这个安全问题。我们只是需要针对4.2以下的系统作修复。

(转载)JS与WebView交互存在的一些问题的更多相关文章

  1. android 从 phonegap 到 js webview 交互

    像生活类.办公协同类. 动态添加,下载等. 1.phonegap 我这里用了旧的版本,可能新版本变化大了. 创建asset资源文件夹,然后新建index.html copy 相应的js 文件进来. 创 ...

  2. 转载 【iOS开发】网页JS与OC交互(JavaScriptCore) OC ----->JS

      目标 本文介绍利用苹果在iOS7时发布的JavaScriptCore.framework框架进行js与OC的交互.我们想要达到的目标是: OC调用网页上的js方法 网页js调用APP中的OC方法 ...

  3. js与android webview交互

    0x01 js调用java代码 android webview中支持通过添加js接口 webview.addJavascriptInterface(new JsInteration(), " ...

  4. 转载 ---原生和H5交互挺多的,最近也有朋友再问。这儿我写个简单的例子给大家 直接贴代码 js的

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> ...

  5. js与native交互

    js与native交互 UIWebView Native调用JS,使用stringByEvaluatingJavaScriptFromString来解释执行js脚本. //script即为要执行的js ...

  6. js与C++交互及C++解析json

    转载:http://zhidao.baidu.com/link?url=LLuWzwMmpfVcQeSGv1CrAfRXpnZaetm9xypqwMW6zxLhhKES-rITAsG0-Ku-bSMA ...

  7. OC和JS之间的交互

    OC和JS之间的交互 目录 对OC和JS之间交互的理解 JS调用OC OC调用JS 对OC和JS之间交互的理解 JS调用OC JS文件 function sendCommand(cmd,param){ ...

  8. 史上最全的 UIWebview 的 JS 与 OC 交互

    来源:伯乐在线 - 键盘风筝 链接:http://ios.jobbole.com/89330/ 点击 → 申请加入伯乐在线专栏作者 其实一直想给大家整理一下JS与OC的交互,但是没有合适的机会,今天借 ...

  9. UIWebView与JS的深度交互

    我要实现这样一个需求:按照本地的CSS文件展示一串网络获取的带HTML格式的只有body部分的文本,需要自己拼写完整的 HTML.除此之外,还需要禁用获取的HTML文本中自带的 < img &g ...

随机推荐

  1. 备份IIS

    备份IIS,这里实质指的是备份IIS配置.如果要备份IIS部署的网站的话,直接Copy目录就行了. 备份IIS配置其实和备份系统含义差不多,为了方便系统或者IIS出现故障后能够及时恢复到某节点上,所以 ...

  2. 1到32 数字正则 还有IP的

    正则是按位解析匹配的,所以[1-32]是不行的. 解析: 1.1-32,包含1位数(1-9)和2位数(10-32) 2.10-32必须切割,10-19和20-29形式一样,得到[12][0-9],30 ...

  3. const使用总结

    1.常变量:  const 类型说明符 变量名    const int a; 常引用:  const 类型说明符 &引用名   const int &a; 常对象:  类名 cons ...

  4. ScSPM & LLC

    为啥会有SPM→ScSPM呢?原因之一是为了寻找better coding + better pooling的方式提高性能,原因之二就是提高速度.如何提高速度?这里的速度,不是Coding+Pooli ...

  5. 使用css选择器来定位元素

    public void CSS(){ driver.get(Constant.baidu_url); //绝对路径 // driver.findElement(By.cssSelector(" ...

  6. JavaScript 实现简单的 弹出框关闭框

    JavaScript 实现简单的 弹出框关闭框 知识点: 1.javaScript 添加HTML标签 2.javaScript 添加HTML标签属性 3.javaScript 追加元素 代码献上: & ...

  7. Python3的URL编码解码

    前言 博主最近在用python3练习一些爬虫脚本的时候,发现一些url的编码问题,在浏览器提交请求api时,如果url中包含汉子,就会被自动编码掉.呈现的结果是 ==> %xx%xx%xx.如果 ...

  8. Ubuntu下安装curl和corn

    Ubuntu下安装curl sudo apt install curl Ubuntu下安装cron apt-get install cron

  9. HDU 4314 Contest 2

    可以知道,逃出的人中,最后一个应当是A+B最长的,这是很容易发现的.那么,最选逃出去的必定是A+B最短的.这符合最优. 于是,可以把各小矮人按A+B的和由大到小排序.定义DP[i][j]为i个人中逃出 ...

  10. Android中通过ViewHelper.setTranslationY实现View移动控制(NineOldAndroids开源项目)

    我们知道有不少开源project,能实现非常多不错的效果.前几天,我看了一个效果,刚好项目中也用到了这个jar包. 没事挖一挖 学一学(一说到挖一挖.那么问题来了.挖掘机技术究竟哪家强 ),看看不错的 ...