JS與WebView交互存在的安全問題

一嗤无、背景概述

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ù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末馆截,一起剝皮案震驚了整個(gè)濱河市充活,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜡娶,老刑警劉巖混卵,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異窖张,居然都是意外死亡幕随,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門宿接,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赘淮,“玉大人枢赔,你說我怎么就攤上這事∮抵” “怎么了踏拜?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)低剔。 經(jīng)常有香客問我速梗,道長(zhǎng),這世上最難降的妖魔是什么襟齿? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任姻锁,我火速辦了婚禮,結(jié)果婚禮上猜欺,老公的妹妹穿的比我還像新娘位隶。我一直安慰自己,他們只是感情好开皿,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布涧黄。 她就那樣靜靜地躺著,像睡著了一般赋荆。 火紅的嫁衣襯著肌膚如雪笋妥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天窄潭,我揣著相機(jī)與錄音春宣,去河邊找鬼。 笑死嫉你,一個(gè)胖子當(dāng)著我的面吹牛月帝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播幽污,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼嚷辅,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了油挥?” 一聲冷哼從身側(cè)響起潦蝇,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎深寥,沒想到半個(gè)月后攘乒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惋鹅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年则酝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡沽讹,死狀恐怖般卑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情爽雄,我是刑警寧澤蝠检,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站挚瘟,受9級(jí)特大地震影響叹谁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乘盖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一焰檩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧订框,春花似錦析苫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至纵揍,卻和暖如春顿乒,著一層夾襖步出監(jiān)牢的瞬間议街,已是汗流浹背泽谨。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留特漩,地道東北人吧雹。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像涂身,于是被迫代替她去往敵國(guó)和親雄卷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容