WebView(三)—— WebView使用漏洞

WebView使用漏洞

WebView中,主要漏洞有三类:

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

1 任意代码执行漏洞

JS调用Android代码是通过addJavascriptInterface接口进行对象映射。

1.1 漏洞产生的原因
// java代码
public class AndroidJS extends Object {

    @JavascriptInterface
    public void hello(String msg) {
        System.out.println("JS调用了Android的hello方法");
    }
}

webView.addJavascriptInterface(new AndroidJS(), "test");

// JS代码
function callAndroid(){
  test.hello("js调用了android中的hello方法");
}

参数1Android的本地对象 参数2JS的对象。通过对象映射将Android中的本地对象和JS中的对象进行关联,从而实现JS调用Android的对象和方法。

漏洞产生原因是:当JS拿到Android这个对象后,就可以调用这个Android对象中所有的方法,包括系统类(java.lang.Runtime类),从而进行任意代码执行。如可以执行命令获取本地设备的SD卡中的文件等信息从而造成信息泄露

具体获取系统类的描述(结合Java反射机制):Android中的对象有一公共的方法——getClass(),该方法可以获取到当前类类型Class,该类有一关键的方法——Class.forName,该方法可以加载一个类(可加载java.lang.Runtime类),而该类是可以执行本地命令的。

以下是攻击的JS核心代码:

function execute(cmdArgs) {  
  // 步骤1:遍历window对象,目的是为了找到包含getClass()的对象,因为Android映射的JS对象在window中,所以肯定会遍历到
  for (var obj in window) {  
    if ("getClass" in window[obj]) {  

      // 步骤2:利用反射调用forName方法得到Runtime类对象
      alert(obj);          
      return  window[obj].getClass().forName("java.lang.Runtime")  

      // 步骤3:以后就可以调用静态方法来执行一些命令,比如访问文件的命令
      getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);  
      
      // 从执行命令后返回的输入流中得到字符串,有很严重暴露隐私的危险
      // 如执行完访问文件的命令之后,就可以得到文件名的信息了

    }  
  }  
}   

当一些APP通过扫描二维码打开一个外部网页时,攻击者就可以执行这段JS代码进行漏洞攻击。

1.2 解决方案

Android 4.2版本之后,GoogleAndroid 4.2版本中规定对被调用的函数以@JavascriptInterface进行注解从而避免漏洞攻击。

Android 4.2版本之前,采用拦截prompt()进行漏洞修复。 具体如下:

每次当WebView加载页面前加载一段本地的JS代码,原理是:

  • JS调用一Javascript方法:该方法是通过调用promptJS中的信息(含特定标识,方法名称等)传递到Android端;
  • AndroidonJsPrompt中 ,解析传递过来的信息,再通过反射机制调用Java对象的方法,这样实现安全的JS调用Android代码;(关于Android返回给JS的值,可通过promptJava中方法的处理结果返回到JS中)
javascript:(function JsAddJavascriptInterface_() {  
  // window.jsInterface表示在window上声明了一个Js对象,jsInterface = 注册的对象名
  // 它注册了两个方法,onButtonClick(arg0)和onImageClick(arg0, arg1, arg2),如果有返回值,就添加上return
  if (typeof(window.jsInterface)!='undefined') {      
    console.log('window.jsInterface_js_interface_name is exist!!');
  } else {  
    window.jsInterface = {     

      onButtonClick:function(arg0) {   
        // prompt()返回约定的字符串,该字符串可自己定义
        // 包含特定的标识符MyApp和JSON字符串(方法名,参数,对象名等)    
        return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}));  
      },  

      onImageClick:function(arg0,arg1,arg2) {   
        return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}));  
      },  
    };  
  }  
})()

// 当JS调用onButtonClick或onImageClick时,就会回调到Android中的onJsPrompt,解析出方法名,参数,对象名,再通过反射机制调用Java对象的方法

2 密码明文存储漏洞

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

关闭密码保存提醒:webSettings.setSavePassword(false)

3 域控制不严格漏洞

如下代码:

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 i = getIntent();
    String url = i.getData().toString(); //url = file:///data/local/tmp/attack.html 
    webView.loadUrl(url);
  }
}

在清单文件中将WebViewActivity 设置android:exported = "true"属性,表示当前Activity是否可以被另一个Application的组件启动。即A应用可以通过B应用导出的ActivityB应用加载一个恶意的file协议的url,从而可以获取B应用的内部私有文件,从而带来数据泄露威胁。

当其他应用启动可以允许外部调用的Activity时, intent中的data直接被当作url 来加载(假定传进来的urlfile:///data/local/tmp/attack.html),其它APP通过使用显式ComponentName或者其他类似方式就可以很轻松的启动该 WebViewActivity并加载恶意url

对于不需要使用file协议的应用,禁用file协议:

setAllowFileAccess(false);

对于需要使用file协议的应用,禁止file协议加载JavaScript:

setAllowFileAccess(true); 

// 禁止file协议加载 JavaScript
if (url.startsWith("file://") {
  setJavaScriptEnabled(false);
} else {
  setJavaScriptEnabled(true);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值