原文:http://blog.csdn.net/fengling59/article/details/50379522
在過(guò)去的一段時(shí)間里,WebView遠(yuǎn)程代碼執(zhí)行漏洞可以說(shuō)是橫掃了一大批的Android App辙浑,查詢Wooyun平臺(tái)可以得到大致的情況,鑒于很多存在漏洞的App并沒(méi)有披露司志,因此WebVeiw遠(yuǎn)程執(zhí)行代碼漏洞的影響程度會(huì)更大。由于Google Android 系統(tǒng)碎片化程度很高降宅,大量的Android系統(tǒng)無(wú)法得到及時(shí)有效地更新骂远,這個(gè)漏洞目前依然在被利用。
本文從WebView的概念開(kāi)始詳細(xì)介紹了webView漏洞的成因腰根,利用和檢測(cè)方法激才,并在文章的末尾對(duì)此類漏洞進(jìn)行了一些思考和總結(jié)。
根據(jù)Google的文檔额嘿,WebView 就是A View that displays web pages 繼承的結(jié)構(gòu)如下:
從上圖中可以得知瘸恼,WebView 也是一個(gè)View,在Android 中一個(gè)View就可以簡(jiǎn)單地理解為顯示在屏幕上的一個(gè)界面册养,而WebView就是用于展示W(wǎng)eb頁(yè)面的界面东帅。Android的WebView的主要作用有下面兩個(gè):
Activity上顯示在線的網(wǎng)頁(yè)內(nèi)容
WebView可以實(shí)現(xiàn)一個(gè)接受簡(jiǎn)單控制的Web瀏覽器
WebView的實(shí)現(xiàn)發(fā)生了很大的改變,在Android < 4.4 (KitKat)上的WebView是基于Webkit實(shí)現(xiàn)的球拦,而Android >= 4.4 的WebView 則是基于Chrome for Android version 30實(shí)現(xiàn)的靠闭,因此差異十分明顯。
在Android系統(tǒng)中使用WebView是很容易的坎炼,首先需要在layout 中定義WebView節(jié)點(diǎn)愧膀。
在layout中添加了WebView節(jié)點(diǎn)后,在Activity中就可以直接使用了谣光,
打開(kāi)WebView的Activity檩淋,就會(huì)訪問(wèn)index.html頁(yè)面,這就是WebView的基本用法萄金。
二. WebView RCE 相關(guān)的幾個(gè)CVE
進(jìn)幾年和WebView遠(yuǎn)程代碼執(zhí)行相關(guān)的漏洞主要有CVE-2012-6336,CVE-2014-1939,CVE-2014-7224, 這些漏洞中最核心的漏洞是CVE-2012-6336蟀悦,另外兩個(gè)CVE只是發(fā)現(xiàn)了幾個(gè)默認(rèn)存在的接口,下面就具體說(shuō)明這些漏洞的情況氧敢。
Android API 16.0及之前的版本中存在安全漏洞日戈,該漏洞源于程序沒(méi)有正確限制使用WebView.addJavascriptInterface方法。遠(yuǎn)程攻擊者可通過(guò)使用Java Reflection API利用該漏洞執(zhí)行任意Java對(duì)象的方法
Google Android <= 4.1.2 (API level 16) 受到此漏洞的影響福稳。
java/android/webkit/BrowserFrame.java 使用addJavascriptInterface API并創(chuàng)建了SearchBoxImpl類的對(duì)象涎拉。攻擊者可通過(guò)訪問(wèn)searchBoxJavaBridge_接口利用該漏洞執(zhí)行任意Java代碼。
Google Android <= 4.3.1 受到此漏洞的影響
香港理工大學(xué)的研究人員發(fā)現(xiàn)當(dāng)系統(tǒng)輔助功能中的任意一項(xiàng)服務(wù)被開(kāi)啟后的圆,所有由系統(tǒng)提供的WebView都會(huì)被加入兩個(gè)JS objects鼓拧,分別為是accessibility和accessibilityTraversal。惡意攻擊者就可以使用accessibility和accessibilityTraversal這兩個(gè)Java Bridge來(lái)執(zhí)行遠(yuǎn)程攻擊代碼.
Google Android < 4.4 受到此漏洞的影響越妈。
要理解WebView 的遠(yuǎn)程代碼執(zhí)行漏洞首先要理解JAVA的反射機(jī)制(Java Reflection)
反射是java語(yǔ)言提供的一種機(jī)制季俩,使Java程序可以在運(yùn)行時(shí)檢查類、接口梅掠、方法和成員酌住,而不需要在編譯的時(shí)候知道類的名字和方法等細(xì)節(jié)信息。
JAVA反射機(jī)制是在運(yùn)行狀態(tài)中阎抒,對(duì)于任意一個(gè)類酪我,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為java語(yǔ)言的反射機(jī)制且叁。
為了使用Java Reflection都哭,我們首先需要了解獲得Class Object的方法,一般的情況下有下面幾種方法逞带。
Classc1=Test.class;
Classc2=Class.forName(“com.reflection.Test”);
Classc3=newTest().getClass();
得到了Class object 后就可以得到非常強(qiáng)大的能力欺矫,Class Object是Reflection API 中的核心,一般常用的方法有下面幾個(gè):
– getName()
– getFields()
– getDeclaredFields()
– getMethods()
為了更好地理解展氓,參考下面的幾個(gè)比較典型的例子
4.1.1 執(zhí)行Private 方法
packageReflect;
importjava.lang.reflect.Method;
classDemo{
privatevoida1(){
System.out.println("I am a1");
}
publicvoida2(){
System.out.println("I am a2");
}
}
classhello{
publicstaticvoidmain(String[]args){
Demodemo=newDemo();
ClassmObjectClass=demo.getClass();
System.out.println(mObjectClass.getName());
Method[]methods=mObjectClass.getDeclaredMethods();
for(Methodmethod:methods){
System.out.println("method = "+method.getName());
}
try{
Objecto=mObjectClass.newInstance();
methods[0].setAccessible(true);
methods[0].invoke(o);
}catch(Throwablee){
}
}
}
>javac-d.Reflect/hello.java
>javaReflect.hello
運(yùn)行結(jié)果:
Reflect.Demo
method=a1
method=a2
Iama1
利用反射的方法穆趴,我們已經(jīng)成功調(diào)用了Demo的private a1 方法。
4.1.2 執(zhí)行命令
packageReflect;
importjava.lang.reflect.Method;
classDemo{
publicvoida1(){
}
publicvoida2(){
}
}
classhello{
publicstaticvoidmain(String[]args){
Demodemo=newDemo();
ClassmObjectClass=demo.getClass();
System.out.println(mObjectClass.getName());
Method[]methods=mObjectClass.getMethods();
for(Methodmethod:methods){
System.out.println("method = "+method.getName());
}
try{
Classc=mObjectClass.forName("java.lang.Runtime");
Methodm=c.getMethod("getRuntime",null);
m.setAccessible(true);
Objectobj=m.invoke(null,null);
Classc2=obj.getClass();
String[]array={"/bin/sh","-c","id > /tmp/id"};
Methodn=c2.getMethod("exec",array.getClass());
n.invoke(obj,newObject[]{array});
}catch(Throwablee){
System.out.println(e.toString());
}
}
}
執(zhí)行上面的java 代碼遇汞,會(huì)將 id 命令的結(jié)果寫(xiě)入 /tmp/id 文件未妹,這個(gè)代碼其和WebView漏洞的實(shí)際情況已經(jīng)很接近了。
4.2 WebView的addJavascriptInterface 方法
接下來(lái)我們來(lái)看看WebView漏洞的實(shí)際情況勺疼,Android 官方網(wǎng)站對(duì)addJavascriptInterface的介紹如下:
publicvoidaddJavascriptInterface(Objectobject,Stringname)
AddedinAPIlevel1
InjectsthesuppliedJavaobjectintothisWebView.Theobjectisinjected
intotheJavaScriptcontextofthemainframe,usingthesuppliedname.
ThisallowstheJavaobject'smethodstobeaccessedfromJavaScript.
ForapplicationstargetedtoAPIlevelJELLY_BEAN_MR1andabove,
onlypublicmethodsthatareannotatedwithJavascriptInterfacecanbe
accessedfromJavaScript.ForapplicationstargetedtoAPIlevel
JELLY_BEANorbelow,allpublicmethods(includingtheinheritedones)
canbeaccessed,seetheimportantsecuritynotebelowforimplications.
NotethatinjectedobjectswillnotappearinJavaScriptuntilthe
pageisnext(re)loaded.Forexample:
classJsObject{
@JavascriptInterface
publicStringtoString(){return"injectedObject";}
}
webView.addJavascriptInterface(newJsObject(),"injectedObject");
webView.loadData("","text/html",null);
webView.loadUrl("javascript:alert(injectedObject.toString())");
從上面的介紹我們可以了解到教寂,addJavascriptInterface往 WebView里注入了一個(gè)Java Object, 而這個(gè)Jave Object 的方法可以被Javascript 訪問(wèn)。之所以提供addJavascriptInterface是為了WebView中的Javascript可以和本地的App通訊执庐,這確實(shí)是一個(gè)很強(qiáng)大的功能酪耕,這么做的好處在于本地App邏輯不變的情況下,不需要升級(jí)App就可以對(duì)程序進(jìn)行更新轨淌,修改相應(yīng)的Web頁(yè)面就可以了迂烁。
但是在Android 的早期版本并沒(méi)有對(duì)可以訪問(wèn)的方法做限制,利用Java 的反射機(jī)制递鹉,可以調(diào)用任意對(duì)象的任意方法盟步,這就是WebView漏洞的根本成因。
使用受漏洞影響的WebView訪問(wèn)包含下面腳本的頁(yè)面就會(huì)執(zhí)行相關(guān)的命令躏结。
jsinterface是導(dǎo)出的Java對(duì)象却盘,如果利用成功,獲得的權(quán)限是app的用戶權(quán)限,也就是說(shuō)利用WebView漏洞獲得的權(quán)限是app的權(quán)限黄橘,受限于Android application sandbox, 受限于AndroidManifest.xml中申請(qǐng)的權(quán)限兆览。像上面的語(yǔ)句要成功寫(xiě)入文件,需要AndroidManifest.xml中存在 android.permission.WRITE_EXTERNAL_STORAGE 權(quán)限塞关。
使用WebView訪問(wèn)下面頁(yè)面抬探,輸出的接口名稱則存在漏洞。利用Ajax等方法完全可以對(duì)WebView漏洞進(jìn)行自動(dòng)化測(cè)試帆赢。
在Android 4.1.2 分兩種情況訪問(wèn)測(cè)試頁(yè)面小压,測(cè)試的結(jié)果如下:
(1) 沒(méi)有打開(kāi)任何一個(gè)輔助功能
(2) 打開(kāi)一個(gè)輔助功能
在沒(méi)有打補(bǔ)丁的情況下,已經(jīng)成功地檢測(cè)出CVE-2014-1939和CVE-2014-7224漏洞中所指出的有JS object椰于,這個(gè)漏洞檢測(cè)代碼是有效的怠益。
Google宣布不為小于Android 4.4 的系統(tǒng)提供WebView補(bǔ)丁, 具體可以參見(jiàn)鏈接:
https://community.rapid7.com/community/metasploit/blog/2015/01/11/google-no-longer-provides-patches-for-webview-jelly-bean-and-prior
因此要解決WebView的RCE漏洞,靠譜的方法是升級(jí)Android系統(tǒng)瘾婿,至少要升級(jí)到 API level 17 (Android 4.2), WebView 除了最嚴(yán)重的RCE漏洞溉痢,還有各種SOP漏洞,所以至少要升級(jí)到Android 4.4才能保證安全憋他,小于Android 4.4 Google不提供補(bǔ)丁孩饼。Android 4.4 以后使用以chrome為基礎(chǔ)的WebView。
升級(jí)系統(tǒng)API level 17后竹挡,只有顯示添加 @JavascriptInterface的方法才能被JavaScript調(diào)用镀娶,這樣反射就失去作用了。
建議在使用WebView的代碼刪除出問(wèn)題的接口揪罕,具體代碼如下: removeJavascriptInterface(“accessibility”); removeJavascriptInterface(“accessibilityTraversal”); removeJavascriptInterface(“searchBoxJavaBridge_”);
由于Java 反射所帶來(lái)的安全問(wèn)題并不在少數(shù)梯码,這也給我們發(fā)掘相關(guān)漏洞提供了思路。比如CVE-2010-1871的jboss seam framework RCE好啰。
看看這個(gè)利用代碼是不是非常的相似轩娶。還有前段很火爆的Spring Framework Remote Code with Expression Language Injection,原理都是類似的框往。
真正的新漏洞并不多鳄抒,人們大多數(shù)時(shí)候都在犯同樣的錯(cuò)誤,雖然俗話說(shuō)人們不應(yīng)該在同樣的地方摔倒兩次椰弊,但是在網(wǎng)絡(luò)安全的世界里许溅,人們卻總是在同樣的地方摔倒。
https://developer.chrome.com/multidevice/webview/overview
http://developer.android.com/reference/android/webkit/WebView.html
https://daoyuan14.github.io/news/newattackvector.html
http://droidsploit.baidu.com/view/14100201.html
http://tutorials.jenkov.com/javareflection/index.html
http://javaxden.blogspot.sg/2007/08/hack-any-java-class-using-reflection.html
http://www.programcreek.com/2013/09/java-reflection-tutorial
https://labs.mwrinfosecurity.com/blog/2012/04/23/adventures-with-android-webviews
https://labs.mwrinfosecurity.com/advisories/2013/09/24/webview-addjavascriptinterface-remote-code-execution