JS與WebView交互存在的一些問題

一臭杰、背景概述

2013年Android平臺暴露出WebView漏洞猜丹。利用該漏洞,攻擊者可以通過存在風險的addJavascriptInterface接口函數(shù)提供的擴展穿透webkit執(zhí)行本地Java代碼硅卢,造成惡意代碼在受害人的手機上執(zhí)行射窒,并可能進一步執(zhí)行木馬。
目前将塑,google公司僅對Android4.2及以上系統(tǒng)提供了規(guī)避方法脉顿,Android4.2以下所有版本尚無官方解決方案。
本文將就上述漏洞提出相應(yīng)的解決方案点寥。

Android API level 16以及之前的版本存在遠程代碼執(zhí)行安全漏洞艾疟,該漏洞源于程序沒有正確限制使用WebView.addJavascriptInterface方法,遠程攻擊者可通過使用Java Reflection API利用該漏洞執(zhí)行任意Java對象的方法敢辩,簡單的說就是通過addJavascriptInterface給WebView加入一個JavaScript橋接接口蔽莱,JavaScript通過調(diào)用這個接口可以直接操作本地的JAVA接口。
該漏洞公布的近期戚长,多款A(yù)ndroid流行應(yīng)用曾被曝出高危掛馬漏洞:點擊消息或朋友社區(qū)圈中的一條網(wǎng)址時盗冷,用戶手機然后就會自動執(zhí)行被掛馬的代碼指令,從而導(dǎo)致被安裝惡意扣費軟件同廉、向好友發(fā)送欺詐短信仪糖、通訊錄和短信被竊取以及被遠程控制等嚴重后果。在烏云漏洞平臺上迫肖,包括Android版的微信锅劝、QQ、騰訊微博蟆湖、QQ瀏覽器故爵、快播、百度瀏覽器隅津、金山瀏覽器等大批TOP應(yīng)用均被曝光同類型的漏洞诬垂。

不可避免,由于公司中饥瓷,修舊并行的架構(gòu)中剥纷,涉及很多的WebView和JS交互的功能實現(xiàn)點。安全部已經(jīng)發(fā)布方案呢铆,需要我們修改晦鞋。最近一直在做這方面的研究。
引用:【http://blog.csdn.net/leehong2005/article/details/11808557#
使用WebView來展示一個網(wǎng)頁,現(xiàn)在很多應(yīng)用為了做到服務(wù)端可控悠垛,很多結(jié)果頁都是網(wǎng)頁的线定,而不是本地實現(xiàn),這樣做有很多好處确买,比如界面的改變不需要重新發(fā)布新版本斤讥,直接在Server端修改就行了。用網(wǎng)頁來展示界面湾趾,通常情況下都或多或少都與Java代碼有交互芭商,比如點擊網(wǎng)頁上面的一個按鈕,我們需要知道這個按鈕點擊事件搀缠,或者我們要調(diào)用某個方法铛楣,讓頁面執(zhí)行某種動作,為了實現(xiàn)這些交互艺普,我們通常都是使用JS來實現(xiàn)簸州,而WebView已經(jīng)提供了這樣的方法,具體用法如下:
< mWebView.getSettings().setJavaScriptEnabled(true); mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");>

我們向WebView注冊一個名叫“jsInterface”的對象歧譬,然后在JS中可以訪問到j(luò)sInterface這個對象岸浑,就可以調(diào)用這個對象的一些方法,最終可以調(diào)用到Java代碼中瑰步,從而實現(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 level JELLY_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.

簡單地說,就是用addJavascriptInterface可能導(dǎo)致不安全面氓,因為JS可能包含惡意代碼兵钮。今天我們要說的這個漏洞就是這個,當JS包含惡意代碼時舌界,它可以干任何事情。

二泰演、實現(xiàn)方案

1呻拌、Android 4.2以上的系統(tǒng)

Android 4.2以上系統(tǒng),通過在Java的遠程方法上面聲明@JavascriptInterface可以解決WebView漏洞睦焕。如下面代碼:

    class JsObject {  
           @JavascriptInterface  
           public String toString() { return "injectedObject"; }  
        }  

2藐握、Android 4.2以下的系統(tǒng)

若客戶端需要兼容支持Android 4.2以下的系統(tǒng)版本,建議使用本方案規(guī)避WebView漏洞垃喊。本方案分為兩個修改要點猾普,建議對于https和http場景均使用下述方法規(guī)避風險。

修改點一:使用安全方法替代addJavascriptInterface

對于Android 4.2以下的系統(tǒng)Google公司官方?jīng)]有提供解決方案本谜。為替代addJavascriptInterface方法初家,可以利用prompt方法傳參以完成java與js的交互。對應(yīng)java中的onJsPrompt方法的聲明如下:
public boolean onJsPrompt( WebView view, String url, String message, String defaultValue, JsPromptResult result )
通過這個方法,JS能把信息(文本)傳遞到Java溜在,而Java也能把信息(文本)傳遞到JS中陌知。

具體實施方法如下:

1)讓JS調(diào)用一個Javascript方法,在這個方法中調(diào)用prompt方法掖肋,通過prompt把JS中的信息傳遞過來仆葡,這些信息應(yīng)該是我們組合成的一段有意義的文本,可能包含:特定標識志笼,參數(shù)等沿盅。在onJsPrompt方法中,我們?nèi)ソ馕鰝鬟f過來的文本纫溃,得到約定好的特定標識腰涧,參數(shù)等,再通過特定標識調(diào)用指定的java方法皇耗,并傳入?yún)?shù)南窗。具體的Java代碼如下:

final class MyWebChromeClient extends WebChromeClient 
{   
    public boolean onJsPrompt( WebView view, String url, String message, String defaultValue, JsPromptResult result )
    {
        if( message.equals("1") )
          {
          //解析參數(shù)defaultValue
        //調(diào)用java方法并得到結(jié)果
           }
           //返回結(jié)果
        result.confirm("result");
        return true;
    }
}

2)關(guān)于返回值,可以通過result返回回去郎楼,這樣就可以把Java中方法的處理結(jié)果返回到Js中万伤。
3)在Javascript方法中,通過調(diào)用prompt方法傳入標識和參數(shù)(依次對應(yīng)onJsPrompt方法中的message呜袁、defaultValue參數(shù))敌买,以通知java需要使用的方法及對應(yīng)參數(shù)。prompt方法中第一個參數(shù)可以傳送約定好的特定方法標識阶界,prompt方法中第二個參數(shù)可以傳入對應(yīng)的參數(shù)序列虹钮。具體的Javascript代碼如下:

   function showHtmlcallJava()
   {
      var ret = prompt( "1", "param1;param2" );
     //ret值即為java傳回的”result”
     //根據(jù)返回內(nèi)容作相應(yīng)處理
    }

修改點二:移除系統(tǒng)開放的JS接口

對于Android 3.0以上版本,Android系統(tǒng)開放了部分JS接口膘融。因此在這個版本范圍下芙粱,盡管客戶端自身沒有使用addJavascriptInterface方法瓤逼,黑客仍可以透過系統(tǒng)開放的JS接口實施惡意操作椒舵。
針對上述風險,客戶端可通過下面的方法移除風險接口政鼠。具體實施方法如下:
1)使用removeJavascriptInterface方法移除操作系統(tǒng)開放的"searchBoxJavaBridge_"岛都、"accessibility"律姨、"accessibilityTraversal"接口。由于removeJavascriptInterface方法只在Android API 11以上版本支持臼疫,因此若客戶端需要支持Android API 11以下版本择份,需要在使用該方法時聲明目標API。
@TargetApi(Build.VERSION_CODES.HONEYCOMB) private void dealJavascriptLeak() { mWebView.removeJavascriptInterface("searchBoxJavaBridge_"); mWebView.removeJavascriptInterface("accessibility"); mWebView.removeJavascriptInterface("accessibilityTraversal"); }
2)針對Android3.0以上系統(tǒng)版本移除問題接口烫堤。
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { dealJavascriptLeak(); }

三荣赶、總結(jié)

對于https和http協(xié)議訪問的頁面凤价,開發(fā)過程中須注意棄用存在漏洞的addJavascriptInterface方法,通過使用prompt方法傳參讯壶,完成java與js的交互料仗。同時客戶端須移除系統(tǒng)開放的JS接口,全面規(guī)避WebView漏洞風險伏蚊。

詳細修步驟:

【1】讓JS調(diào)用一個Javascript方法立轧,這個方法中是調(diào)用prompt方法,通過prompt把JS中的信息傳遞過來躏吊,這些信息應(yīng)該是我們組合成的一段有意義的文本氛改,可能包含:特定標識,方法名稱比伏,參數(shù)等胜卤。在onJsPrompt方法中,我們?nèi)ソ馕鰝鬟f過來的文本赁项,得到方法名葛躏,參數(shù)等,再通過反射機制悠菜,調(diào)用指定的方法舰攒,從而調(diào)用到Java對象的方法。
【2】關(guān)于返回值悔醋,可以通過prompt返回回去摩窃,這樣就可以把Java中方法的處理結(jié)果返回到Js中。
【3】我們需要動態(tài)生成一段聲明Javascript方法的JS腳本芬骄,通過loadUrl來加載它猾愿,從而注冊到html頁面中,具體的代碼如下:

javascript:(function JsAddJavascriptInterface_(){
if (typeof(window.jsInterface)!='undefined') {    
    console.log('window.jsInterface_js_interface_name is exist!!');} 
else {
    window.jsInterface = {        
        onButtonClick:function(arg0) { 
            return prompt('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就是要注冊的對象名蒂秘,它注冊了兩個方法,onButtonClick(arg0)和onImageClick(arg0, arg1, arg2)淘太,如果有返回值材彪,就添加上return。
2琴儿,prompt中是我們約定的字符串,它包含特定的標識符MyApp:嘁捷,后面包含了一串JSON字符串造成,它包含了方法名,參數(shù)雄嚣,對象名等晒屎。
3喘蟆,當JS調(diào)用onButtonClick或onImageClick時,就會回調(diào)到Java層中的onJsPrompt方法鼓鲁,我們再解析出方法名蕴轨,參數(shù),對象名骇吭,再反射調(diào)用方法橙弱。
4,window.jsInterface這表示在window上聲明了一個Js對象燥狰,聲明方法的形式是:方法名:function(參數(shù)1棘脐,參數(shù)2)
5,一些思考
以下是在實現(xiàn)這個解決方案過程中遇到的一些問題和思考:
【1】生成Js方法后龙致,加載這段Js的時機是什么蛀缝?
剛開始時在當WebView正常加載URL后去加載Js,但發(fā)現(xiàn)會存在問題目代,如果當WebView跳轉(zhuǎn)到下一個頁面時屈梁,之前加載的Js就可能無效了,所以需要再次加載榛了。這個問題經(jīng)過嘗試在讶,需要在以下幾個方法中加載Js,它們是WebChromeClient和WebViewClient的方法:
· onLoadResource
· doUpdateVisitedHistory
· onPageStarted
· onPageFinished
· onReceivedTitle
· onProgressChanged
目前測試了這幾個地方忽冻,沒什么問題真朗,這里我也不能完全確保沒有問題。

【2】需要過濾掉Object類的方法
由于通過反射的形式來得到指定對象的方法僧诚,他會把基類的方法也會得到遮婶,最頂層的基類就是Object,所以我們?yōu)榱瞬话裧etClass方法注入到Js中湖笨,所以我們需要把Object的公有方法過濾掉旗扑。這里嚴格說來,應(yīng)該有一個需要過濾方法的列表慈省。目前我的實現(xiàn)中臀防,需要過濾的方法有:
"getClass",
"hashCode",
"notify",
"notifyAll",
"equals",
"toString",
"wait",

【3】通過手動loadUrl來加載一段js,這種方式難道js中的對象就不在window中嗎边败?也就是說袱衷,通過遍歷window的對象,不能找到我們通過loadUrl注入的js對象嗎笑窜?
關(guān)于這個問題致燥,我們的方法是通過Js聲明的,通過loadUrl的形式來注入到頁面中排截,其實本質(zhì)相當于把我們這動態(tài)生成的這一段Js直接寫在Html頁面中嫌蚤,所以辐益,這些Js中的window中雖然包含了我們聲明的對象,但是他們并不是Java對象脱吱,他們是通過Js語法聲明的智政,所以不存在getClass之類的方法。本質(zhì)上他們是Js對象箱蝠。

【4】在Android 3.0以下续捂,系統(tǒng)自己添加了一個叫searchBoxJavaBridge_的Js接口,要解決這個安全問題抡锈,我們也需要把這個接口刪除疾忍,調(diào)用removeJavascriptInterface方法。這個searchBoxJavaBridge_好像是跟google的搜索框相關(guān)的床三。

【5】在實現(xiàn)過程中一罩,我們需要判斷系統(tǒng)版本是否在4.2以下,因為在4.2以上撇簿,Android修復(fù)了這個安全問題聂渊。我們只是需要針對4.2以下的系統(tǒng)作修復(fù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末四瘫,一起剝皮案震驚了整個濱河市汉嗽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌找蜜,老刑警劉巖饼暑,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異洗做,居然都是意外死亡弓叛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門诚纸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撰筷,“玉大人,你說我怎么就攤上這事畦徘”献眩” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵井辆,是天一觀的道長关筒。 經(jīng)常有香客問我,道長杯缺,這世上最難降的妖魔是什么平委? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮夺谁,結(jié)果婚禮上廉赔,老公的妹妹穿的比我還像新娘。我一直安慰自己匾鸥,他們只是感情好蜡塌,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勿负,像睡著了一般馏艾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奴愉,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天琅摩,我揣著相機與錄音,去河邊找鬼锭硼。 笑死房资,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的檀头。 我是一名探鬼主播轰异,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼暑始!你這毒婦竟也來了搭独?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤廊镜,失蹤者是張志新(化名)和其女友劉穎牙肝,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嗤朴,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡配椭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了播赁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颂郎。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖容为,靈堂內(nèi)的尸體忽然破棺而出乓序,到底是詐尸還是另有隱情,我是刑警寧澤坎背,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布替劈,位于F島的核電站,受9級特大地震影響得滤,放射性物質(zhì)發(fā)生泄漏陨献。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一懂更、第九天 我趴在偏房一處隱蔽的房頂上張望眨业。 院中可真熱鬧急膀,春花似錦、人聲如沸龄捡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽聘殖。三九已至晨雳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奸腺,已是汗流浹背餐禁。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留突照,地道東北人帮非。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像绷旗,于是被迫代替她去往敵國和親喜鼓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

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