一嗤无、背景概述
2013年Android平臺(tái)暴露出WebView漏洞杰妓。利用該漏洞哀蘑,攻擊者可以通過存在風(fēng)險(xiǎn)的addJavascriptInterface接口函數(shù)提供的擴(kuò)展穿透webkit執(zhí)行本地Java代碼,造成惡意代碼在受害人的手機(jī)上執(zhí)行阳仔,并可能進(jìn)一步執(zhí)行木馬攒霹。
目前怯疤,google公司僅對(duì)Android4.2及以上系統(tǒng)提供了規(guī)避方法,Android4.2以下所有版本尚無官方解決方案催束。
本文將就上述漏洞提出相應(yīng)的解決方案集峦。
Android API level 16以及之前的版本存在遠(yuǎn)程代碼執(zhí)行安全漏洞,該漏洞源于程序沒有正確限制使用WebView.addJavascriptInterface方法抠刺,遠(yuǎn)程攻擊者可通過使用Java Reflection API利用該漏洞執(zhí)行任意Java對(duì)象的方法塔淤,簡(jiǎn)單的說就是通過addJavascriptInterface給WebView加入一個(gè)JavaScript橋接接口,JavaScript通過調(diào)用這個(gè)接口可以直接操作本地的JAVA接口速妖。
該漏洞公布的近期高蜂,多款A(yù)ndroid流行應(yīng)用曾被曝出高危掛馬漏洞:點(diǎn)擊消息或朋友社區(qū)圈中的一條網(wǎng)址時(shí),用戶手機(jī)然后就會(huì)自動(dòng)執(zhí)行被掛馬的代碼指令罕容,從而導(dǎo)致被安裝惡意扣費(fèi)軟件备恤、向好友發(fā)送欺詐短信、通訊錄和短信被竊取以及被遠(yuǎn)程控制等嚴(yán)重后果锦秒。在烏云漏洞平臺(tái)上露泊,包括Android版的微信、QQ旅择、騰訊微博惭笑、QQ瀏覽器、快播生真、百度瀏覽器沉噩、金山瀏覽器等大批TOP應(yīng)用均被曝光同類型的漏洞。
不可避免柱蟀,由于公司中川蒙,修舊并行的架構(gòu)中,涉及很多的WebView和JS交互的功能實(shí)現(xiàn)點(diǎn)产弹。安全部已經(jīng)發(fā)布方案派歌,需要我們修改。最近一直在做這方面的研究痰哨。
引用:【http://blog.csdn.net/leehong2005/article/details/11808557#】
使用WebView來展示一個(gè)網(wǎng)頁胶果,現(xiàn)在很多應(yīng)用為了做到服務(wù)端可控,很多結(jié)果頁都是網(wǎng)頁的斤斧,而不是本地實(shí)現(xiàn)早抠,這樣做有很多好處,比如界面的改變不需要重新發(fā)布新版本撬讽,直接在Server端修改就行了蕊连。用網(wǎng)頁來展示界面,通常情況下都或多或少都與Java代碼有交互游昼,比如點(diǎn)擊網(wǎng)頁上面的一個(gè)按鈕甘苍,我們需要知道這個(gè)按鈕點(diǎn)擊事件,或者我們要調(diào)用某個(gè)方法烘豌,讓頁面執(zhí)行某種動(dòng)作载庭,為了實(shí)現(xiàn)這些交互,我們通常都是使用JS來實(shí)現(xiàn)廊佩,而WebView已經(jīng)提供了這樣的方法囚聚,具體用法如下:
<? ? mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");>
我們向WebView注冊(cè)一個(gè)名叫“jsInterface”的對(duì)象,然后在JS中可以訪問到j(luò)sInterface這個(gè)對(duì)象标锄,就可以調(diào)用這個(gè)對(duì)象的一些方法顽铸,最終可以調(diào)用到Java代碼中,從而實(shí)現(xiàn)了JS與Java代碼的交互料皇。
我們一起來看看關(guān)于addJavascriptInterface方法在Android官網(wǎng)的描述:
This method can be used to allow JavaScript to control the host application. This is a powerful feature, but also presents a security risk for applications targeted to API levelJELLY_BEAN
or below, because JavaScript could use reflection to access an injected object's public fields. Use of this method in a WebView containing untrusted content could allow an attacker to manipulate the host application in unintended ways, executing Java code with the permissions of the host application. Use extreme care when using this method in a WebView which could contain untrusted content.
JavaScript interacts with Java object on a private, background thread of this WebView. Care is therefore required to maintain thread safety.
The Java object's fields are not accessible.
簡(jiǎn)單地說谓松,就是用addJavascriptInterface可能導(dǎo)致不安全,因?yàn)镴S可能包含惡意代碼践剂。今天我們要說的這個(gè)漏洞就是這個(gè)毒返,當(dāng)JS包含惡意代碼時(shí),它可以干任何事情舷手。
二拧簸、實(shí)現(xiàn)方案
1、Android 4.2以上的系統(tǒng)
Android 4.2以上系統(tǒng)男窟,通過在Java的遠(yuǎn)程方法上面聲明@JavascriptInterface可以解決WebView漏洞盆赤。如下面代碼:
classJsObject{@JavascriptInterfacepublicStringtoString(){return"injectedObject"; }? ? ? ? ? }
2、Android 4.2以下的系統(tǒng)
若客戶端需要兼容支持Android 4.2以下的系統(tǒng)版本歉眷,建議使用本方案規(guī)避WebView漏洞牺六。本方案分為兩個(gè)修改要點(diǎn),建議對(duì)于https和http場(chǎng)景均使用下述方法規(guī)避風(fēng)險(xiǎn)汗捡。
修改點(diǎn)一:使用安全方法替代addJavascriptInterface
對(duì)于Android 4.2以下的系統(tǒng)Google公司官方?jīng)]有提供解決方案淑际。為替代addJavascriptInterface方法畏纲,可以利用prompt方法傳參以完成java與js的交互。對(duì)應(yīng)java中的onJsPrompt方法的聲明如下:
public boolean onJsPrompt( WebView view, String url, String message, String defaultValue, JsPromptResult result )
通過這個(gè)方法春缕,JS能把信息(文本)傳遞到Java盗胀,而Java也能把信息(文本)傳遞到JS中。
具體實(shí)施方法如下:
1)讓JS調(diào)用一個(gè)Javascript方法锄贼,在這個(gè)方法中調(diào)用prompt方法票灰,通過prompt把JS中的信息傳遞過來,這些信息應(yīng)該是我們組合成的一段有意義的文本宅荤,可能包含:特定標(biāo)識(shí)屑迂,參數(shù)等。在onJsPrompt方法中冯键,我們?nèi)ソ馕鰝鬟f過來的文本惹盼,得到約定好的特定標(biāo)識(shí),參數(shù)等惫确,再通過特定標(biāo)識(shí)調(diào)用指定的java方法逻锐,并傳入?yún)?shù)。具體的Java代碼如下:
finalclassMyWebChromeClientextendsWebChromeClient{? ? ? public boolean onJsPrompt(WebViewview,Stringurl,Stringmessage,StringdefaultValue,JsPromptResultresult )? ? {if( message.equals("1") )? ? ? ? ? {//解析參數(shù)defaultValue//調(diào)用java方法并得到結(jié)果}//返回結(jié)果result.confirm("result");returntrue;? ? }}
2)關(guān)于返回值雕薪,可以通過result返回回去昧诱,這樣就可以把Java中方法的處理結(jié)果返回到Js中。
3)在Javascript方法中所袁,通過調(diào)用prompt方法傳入標(biāo)識(shí)和參數(shù)(依次對(duì)應(yīng)onJsPrompt方法中的message盏档、defaultValue參數(shù)),以通知java需要使用的方法及對(duì)應(yīng)參數(shù)燥爷。prompt方法中第一個(gè)參數(shù)可以傳送約定好的特定方法標(biāo)識(shí)蜈亩,prompt方法中第二個(gè)參數(shù)可以傳入對(duì)應(yīng)的參數(shù)序列。具體的Javascript代碼如下:
functionshowHtmlcallJava(){varret = prompt("1","param1;param2");//ret值即為java傳回的”result”//根據(jù)返回內(nèi)容作相應(yīng)處理}
修改點(diǎn)二:移除系統(tǒng)開放的JS接口
對(duì)于Android 3.0以上版本前翎,Android系統(tǒng)開放了部分JS接口稚配。因此在這個(gè)版本范圍下,盡管客戶端自身沒有使用addJavascriptInterface方法港华,黑客仍可以透過系統(tǒng)開放的JS接口實(shí)施惡意操作道川。
針對(duì)上述風(fēng)險(xiǎn),客戶端可通過下面的方法移除風(fēng)險(xiǎn)接口立宜。具體實(shí)施方法如下:
1)使用removeJavascriptInterface方法移除操作系統(tǒng)開放的"searchBoxJavaBridge_"冒萄、"accessibility"、"accessibilityTraversal"接口橙数。由于removeJavascriptInterface方法只在Android API 11以上版本支持尊流,因此若客戶端需要支持Android API 11以下版本,需要在使用該方法時(shí)聲明目標(biāo)API灯帮。
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void dealJavascriptLeak() {
mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
mWebView.removeJavascriptInterface("accessibility");
mWebView.removeJavascriptInterface("accessibilityTraversal");
}
2)針對(duì)Android3.0以上系統(tǒng)版本移除問題接口崖技。
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
dealJavascriptLeak();
}
三逻住、總結(jié)
對(duì)于https和http協(xié)議訪問的頁面,開發(fā)過程中須注意棄用存在漏洞的addJavascriptInterface方法迎献,通過使用prompt方法傳參瞎访,完成java與js的交互。同時(shí)客戶端須移除系統(tǒng)開放的JS接口忿晕,全面規(guī)避WebView漏洞風(fēng)險(xiǎn)装诡。
詳細(xì)修步驟:
【1】讓JS調(diào)用一個(gè)Javascript方法银受,這個(gè)方法中是調(diào)用prompt方法践盼,通過prompt把JS中的信息傳遞過來,這些信息應(yīng)該是我們組合成的一段有意義的文本宾巍,可能包含:特定標(biāo)識(shí)咕幻,方法名稱,參數(shù)等顶霞。在onJsPrompt方法中肄程,我們?nèi)ソ馕鰝鬟f過來的文本,得到方法名选浑,參數(shù)等蓝厌,再通過反射機(jī)制,調(diào)用指定的方法古徒,從而調(diào)用到Java對(duì)象的方法拓提。
【2】關(guān)于返回值,可以通過prompt返回回去隧膘,這樣就可以把Java中方法的處理結(jié)果返回到Js中代态。
【3】我們需要?jiǎng)討B(tài)生成一段聲明Javascript方法的JS腳本,通過loadUrl來加載它疹吃,從而注冊(cè)到html頁面中蹦疑,具體的代碼如下:
javascript:(functionJsAddJavascriptInterface_(){if(typeof(window.jsInterface)!='undefined') {console.log('window.jsInterface_js_interface_name is exist!!');}else{window.jsInterface = {? ? ? ? ? ? ? ? onButtonClick:function(arg0){returnprompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}));? ? ? ? },? ? ? ? onImageClick:function(arg0,arg1,arg2){? prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}));? ? ? ? },? ? };? ? }? }? ? ? ? )()
說明:
1,上面代碼中的jsInterface就是要注冊(cè)的對(duì)象名萨驶,它注冊(cè)了兩個(gè)方法歉摧,onButtonClick(arg0)和onImageClick(arg0, arg1, arg2),如果有返回值腔呜,就添加上return判莉。
2,prompt中是我們約定的字符串育谬,它包含特定的標(biāo)識(shí)符MyApp:券盅,后面包含了一串JSON字符串,它包含了方法名膛檀,參數(shù)锰镀,對(duì)象名等娘侍。
3,當(dāng)JS調(diào)用onButtonClick或onImageClick時(shí)泳炉,就會(huì)回調(diào)到Java層中的onJsPrompt方法,我們?cè)俳馕龀龇椒ǘ欤瑓?shù)氧腰,對(duì)象名,再反射調(diào)用方法古拴。
4黄痪,window.jsInterface這表示在window上聲明了一個(gè)Js對(duì)象桅打,聲明方法的形式是:方法名:function(參數(shù)1,參數(shù)2)
5遭铺,一些思考
以下是在實(shí)現(xiàn)這個(gè)解決方案過程中遇到的一些問題和思考:
【1】生成Js方法后,加載這段Js的時(shí)機(jī)是什么崇众?
剛開始時(shí)在當(dāng)WebView正常加載URL后去加載Js掂僵,但發(fā)現(xiàn)會(huì)存在問題,如果當(dāng)WebView跳轉(zhuǎn)到下一個(gè)頁面時(shí)顷歌,之前加載的Js就可能無效了锰蓬,所以需要再次加載。這個(gè)問題經(jīng)過嘗試眯漩,需要在以下幾個(gè)方法中加載Js芹扭,它們是WebChromeClient和WebViewClient的方法:
· onLoadResource
· doUpdateVisitedHistory
· onPageStarted
· onPageFinished
· onReceivedTitle
· onProgressChanged
目前測(cè)試了這幾個(gè)地方,沒什么問題赦抖,這里我也不能完全確保沒有問題舱卡。
【2】需要過濾掉Object類的方法
由于通過反射的形式來得到指定對(duì)象的方法,他會(huì)把基類的方法也會(huì)得到队萤,最頂層的基類就是Object轮锥,所以我們?yōu)榱瞬话裧etClass方法注入到Js中,所以我們需要把Object的公有方法過濾掉要尔。這里嚴(yán)格說來舍杜,應(yīng)該有一個(gè)需要過濾方法的列表新娜。目前我的實(shí)現(xiàn)中,需要過濾的方法有:
"getClass",
"hashCode",
"notify",
"notifyAll",
"equals",
"toString",
"wait",
【3】通過手動(dòng)loadUrl來加載一段js既绩,這種方式難道js中的對(duì)象就不在window中嗎概龄?也就是說,通過遍歷window的對(duì)象饲握,不能找到我們通過loadUrl注入的js對(duì)象嗎私杜?
關(guān)于這個(gè)問題,我們的方法是通過Js聲明的救欧,通過loadUrl的形式來注入到頁面中衰粹,其實(shí)本質(zhì)相當(dāng)于把我們這動(dòng)態(tài)生成的這一段Js直接寫在Html頁面中,所以颜矿,這些Js中的window中雖然包含了我們聲明的對(duì)象寄猩,但是他們并不是Java對(duì)象嫉晶,他們是通過Js語法聲明的骑疆,所以不存在getClass之類的方法。本質(zhì)上他們是Js對(duì)象替废。
【4】在Android 3.0以下箍铭,系統(tǒng)自己添加了一個(gè)叫searchBoxJavaBridge_的Js接口,要解決這個(gè)安全問題椎镣,我們也需要把這個(gè)接口刪除诈火,調(diào)用removeJavascriptInterface方法。這個(gè)searchBoxJavaBridge_好像是跟google的搜索框相關(guān)的状答。
【5】在實(shí)現(xiàn)過程中冷守,我們需要判斷系統(tǒng)版本是否在4.2以下,因?yàn)樵?.2以上惊科,Android修復(fù)了這個(gè)安全問題拍摇。我們只是需要針對(duì)4.2以下的系統(tǒng)作修復(fù)。