WebView常见漏洞修复

一、WebView中,主要漏洞有三类

  • 任意代码执行漏洞
  • 密码明文存储漏洞
  • 域控制不严格漏洞
    二、具体分析

2.1 WebView任意代码执行漏洞

出现该漏洞的三个:

  • WebView中addJavascriptInterface()接口
  • WebView 内置导出的 searchBoxJavaBridge_对象
  • WebView 内置导出的 accessibility 和 accessibilityTraversalObject 对象

2.1.1 WebView中addJavascriptInterface()接口

A.漏洞产生原因

JS调用Android的addJavascriptInterface接口进行对象映射:

 webView.addJavascriptInterface(new JSObject(), "myObj");
// 参数1:Android的本地对象
// 参数2:JS的对象
// 通过对象映射将Android中的本地对象和JS中的对象进行关联,从而实现JS调用Android的对象和方法

原因:在Android早期版本中并没有对可以访问的方法做限制,当JS拿到java对象后,就可以利用Java反射机制,调用任意对象的任意方法,如获取系统类(java.lang.Runtime类)

如可以执行命令获取本地设备SD卡中的文件等信息从而造成信息泄露

  • WebView 添加 Javascript 对象,并且添加一些权限,比如想要获取 SD 卡上面的信息就需要 android.permission.WRITE_EXTERNAL_STORAGE

  • JS 中可以遍历 window对象,找到存在 getClass 方法的对象,再通过反射的机制,得到 Runtime 对象,然后就可以调用静态方法来执行一些命令,比如访问文件的命令;

  • 从执行命令后返回的输入流中得到字符串,比如执行完访问文件的命令之后,就可以得到文件名的信息了

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

漏洞解决

4.2以上的版本规定够被调用的函数必须添加@JavascriptInterface进行注解

4.2以下的版本解决方法

  • 通过重写WebView中addJavascriptInterface 方法,然后在内部自己维护一个对象映射关系的 Map,当调用 addJavascriptInterface 方法,将需要添加的 JS 接口放入这个 Map 中;
    -每次当 WebView 加载页面的时候加载一段本地的 JS 代码:
avascript:(function JsAddJavascriptInterface_(){
//XXX表示注入对象的方法的名字,终端和Web端按照定义的格式去相互调用即可
    if(typeof(window.XXX_js_interface_name)!='undefined'){
            console.log('window.XXX_js_interface_name is exist!!');
        }else{
           window.XXX_js_interface_name={
                   XXX:function(arg0,arg1){
                   //在prompt中返回我们约定的字符串,包含了特定的标识符MyApp,后面包含了一串JSON字符串,它包含了方法名,参数,对象名等。当JS调用XXX方法的时候,就会调用到终端Native层的OnJsPrompt方法中,我们在解析出方法名,参数,对象名等
                     return prompt('MyApp:'+JSON.stringify({obj:'XXX_js_interface_name',func:'XXX_',args:[arg0,arg1]}));
                 },
            };
        }
    })

还有一个问题是什么时候加载这段 JS 呢,在 WebView 正常加载 URL 的时候去加载它,但是会发现当 WebView 跳转到下一个页面时,之前加载的 JS 可能就已经无效了,需要再次加载,所以通常需要在以下几个方法中加载 JS,这几个方法分别是 onLoadResource,doUpdateVisitedHistory,onPageStarted,onPageFinished,onReceivedTitle,onProgressChanged。
需要过滤的方法为Object类中定义的方法

2.2密码明文存储漏洞

WebView 默认开启密码保存功能 mWebView.setSavePassword(true),如果该功能未关闭,在用户输入密码时,会弹出提示框,询问用户是否保存密码,如果选择”是”,密码会被明文保到 /data/data/com.package.name/databases/webview.db 中,这样就有被盗取密码的危险,所以需要通过 WebSettings.setSavePassword(false) 关闭密码保存提醒功能。

2.3域控制不严格漏洞

了解WebView 中 file 协议的安全性,先看一个Demo, WebViewActivity

public class WebViewActivity extends Activity {
    private WebView webView;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);
        webView = (WebView) findViewById(R.id.webView);
        
        //webView.getSettings().setJavaScriptEnabled(true);                  
        //webView.getSettings().setAllowFileAccess(false);                   
        //webView.getSettings().setAllowFileAccessFromFileURLs(true);         
        //webView.getSettings().setAllowUniversalAccessFromFileURLs(true); 
        
        Intent i = getIntent();
        String url = i.getData().toString(); //url = file:///data/local/tmp/attack.html 
        webView.loadUrl(url);
    }
 }

当其他应用启动此 Activity 时, intent 中的 data 直接被当作 url 来加载(假定传进来的 url 为 file:///data/local/tmp/attack.html ),通过其他 APP 使用显式 ComponentName 或者其他类似方式就可以很轻松的启动该 WebViewActivity ,我们知道因为 Android 中的 sandbox,Android 中的各应用是相互隔离的,在一般情况下 A 应用是不能访问 B 应用的文件的,但不正确的使用 WebView 可能会打破这种隔离,从而带来应用数据泄露的威胁,即 A 应用可以通过 B 应用导出的 Activity 让 B 应用加载一个恶意的 file 协议的 url,从而可以获取 B 应用的内部私有文件,下面我们着重分析这几个 API 对 WebView 安全性的影响。

  • setAllowFileAccess
    WebSetting中的方法setAllowFileAccess(boolean allow),Android中的注释如下:

Enables or disables file access within WebView. File access is enabled by
default. Note that this enables or disables file system access only.
Assets and resources are still accessible using file:///android_asset and
file:///android_res.

这个Api可以设置是否允许WebView使用File协议,Android中默认setAllowFileAccess(true)允许访问,在File域下,能够执行任意JavaScript代码同源策略跨域访问则能够对私有目录文件进行访问, APP嵌入的WebView未对file:///形式的URL做限制,常见泄露:

  • 使用file 域加载的js能够使用同源策略跨域访问导致隐私信息泄露
  • 针对IM类软件会导致聊天信息、联系人等等重要信息泄露
  • 针对浏览器类软件,则更多的是cookie信息泄露
    如果不允许使用 file 协议,则不会存在上述的威胁;

解决方案

对于不需要
setAllowFileAccess(false)来禁止加载file协议类文件

  • setAllowFileAccessFromFileURLs

通过此API可以设置是否允许通过 file url 加载的 Javascript 读取其他的本地文件,这个设置在 JELLY_BEAN(android 4.1) 以前的版本默认是允许,在 JELLY_BEAN 及以后的版本中默认是禁止的。当 AllowFileAccessFromFileURLs 设置为 true 时,对应上面的 attack.html 代码为:

<script>
function loadXMLDoc()
{
    var arm = "file:///etc/hosts";
    var xmlhttp;
    if (window.XMLHttpRequest)
    {
        xmlhttp=new XMLHttpRequest();
    }
    xmlhttp.onreadystatechange=function()
    {
        //alert("status is"+xmlhttp.status);
        if (xmlhttp.readyState==4)
        {
              console.log(xmlhttp.responseText);
        }
    }
    xmlhttp.open("GET",arm);
    xmlhttp.send(null);
}
loadXMLDoc();
</script>

当设置成为 false 时,上述JS的攻击代码执行会导致错误,表示浏览器禁止从 file url 中的 javascript 读取其它本地文件

  • setAllowUniversalAccessFromFileURLs()

通过此 API 可以设置是否允许通过 file url 加载的 Javascript 可以访问其他的源,包括其他的文件和 http,https 等其他的源。这个设置在 JELLY_BEAN 以前的版本默认是允许,在 JELLY_BEAN 及以后的版本中默认是禁止的。如果此设置是允许,则 setAllowFileAccessFromFileURLs 不起做用,此时修改 attack.html 的代码:

<script>
function loadXMLDoc()
{
    var arm = "http://www.so.com";
    var xmlhttp;
    if (window.XMLHttpRequest)
    {
        xmlhttp=new XMLHttpRequest();
    }
    xmlhttp.onreadystatechange=function()
    {
        //alert("status is"+xmlhttp.status);
        if (xmlhttp.readyState==4)
        {
             console.log(xmlhttp.responseText);
        }
    }
    xmlhttp.open("GET",arm);
    xmlhttp.send(null);
}
loadXMLDoc();
</script>

当 AllowFileAccessFromFileURLs 为 true 时,上述 javascript 可以成功读取 http://www.so.com 的内容,但设置为 false 时,上述脚本执行会导致如下错误,表示浏览器禁止从 file url 中的 javascript 访问其他源的资源:

漏洞解决方案

setAllowFileAccess(true);                               //设置为 false 将不能加载本地 html 文件
setAllowFileAccessFromFileURLs(false);
setAllowUniversalAccessFromFileURLs(false);
  • setJavaScriptEnabled

通过此API可以设置是否允许WebView使用 JavaScript,默认是不允许,但很多应用,包括移动浏览器为了让 WebView 执行 http 协议中的 JavaScript,都会主动设置允许 WebView 执行 JavaScript,而又不会对不同的协议区别对待,比较安全的实现是如果加载的 url 是 http 或 https 协议,则启用 JavaScript,如果是其它危险协议,比如是 file 协议,则禁用 JavaScript。

解决方案:

  • 对于不需要file协议的应用,禁用file协议
setAllowFileAccess(false);                              //设置为 false 将不能加载本地 html 文件
setAllowFileAccessFromFileURLs(false);
setAllowUniversalAccessFromFileURLs(false);
  • 对于需要使用file协议的应用,禁止file协议加载javascript
setAllowFileAccess(true);                             //设置为 false 将不能加载本地 html 文件
setAllowFileAccessFromFileURLs(false);
setAllowUniversalAccessFromFileURLs(false);
if (url.startsWith("file://") {
    setJavaScriptEnabled(false);
} else {
    setJavaScriptEnabled(true);
}

参考博客:

https://blog.csdn.net/self_study/article/details/54928371
https://www.jianshu.com/p/3a345d27cd42

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值