你不知道的Android WebView漏洞

前言

  • 如今不少App裏都內置了Web網頁(Hyprid App),好比說不少電商平臺,淘寶、京東、聚划算等等,以下圖

京東首頁
京東首頁


目錄

目錄
目錄


1. 類型

WebView中,主要漏洞有三類:html

  • 任意代碼執行漏洞
  • 密碼明文存儲漏洞
  • 域控制不嚴格漏洞

2. 具體分析

2.1 WebView 任意代碼執行漏洞

出現該漏洞的緣由有三個:java

  • WebView 中 addJavascriptInterface() 接口
  • WebView 內置導出的 searchBoxJavaBridge_對象
  • WebView 內置導出的 accessibilityaccessibilityTraversalObject 對象

2.1.1 addJavascriptInterface 接口引發遠程代碼執行漏洞

A. 漏洞產生緣由

JS調用Android的其中一個方式是經過addJavascriptInterface接口進行對象映射:android

webView.addJavascriptInterface(new JSObject(), "myObj");
// 參數1:Android的本地對象
// 參數2:JS的對象
// 經過對象映射將Android中的本地對象和JS中的對象進行關聯,從而實現JS調用Android的對象和方法複製代碼

因此,漏洞產生緣由是:當JS拿到Android這個對象後,就能夠調用這個Android對象中全部的方法,包括系統類(java.lang.Runtime 類),從而進行任意代碼執行。web

如能夠執行命令獲取本地設備的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 代碼進行漏洞攻擊。
  • 在微信盛行、掃一掃行爲普及的狀況下,該漏洞的危險性很是大

B. 解決方案

B1. Android 4.2版本以後

Google 在Android 4.2 版本中規定對被調用的函數以 @JavascriptInterface進行註解從而避免漏洞攻擊安全

B2. Android 4.2版本以前

在Android 4.2版本以前採用攔截prompt()進行漏洞修復。
具體步驟以下:微信

  • 繼承 WebView ,重寫 addJavascriptInterface 方法,而後在內部本身維護一個對象映射關係的 Map;

    將須要添加的 JS 接口放入該Map中

  • 每次當 WebView 加載頁面前加載一段本地的 JS 代碼,原理是:

    • 讓JS調用一Javascript方法:該方法是經過調用prompt()把JS中的信息(含特定標識,方法名稱等)傳遞到Android端;
    • 在Android的onJsPrompt()中 ,解析傳遞過來的信息,再經過反射機制調用Java對象的方法,這樣實現安全的JS調用Android代碼。

關於Android返回給JS的值:可經過prompt()把Java中方法的處理結果返回到Js中

具體須要加載的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 = {     

     // 聲明方法形式:方法名: function(參數)
            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對象的方法複製代碼

關於該方法的其餘細節

細節1:加載上述JS代碼的時機

  • 因爲當 WebView 跳轉到下一個頁面時,以前加載的 JS 可能已經失效
  • 因此,一般須要在如下方法中加載 JS:
onLoadResource();
doUpdateVisitedHistory();
onPageStarted();
onPageFinished();
onReceivedTitle();
onProgressChanged();複製代碼

細節2:須要過濾掉 Object 類的方法

  • 因爲最終是經過反射獲得Android指定對象的方法,因此同時也會獲得基類的其餘方法(最頂層的基類是 Object類)
  • 爲了避免把 getClass()等方法注入到 JS 中,咱們須要把 Object 的共有方法過濾掉,須要過濾的方法列表以下:
getClass()
hashCode()
notify()
notifyAl()
equals()
toString()
wait()複製代碼

總結

  • 對於Android 4.2之前,須要採用攔截prompt()的方式進行漏洞修復
  • 對於Android 4.2之後,則只須要對被調用的函數以 @JavascriptInterface進行註解
  • 關於 Android 系統佔比,Google公佈的數據:截止 2017 .1 .8 ,Android4.4 之下佔有約15%,因此須要重視。

    具體數據以下:

Paste_Image.png
Paste_Image.png

2.1.2 searchBoxJavaBridge_接口引發遠程代碼執行漏洞

A. 漏洞產生緣由

  • 在Android 3.0如下,Android系統會默認經過searchBoxJavaBridge_的Js接口給 WebView 添加一個JS映射對象:searchBoxJavaBridge_對象
  • 該接口可能被利用,實現遠程任意代碼。

B. 解決方案

刪除searchBoxJavaBridge_接口

// 經過調用該方法刪除接口
removeJavascriptInterface();複製代碼

2.1.3 accessibilityaccessibilityTraversal接口引發遠程代碼執行漏洞

問題分析與解決方案同上,這裏不做過多闡述。

2.2 密碼明文存儲漏洞

2.2.1 問題分析

WebView默認開啓密碼保存功能 :

mWebView.setSavePassword(true)`複製代碼
  • 開啓後,在用戶輸入密碼時,會彈出提示框:詢問用戶是否保存密碼;
  • 若是選擇」是」,密碼會被明文保到 /data/data/com.package.name/databases/webview.db 中,這樣就有被盜取密碼的危險

2.2.2 解決方案

關閉密碼保存提醒

WebSettings.setSavePassword(false)複製代碼

2.3 域控制不嚴格漏洞

2.3.1 問題分析

先看Android裏的 WebViewActivity.java

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);
    }
 }

/**Mainifest.xml**/
// 將該 WebViewActivity 在Mainifest.xml設置exported屬性
// 表示:當前Activity是否能夠被另外一個Application的組件啓動
android:exported="true"複製代碼

即 A 應用能夠經過 B 應用導出的 Activity 讓 B 應用加載一個惡意的 file 協議的 url,從而能夠獲取 B 應用的內部私有文件,從而帶來數據泄露威脅

具體:當其餘應用啓動此 Activity 時, intent 中的 data 直接被看成 url 來加載(假定傳進來的 url 爲 file:///data/local/tmp/attack.html ),其餘 APP 經過使用顯式 ComponentName 或者其餘相似方式就能夠很輕鬆的啓動該 WebViewActivity 並加載惡意url。

下面咱們着重分析WebView中getSettings類的方法對 WebView 安全性的影響:

  • setAllowFileAccess()
  • setAllowFileAccessFromFileURLs()
  • setAllowUniversalAccessFromFileURLs()

1. setAllowFileAccess()

// 設置是否容許 WebView 使用 File 協議
webView.getSettings().setAllowFileAccess(true);     
// 默認設置爲true,即容許在 File 域下執行任意 JavaScript 代碼複製代碼

使用 file 域加載的 js代碼可以使用進行同源策略跨域訪問,從而致使隱私信息泄露

  1. 同源策略跨域訪問:對私有目錄文件進行訪問
  2. 針對 IM 類產品,泄露的是聊天信息、聯繫人等等
  3. 針對瀏覽器類軟件,泄露的是cookie 信息泄露。

若是不容許使用 file 協議,則不會存在上述的威脅;

webView.getSettings().setAllowFileAccess(true);複製代碼

但同時也限制了 WebView 的功能,使其不能加載本地的 html 文件,以下圖:

移動版的 Chrome 默認禁止加載 file 協議的文件

Paste_Image.png
Paste_Image.png

解決方案:

  • 對於不須要使用 file 協議的應用,禁用 file 協議;
    setAllowFileAccess(false);複製代碼
  • 對於須要使用 file 協議的應用,禁止 file 協議加載 JavaScript。
setAllowFileAccess(true); 

// 禁止 file 協議加載 JavaScript
if (url.startsWith("file://") {
    setJavaScriptEnabled(false);
} else {
    setJavaScriptEnabled(true);
}複製代碼

2. setAllowFileAccessFromFileURLs()

// 設置是否容許經過 file url 加載的 Js代碼讀取其餘的本地文件
webView.getSettings().setAllowFileAccessFromFileURLs(true);
// 在Android 4.1前默認容許
// 在Android 4.1後默認禁止複製代碼

AllowFileAccessFromFileURLs()設置爲 true 時,攻擊者的JS代碼爲:

// 經過該代碼可成功讀取 /etc/hosts 的內容數據複製代碼

解決方案:設置setAllowFileAccessFromFileURLs(false);

當設置成爲 false 時,上述JS的攻擊代碼執行會致使錯誤,表示瀏覽器禁止從 file url 中的 javascript 讀取其它本地文件。

3. setAllowUniversalAccessFromFileURLs()

// 設置是否容許經過 file url 加載的 Javascript 能夠訪問其餘的源(包括http、https等源)
webView.getSettings().setAllowUniversalAccessFromFileURLs(true);

// 在Android 4.1前默認容許(setAllowFileAccessFromFileURLs()不起做用)
// 在Android 4.1後默認禁止複製代碼

AllowFileAccessFromFileURLs()被設置成true時,攻擊者的JS代碼是:

// 經過該代碼可成功讀取 http://www.so.com 的內容
複製代碼

解決方案:設置setAllowUniversalAccessFromFileURLs(false);

4. setJavaScriptEnabled()

// 設置是否容許 WebView 使用 JavaScript(默認是不容許)
webView.getSettings().setJavaScriptEnabled(true);  

// 但不少應用(包括移動瀏覽器)爲了讓 WebView 執行 http 協議中的 JavaScript,都會主動設置爲true,不區別對待是很是危險的。複製代碼

即便把setAllowFileAccessFromFileURLs()setAllowUniversalAccessFromFileURLs()都設置爲 false,經過 file URL 加載的 javascript 仍然有方法訪問其餘的本地文件:符號連接跨源攻擊

前提是容許 file URL 執行 javascript,即webView.getSettings().setJavaScriptEnabled(true);

這一攻擊能奏效的緣由是:經過 javascript 的延時執行和將當前文件替換成指向其它文件的軟連接就能夠讀取到被符號連接所指的文件。具體攻擊步驟:

  1. 把惡意的 js 代碼輸出到攻擊應用的目錄下,隨機命名爲 xx.html,修改該目錄的權限;
  2. 修改後休眠 1s,讓文件操做完成;
  3. 完成後經過系統的 Chrome 應用去打開該 xx.html 文件
  4. 等待 4s 讓 Chrome 加載完成該 html,最後將該 html 刪除,而且使用 ln -s 命令爲 Chrome 的 Cookie 文件建立軟鏈接

    注:在該命令執行前 xx.html 是不存在的;執行完這條命令以後,就生成了這個文件,而且將 Cookie 文件連接到了 xx.html 上。

因而就可經過連接來訪問 Chrome 的 Cookie

  1. Google 沒有進行修復,只是讓Chrome 最新版本默認禁用 file 協議,因此這一漏洞在最新版的 Chrome 中並不存在
  2. 可是,在平常大量使用 WebView 的App和瀏覽器,都有可能受到此漏洞的影響。經過利用此漏洞,容易出現數據泄露的危險

若是是 file 協議,禁用 javascript 能夠很大程度上減少跨源漏洞對 WebView 的威脅。

  1. 但並不能徹底杜絕跨源文件泄露。
  2. 例:應用實現了下載功能,對於沒法加載的頁面,會自動下載到 sd 卡中;因爲 sd 卡中的文件全部應用均可以訪問,因而能夠經過構造一個 file URL 指向被攻擊應用的私有文件,而後用此 URL 啓動被攻擊應用的 WebActivity,這樣因爲該 WebActivity 沒法加載該文件,就會將該文件下載到 sd 卡下面,而後就能夠從 sd 卡上讀取這個文件了

最終解決方案

  • 對於不須要使用 file 協議的應用,禁用 file 協議;

    // 禁用 file 協議;
    setAllowFileAccess(false); 
    setAllowFileAccessFromFileURLs(false);
    setAllowUniversalAccessFromFileURLs(false);複製代碼
  • 對於須要使用 file 協議的應用,禁止 file 協議加載 JavaScript。

// 須要使用 file 協議
setAllowFileAccess(true); 
setAllowFileAccessFromFileURLs(false);
setAllowUniversalAccessFromFileURLs(false);

// 禁止 file 協議加載 JavaScript
if (url.startsWith("file://") {
    setJavaScriptEnabled(false);
} else {
    setJavaScriptEnabled(true);
}複製代碼

3. 總結


請點贊!由於大家的贊同/鼓勵是我寫做的最大動力!

相關文章
相關標籤/搜索