1. 程式人生 > >Android JS與WebView互動存在的一些問題

Android JS與WebView互動存在的一些問題

一、背景概述

2013年Android平臺暴露出WebView漏洞。利用該漏洞,攻擊者可以通過存在風險的addJavascriptInterface介面函式提供的擴充套件穿透webkit執行本地Java程式碼,造成惡意程式碼在受害人的手機上執行,並可能進一步執行木馬。
目前,google公司僅對Android4.2及以上系統提供了規避方法,Android4.2以下所有版本尚無官方解決方案。
本文將就上述漏洞提出相應的解決方案。

Android API level 16以及之前的版本存在遠端程式碼執行安全漏洞,該漏洞源於程式沒有正確限制使用WebView.addJavascriptInterface方法,遠端攻擊者可通過使用Java Reflection API利用該漏洞執行任意Java物件的方法,簡單的說就是通過addJavascriptInterface給WebView加入一個JavaScript橋接介面,JavaScript通過呼叫這個介面可以直接操作本地的JAVA介面。
該漏洞公佈的近期,多款Android流行應用曾被曝出高危掛馬漏洞:點選訊息或朋友社群圈中的一條網址時,使用者手機然後就會自動執行被掛馬的程式碼指令,從而導致被安裝惡意扣費軟體、向好友傳送欺詐簡訊、通訊錄和簡訊被竊取以及被遠端控制等嚴重後果。在烏雲漏洞平臺上,包括Android版的微信、QQ、騰訊微博、QQ瀏覽器、快播、百度瀏覽器、金山瀏覽器等大批TOP應用均被曝光同類型的漏洞。

不可避免,由於公司中,修舊並行的架構中,涉及很多的WebView和JS互動的功能實現點。安全部已經發布方案,需要我們修改。最近一直在做這方面的研究。
引用:【http://blog.csdn.net/leehong2005/article/details/11808557#】
使用WebView來展示一個網頁,現在很多應用為了做到服務端可控,很多結果頁都是網頁的,而不是本地實現,這樣做有很多好處,比如介面的改變不需要重新發布新版本,直接在Server端修改就行了。用網頁來展示介面,通常情況下都或多或少都與Java程式碼有互動,比如點選網頁上面的一個按鈕,我們需要知道這個按鈕點選事件,或者我們要呼叫某個方法,讓頁面執行某種動作,為了實現這些互動,我們通常都是使用JS來實現,而WebView已經提供了這樣的方法,具體用法如下:
< mWebView.getSettings().setJavaScriptEnabled(true); mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");>

我們向WebView註冊一個名叫“jsInterface”的物件,然後在JS中可以訪問到jsInterface這個物件,就可以呼叫這個物件的一些方法,最終可以呼叫到Java程式碼中,從而實現了JS與Java程式碼的互動。
我們一起來看看關於addJavascriptInterface方法在Android官網的描述:

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可能導致不安全,因為JS可能包含惡意程式碼。今天我們要說的這個漏洞就是這個,當JS包含惡意程式碼時,它可以幹任何事情。

Java和js互動有以下一些特點:

1.Java 呼叫 js 裡面的函式,速度並不令人滿意,大概一次一兩百毫秒吧,如果要做互動性很強的事情,這種速度會讓人瘋掉的。而反過來就不一樣了, js 去調 java 的方法,速度很快,基本上 40-50 毫秒一次。所以儘量用 js 呼叫 java 方法,而不是 java 去呼叫 js 函式。

2.Java 呼叫 js 的函式,沒有返回值,而 Js 呼叫 java 方法,可以有返回值。返回值可以是基本型別、字串,也可以是物件。如果是字串,有個很討厭的問題,第 3 點我會講的。如果是物件,這個物件會被轉換為 js 的物件,直接可以訪問裡面的方法。但是我不推薦 java 返回給 js 的是物件,除非是必須。因為 js 收到 java 返回的物件,會產生一些交換物件,而如果這些物件的數量增加到了 500 或 600 以上,程式就會出問題。所以儘量返回基本資料型別或者字串。

3.Js 呼叫 Java 的方法,返回值如果是字串,你會發現這個字串是 native 的,不能對它進行一些修改操作,比如想對它 substr ,取不到。怎麼解決呢?轉成 locale 的。使用 toLocaleString() 函式就可以了。不過這個函式的速度並不快,轉化的字串如果很多,將會很耗費時間。

二、實現方案

1、Android 4.2以上的系統

Android 4.2以上系統,通過在Java的遠端方法上面宣告@JavascriptInterface可以解決WebView漏洞。如下面程式碼:

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

2、Android 4.2以下的系統

若客戶端需要相容支援Android 4.2以下的系統版本,建議使用本方案規避WebView漏洞。本方案分為兩個修改要點,建議對於https和http場景均使用下述方法規避風險。

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

對於Android 4.2以下的系統Google公司官方沒有提供解決方案。為替代addJavascriptInterface方法,可以利用prompt方法傳參以完成java與js的互動。對應java中的onJsPrompt方法的宣告如下:
public boolean onJsPrompt( WebView view, String url, String message, String defaultValue, JsPromptResult result )
通過這個方法,JS能把資訊(文字)傳遞到Java,而Java也能把資訊(文字)傳遞到JS中。

具體實施方法如下:

1)讓JS呼叫一個Javascript方法,在這個方法中呼叫prompt方法,通過prompt把JS中的資訊傳遞過來,這些資訊應該是我們組合成的一段有意義的文字,可能包含:特定標識,引數等。在onJsPrompt方法中,我們去解析傳遞過來的文字,得到約定好的特定標識,引數等,再通過特定標識呼叫指定的java方法,並傳入引數。具體的Java程式碼如下:

final class MyWebChromeClient extends WebChromeClient 
{   
    public boolean onJsPrompt( WebView view, String url, String message, String defaultValue, JsPromptResult result )
    {
        if( message.equals("1") )
          {
          //解析引數defaultValue
        //呼叫java方法並得到結果
           }
           //返回結果
        result.confirm("result");
        return true;
    }
}

2)關於返回值,可以通過result返回回去,這樣就可以把Java中方法的處理結果返回到Js中。
3)在Javascript方法中,通過呼叫prompt方法傳入標識和引數(依次對應onJsPrompt方法中的message、defaultValue引數),以通知java需要使用的方法及對應引數。prompt方法中第一個引數可以傳送約定好的特定方法標識,prompt方法中第二個引數可以傳入對應的引數序列。具體的Javascript程式碼如下:

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

修改點二:移除系統開放的JS介面

對於Android 3.0以上版本,Android系統開放了部分JS介面。因此在這個版本範圍下,儘管客戶端自身沒有使用addJavascriptInterface方法,黑客仍可以透過系統開放的JS介面實施惡意操作。
針對上述風險,客戶端可通過下面的方法移除風險介面。具體實施方法如下:
1)使用removeJavascriptInterface方法移除作業系統開放的"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以上系統版本移除問題介面。
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { dealJavascriptLeak(); }

三、總結

對於https和http協議訪問的頁面,開發過程中須注意棄用存在漏洞的addJavascriptInterface方法,通過使用prompt方法傳參,完成java與js的互動。同時客戶端須移除系統開放的JS介面,全面規避WebView漏洞風險。

詳細修步驟:

【1】讓JS呼叫一個Javascript方法,這個方法中是呼叫prompt方法,通過prompt把JS中的資訊傳遞過來,這些資訊應該是我們組合成的一段有意義的文字,可能包含:特定標識,方法名稱,引數等。在onJsPrompt方法中,我們去解析傳遞過來的文字,得到方法名,引數等,再通過反射機制,呼叫指定的方法,從而呼叫到Java物件的方法。
【2】關於返回值,可以通過prompt返回回去,這樣就可以把Java中方法的處理結果返回到Js中。
【3】我們需要動態生成一段宣告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字串,它包含了方法名,引數,物件名等。
3,當JS呼叫onButtonClick或onImageClick時,就會回撥到Java層中的onJsPrompt方法,我們再解析出方法名,引數,物件名,再反射呼叫方法。
4,window.jsInterface這表示在window上聲明瞭一個Js物件,宣告方法的形式是:方法名:function(引數1,引數2)
5,一些思考
以下是在實現這個解決方案過程中遇到的一些問題和思考:
【1】生成Js方法後,載入這段Js的時機是什麼?
剛開始時在當WebView正常載入URL後去載入Js,但發現會存在問題,如果當WebView跳轉到下一個頁面時,之前載入的Js就可能無效了,所以需要再次載入。這個問題經過嘗試,需要在以下幾個方法中載入Js,它們是WebChromeClient和WebViewClient的方法:
· onLoadResource
· doUpdateVisitedHistory
· onPageStarted
· onPageFinished
· onReceivedTitle
· onProgressChanged
目前測試了這幾個地方,沒什麼問題,這裡我也不能完全確保沒有問題。

【2】需要過濾掉Object類的方法
由於通過反射的形式來得到指定物件的方法,他會把基類的方法也會得到,最頂層的基類就是Object,所以我們為了不把getClass方法注入到Js中,所以我們需要把Object的公有方法過濾掉。這裡嚴格說來,應該有一個需要過濾方法的列表。目前我的實現中,需要過濾的方法有:
"getClass",
"hashCode",
"notify",
"notifyAll",
"equals",
"toString",
"wait",

【3】通過手動loadUrl來載入一段js,這種方式難道js中的物件就不在window中嗎?也就是說,通過遍歷window的物件,不能找到我們通過loadUrl注入的js物件嗎?
關於這個問題,我們的方法是通過Js宣告的,通過loadUrl的形式來注入到頁面中,其實本質相當於把我們這動態生成的這一段Js直接寫在Html頁面中,所以,這些Js中的window中雖然包含了我們宣告的物件,但是他們並不是Java物件,他們是通過Js語法宣告的,所以不存在getClass之類的方法。本質上他們是Js物件。

【4】在Android 3.0以下,系統自己添加了一個叫searchBoxJavaBridge_的Js介面,要解決這個安全問題,我們也需要把這個介面刪除,呼叫removeJavascriptInterface方法。這個searchBoxJavaBridge_好像是跟google的搜尋框相關的。

【5】在實現過程中,我們需要判斷系統版本是否在4.2以下,因為在4.2以上,Android修復了這個安全問題。我們只是需要針對4.2以下的系統作修復。

相關推薦

Android JSWebView互動存在的一些問題

一、背景概述 2013年Android平臺暴露出WebView漏洞。利用該漏洞,攻擊者可以通過存在風險的addJavascriptInterface介面函式提供的擴充套件穿透webkit執行本地Java程式碼,造成惡意程式碼在受害人的手機上執行,並可能進一步執行木馬。 目

Flutter的需要原生互動一些常用庫

轉自: https://github.com/AweiLoveAndroid/Flutter-learning/blob/master/readme/Flutter%E7%9A%84%E9%9C%80%E8%A6%81%E4%B8%8E%E5%8E%9F%E7%94%9F%E4%BA%A4%E4

省市聯動jsphp互動

js 部分程式碼 - ajax <script> function f1(){ // sele1=document.getElementById('a').value var sele1 = $('#a').val(); $.ajax({ t

sqlplus shell互動一些技巧

sqlplus 與shell互動的一些技巧 linux 下 輸入sqlplus 使用者名稱/密碼@例項名 <<! sql語句塊 ! 可以與shell進行互動,從而不適用@符號去呼叫sql檔案 例如 sqlplus / as sysdba <<! sta

以太坊學習(5)利用Web3.js節點互動【1】

利用Web3.js與節點互動  一、環境配置 【寫在最前:本文用到的主要工具:node.js+geth+ web3.js 1.0.0-beta.18】 1、確保已經安裝node.js 個人在debian9上安裝nodejs的經歷比較坎坷,但是據說ubuntu上安裝方便

android java native互動 基礎學習(一)

javap 與javah的用法 javap 的用法: cd 到 class 所在的目錄: javap -classpath . -s Bean(類名) java h的用法一: native 所在的資料夾。ExampleUnitTest 資料夾所在的包

jsapp互動

1. 判斷當前頁面的環境 var u = navigator.userAgent; var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android終端

WebBrowser控制元件中JS原生互動

在wp8中,可以通過監聽WebBrowser控制元件的ScriptNotify方法,來獲取JS對原生的呼叫。當然JS必須呼叫特定的方法:window.external.notify. 然後可以通過呼叫Webbrowser的InvokeScript方法回撥JS,這樣即實現了雙

js後臺互動詳述(入門篇)

很多新手前端在初期學習的時候往往把注意力放在如何編寫頁面,如何編寫效果上,群裡有個朋友問我js是如何與後臺互動的,我簡單的說一下。   首先需要知道兩個東西,一個是客戶端,一個是伺服器,客戶端其實就是我們在上網時候使用的機器,大部分情況下這個客戶端就是我們的電

Android手機vr互動暴風魔鏡3D效果顯示原理

首先講到VR,談談個人體會,半年前看到淘寶上的vr眼鏡盒為了促銷標題圖片都是非常性感的,還有海量你懂得資源。到最近在淘寶搜尋vr暴風魔鏡都正規了,而且銷售量龐大 還有新聞上很多vr的科技前沿資訊可以看出來。vr技術隨時間的流逝正在日益發展成熟,就像曾經的諾基亞到安卓,蘋

Android Studio Unity3d互動。歸納版。

本來想自己整理下,發現有人整理了,直接搬運過來了。備忘。 原址:http://blog.csdn.net/u014230923/article/details/51363556 這次部落格講解 Android Studio 怎麼匯出專案到 Unity。  在這

Android EditText軟鍵盤的一些效果

主要記錄幾個常見功能的實現:1、進入頁面EditText不自動獲取焦點;2、進入頁面自動彈出鍵盤;3、點選其他區域關閉鍵盤;4、軟鍵盤開啟與關閉的工具類 EditText不自動獲取焦點 在外層的父容器上做下簡單的配置就可以了,通過程式碼設定或者xml佈局檔案

Android程式伺服器互動(一)

在公司一個專案中用到了這樣一種網路請求方式,在此記錄學習。 1.java程式碼 /** * 訪問網路改變座位號 */ private void saveSeatNumber() { Controller.g

QMLc++互動一些

這個是轉載的,【lvliang2008】, #include <QtGui/QApplication> #include <QtDeclarative/QDeclarativeView> #inc

JSiOS互動之OC獲取JS內容跳轉到指定控制器實現技巧

前言 之前有不少人問我關於JS與iOS進行互動的問題,也就是,我們怎麼才能從通過獲取JS的內容顯示到指定的控制器中,今天我給大家寫了一個Demo,在這裡互動我們用到了WKWebView而不是UIwebview,至於為什麼會使用它其實在前一章關於WKWebVie

node.jsajax互動之 json jsonp 資料格式問題

將 dataType 從 json 改成 jsonp 之後,新的問題出現了,就是 ajax 無法解析 json 型別的資料。這就很尷尬了,看了好幾篇怎麼解析的問題,都沒看懂。後來終於看懂了。簡而言之就是 dataType 改成 jsonp 的資料格式以後,再傳 json 格式

iOS移動端WebApp的JSNative互動JSOC)

不論是純webApp還是hybrid,js與原生的互動都不可避免,這裡做一個自己的學習記錄吧。js與OC的互動。 這裡就以一個最基礎的web頁面獲取移動端裝置號UUID為例。 JS程式碼如下: var mobilePort; var uuid; var getUuid

[IOS開發]jsWKwebview互動Demo(調取二維碼掃描)

#pragmamark-WKWebDelegate -(void)userContentController:(WKUserContentController*)userContentContr

Android — ActivityService互動之Binder總結

最近在複習Android跨程序呼叫,整理了一下自己對Binder的一些理解,希望能對大家也有所幫助,如有錯誤歡迎指正~ 為了加深理解,希望看完後能自己操練驗證一下,要不真的很容易眼高手低哦 ps:不想細看,可以只看裡面的3張圖片即可~ ^_^ 好了,迴歸

Android開發之Webview中原生JS互動

文章目錄 概述 使用場景 互動方式 Java呼叫JS程式碼 JS呼叫Java程式碼 總結 概述 由於手機硬體資源的快速提升,使得采用混合開發的可能性逐漸成為現實並且流行起來。Android開發中