Android WebView常见的安全漏洞和解决方案

4,877 阅读5分钟

概述

WebView中安全漏洞有三种,分别是:

  • 远程代码执行漏洞
  • 密码明文存储漏洞
  • 域控制不严格漏洞

下面依次分析各漏洞产生的原因以及解决方案

一、远程代码执行漏洞

1、WbView中addJavascriptInterface()接口

产生原因:

Android API level 17以及之前的系统版本,由于程序没有正确限制使用addJavascriptInterface方法,远程攻击者可通过使用Java Reflection API利用该漏洞执行任意Java对象的方法。 通过addJavascriptInterface给WebView加入一个JavaScript桥接接口,JavaScript通过调用这个接口可以直接与本地的Java接口进行交互。就有可能出现手机被安装木马程序、发送扣费短信、通信录和短信被窃取、获取本地设备的SD卡中的文件等信息,从而造成信息泄露,甚至手机被远程控制等安全问题。

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

当JS拿到Android这个对象后,通过Java反射机制,就可以调用这个Android对象中所有的方法,包括系统类(java.lang.Runtime类),从而进行任意代码执行。

Java反射机制:
反射机制其实就是指程序在运行的时候能够获取自身的信息。
如果知道一个类的名称/或者它的一个实例对象, 就能把这个类的所有方法和变量的信息
(方法名,变量名,方法,修饰符,类型,方法参数等等所有信息)找出来。
反射最重要的功能是:在运行时,动态创建类的对象

如何获取Class类
Class c = Class.forName("类的路径"); 
Class c = 类名.class;
Class c = 实例.getClass();

Android中的对象的getClass()可以获取到当前类Class,当前类Class的forName()可加载java.lang.Runtime类,从而得到Runtime类,而Runtime是可以执行本地命令的。

 function execute(cmdArgs)
       {
        for (var obj in window) {
            console.log(obj);
            if ("getClass" in window[obj]) {
                alert(obj);
                return window[obj].getClass().forName("java.lang.Runtime").
                    getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
             }
         }
       } 
      //从执行命令后返回的输入流中得到字符串,
      从而得到文件名的信息,有很严重暴露隐私的危险。
      var p = execute(["ls","/mnt/sdcard/"]);
      document.write(getInputStream2String(p.getInputStream()));

解决方案:

如果一定要使用addJavascriptInterface接口,需使用以下方法:Android4.2以上,允许被JavaScript调用的方法必须以@JavascriptInterface进行注解声明,从而避免漏洞攻击。Android4.2以下,采用setWebChromeClient重新onJsPrompt()拦截prompt()消息进行交互。

2、WebView内置导出的searchBoxJavaBridge_对象和内置导出的accessibility和accessibilityTraversalObject对象

产生原因

在Android 4.4 以下的系统中存在一共三个有远程代码执行漏洞的隐藏接口。分别是位于android/webkit/webview中的“searchBoxJavaBridge”接口和android/webkit/AccessibilityInjector.java中的“accessibility”接口和“accessibilityTraversal”接口。调用此三个接口的APP在开启辅助功能选项中第三方服务的Android系统上将面临远程代码执行漏洞。

解决方案

在创建WebView时使用 webView.removeJavascriptInterface(String name)方法移除searchBoxJavaBridge、accessibility、accessibilityTraversal这三个接口。

webView.removeJavascriptInterface("searchBoxJavaBridge_");
webView.removeJavascriptInterface("accessibility");
webView.removeJavascriptInterface("accessibilityTraversal");

二、密码明文存储漏洞

产生原因

WebView默认开启密码保存功能 :mWebView.setSavePassword(true) 开启后,在用户输入密码时,会弹出提示框:询问用户是否保存密码; 如果选择”是”,密码会被明文保到 /data/data/com.package.name/databases/webview.db 中,这样就有被盗取密码的危险。

解决方案

通过 WebSettings.setSavePassword(false) 关闭密码保存提醒功能,防止明文密码存在本地被盗用。

三、域控制不严格漏洞

产生原因

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().setAllowFileAccess(false);                    (1)
        //webView.getSettings().setAllowFileAccessFromFileURLs(true);         (2)
        //webView.getSettings().setAllowUniversalAccessFromFileURLs(true);    (3)
        
        Intent intent = getIntent();
        String url = intent.getData().toString(); 
        webView.loadUrl(url);
    }
 }

将该WebViewActivity 在Mainifest.xml设置android:exported="true"表示:当前Activity是否可以被另一个Application的组件启动。

例如:

A应用可以通过B应用导出的Activity(android:exported="true"),让B应用加载一个恶意的file 协议的url,从而可以获取B应用的内部私有文件,从而带来数据泄露威胁。

  • 同源策略跨域访问:对私有目录文件进行访问
  • 针对 IM 类产品,泄露的是聊天信息、联系人等等
  • 针对浏览器类软件,泄露的是cookie 信息泄露。

WebView 默认是可以使用 File 协议的,也就是setAllowFileAccess(true)。 所以我们应该是主动设置为 setAllowFileAccess(false),防止加载应用本地文件,移动版的 Chrome 默认禁止加载file协议的文件。

如果不允许使用 file 协议,则不会存在上述的威胁,但同时也限制了WebView的功能,使其不能加载想要加载的本地html文件。

解决方案

对于不需要使用file协议的应用,禁用file协议,setAllowFileAccess(false); 对于需要使用 file 协议的应用,允许file协议加载 JavaScript。

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

// 设置是否允许通过 file url 加载的 Js代码读取其他的本地文件
setAllowFileAccessFromFileURLs(false);

//设置是否允许通过fileurl加载的Javascript可以访问其他任何的源,
也就是说,它包括其他的文件和http,https等其他的源(同源跨域访问)
setAllowUniversalAccessFromFileURLs(false);

if (url.startsWith("file://") {
    setJavaScriptEnabled(false);
} else {
    setJavaScriptEnabled(true);
}

总结

以上就是WebView中三种安全漏洞:任意代码执行漏洞、密码明文存储漏洞、域控制不严格漏洞,一般都出现在低版本里,如果App支持最小版本为4.4,则任意代码执行漏洞就不复存在了。