一、的漏洞分析
最近在開發過程中遇到一個問題,就是使用的時候,還是需要解決之前系統(4.2之前)導致的一個漏洞,雖然現在這個系統版本用戶很少了,但是也不能忽視,關于這個漏洞,這里就不多做解釋了,可能有的同學早就了解了,本來想寫一篇文章詳細介紹一下,但是網上的知識太多了,而且都很詳細,就沒弄了,這里大致簡單明了的說幾句:
第一、漏洞產生的原因
這個漏洞導致的原因主要是因為中中的JS訪問本地方法的方式存在缺陷,我們做過交互的都知道,中的交互方式是通過的一個方法:ce(new (), "myObj");
第一個參數:本地對象;第二個參數就是JS代碼中需要使用的對象
所以這里看其實就相當于一個映射關系,把中的本地對象和JS中的對象關聯即可。
那么這里就存在這樣的一個問題了,在4.2系統之前,JS中通過對象調用的方法無需任何注解約束,那么就意味著JS中拿到這個對象,就可以調用這個對象中所有的方法,而我們知道中的對象有一個公共的方法()方法,而這個方法可以獲取到當前類類型Class,而這個類型有一個很關鍵的方法就是Class.,這個方法可以加載一個類,這里可以加載java.lang.這個類,而這個類就可以執行本地命令了,那么就會發生危險了,比如這里可以執行命令獲取本地設備的SD卡中的文件等信息,非常危險的。
上面可能說的還是有些同學不太了解,下面就用一段簡單的JS代碼來了解一下:
看到這段JS之后的同學應該好理解了,因為我們本地通過進行了對象映射,那么加載頁面中如果包含這段JS代碼,那么就會存在這個問題,這里先遍歷中所有的對象,然后查找這個對象是否有方法,有的話就在利用反射調用類執行具體命令即可。其實這個漏洞也得力于JS中的語法特性網頁用什么做交互,這里可以看到JS語法非常的靈活。
第二、漏洞修復
當然對于.2之后系統修復了這個漏洞,修復方法也很簡單,加上注解約束:@ 就是只有加上這個注解的方法才會被JS調用,那么我們知道是類中的,肯定沒有這個注解,那么上面的JS代碼肯定執行不到了。就這樣解決了這個漏洞。
還有一個問題,就是系統默認的會給添加一個JS映射對象: 這個對象是.0之后默認加上去的,也就是說通過這個對象也是可以操作的上面的代碼的。
二、三種交互分析分析
說完了,這個漏洞,下面開始說今天的正題了,為什么要先介紹這個漏洞呢?原因就是如果要在4.2以下版本中解決這個漏洞的話就需要借助今天介紹的內容了,首先來看看今天的內容主要是介紹中的JS和本地交互的三種方式:
第一種方式:通過ce方法進行添加對象映射
這種方式不多解釋了,也是中最常用的方式,但是這種方式會存在風險就是上面說到的漏洞問題。
這里定義一個簡單的本地對象,在需要被調用的方法加上約束注解。JS代碼也很簡單:
這種方式的好處在于使用簡單明了,本地和JS的約定也很簡單,就是對象名稱和方法名稱約定好即可,缺點就是存在漏洞問題。
第二種方式:利用接口回調方法攔截url
這種方式其實實現也很簡單,就是我們可以添加回調接口,在ding回調方法中攔截url,然后解析這個url的協議,如果發現是我們約定好的協議就開始解析參數執行具體邏輯:
代碼也很簡單,這個方法可以攔截中加載url的過程,得到對應的url,我們就可以通過這個方法,和網頁JS約定好一個協議,看一下JS代碼:
這個JS代碼執行之后,就會觸發本地的ding方法,然后進行參數解析,調用指定方法。
這個方法是不會存在第一種方法的漏洞問題,但是細心的同學可以發現,這里本地和JS之間的約定有點繁瑣,比如要約定好協議,參數名稱等信息,沒有第一種方式方便。而且最主要的問題是,這個只能主動的調用本地化方法,如果想得到方法的返回值,只能通過的方法去執行JS方法,把返回值傳遞回去:.(":("+res+")");
看到這種方式是非常繁瑣的。在中也是不提倡使用的。
注意:在iOS中沒有像中的第一種方式,他也是為了安全考慮,所以iOS中的交互就是采用的第二種方式,通過攔截url來進行操作的,當時候介紹iOS這部分內容的時候在詳細介紹。
第三種方式:利用回調接口的三個方法攔截消息
這個方法的原理其實和第二種方式差不多,只是攔截的接口方法不一樣:
中的添加接口,可以攔截JS中的幾個提示方法網頁用什么做交互,也就是幾種樣式的對話框,在JS中有三個常用的對話框方法:
1. alert是彈出警告框,在文本里面加入\n就可以換行。
2. 彈出確認框,會返回布爾值,通過這個值可以判斷點擊時確認還是取消。true表示點擊了確認,false表示點擊了取消。
3. 彈出輸入框,點擊確認返回輸入框中的值,點擊取消返回null。
那么這三種對話框都是可以在本地攔截到的,那么第三種方法的原理就是攔截這些方法,得到他們的消息內容,然后解析即可,比如這里我們攔截了方法內容:
本地攔截的方法參數說明:
為什么要攔截方法,因為這個方法可以返回想要的值,而對于alert是無法得到返回值的,只能得到兩個返回值。只有方法可以返回各種類型的值,操作最方便。
然后在這個方法中和第二種方法一樣的原理解析消息內容即可
三、執行結果
下面直接看看上面的三種方式的執行效果:
第一種方式:
第二種方式:
第三種方式:
其中html代碼如下:
四、三種方式總結
好了,到這里我們就介紹完了中的JS和本地交互的三種方式:
第一種方式:是最普遍的用法,方便簡單,但是在4.2系統以下存在漏洞問題
第二種方式:是通過攔截url,解析約定之后的協議調用本地方法,缺點是約束協議比較繁瑣,而且傳回執行之后的返回值比較麻煩。但是不會存在漏洞問題,而這種方式也是iOS中采用的方式。
第三種方式:其實和第二種方式差不多,只是攔截的方法變了,這里攔截的是JS中的三種對話框方法,而這三種對話框方法的區別就在于返回值問題,alert對話框方法沒有返回值,對話框方法只有兩種狀態的返回值,對話框方法可以返回任意類型的返回值。缺點和第二種方法一樣,協議約定比較繁瑣,但是不會存在漏洞問題。
五、4.2以下的漏洞修復
最后在來介紹一下文章中開始介紹的漏洞問題,雖然在4.2之后修復了這個漏洞,但是對于4.2之前的用戶該如何處理這個漏洞呢?這里主要就是需要借助第三種方式了,攔截方法,修復步驟很簡單:
1、我們自己顯示一個的包裝器,重寫他的ce方法,然后在內部自己維護一個對象映射關系Map
2、在加載頁面的方法中構造一段本地JS代碼:
關于這段JS代碼的含義:
1> 上面代碼中的就是要注冊的對象名,它注冊了兩個方法,(arg0)和(arg0, arg1, arg2),如果有返回值,就添加上。
2> 中是我們約定的字符串,它包含特定的標識符MyApp:,后面包含了一串JSON字符串,它包含了方法名,參數,對象名等。
3> 當JS調用或時,就會回調到Java層中的方法,我們再解析出方法名,參數,對象名,再反射調用方法。
4> .這表示在上聲明了一個Js對象,聲明方法的形式是:方法名:(參數1,參數2)
而加載這段JS代碼的時機是什么時候呢?
剛開始時在當正常加載URL后去加載Js,但發現會存在問題,如果當跳轉到下一個頁面時,之前加載的Js就可能無效了,所以需要再次加載。這個問題經過嘗試,需要在以下幾個方法中加載Js,它們是和的方法:,ry,,,,
3、讓JS調用一個方法,這個方法中是調用方法,通過把JS中的信息傳遞過來,這些信息應該是我們組合成的一段有意義的文本,可能包含:特定標識,方法名稱,參數等。在方法中,我們去解析傳遞過來的文本,得到方法名,參數等,再通過反射機制,調用指定的方法,從而調用到Java對象的方法。
4、關于返回值,可以通過返回回去,這樣就可以把Java中方法的處理結果返回到Js中。
通過這幾步,就可以簡單的修復漏洞問題,但是還是需要注意幾個問題:
1> 需要過濾掉類的方法由于通過反射的形式來得到指定對象的方法,他會把基類的方法也會得到,最頂層的基類就是,所以我們為了不把方法注入到Js中,所以我們需要把的公有方法過濾掉。這里嚴格說來,應該有一個需要過濾方法的列表。目前我的實現中,需要過濾的方法有:
"","","","","","","wait",
2> 在 3.0以下,系統自己添加了一個叫的Js接口,要解決這個安全問題,我們也需要把這個接口刪除,調用rface方法。這個好像是跟的搜索框相關的。
3> 在實現過程中,我們需要判斷系統版本是否在4.2以下,因為在4.2以上,修復了這個安全問題。我們只是需要針對4.2以下的系統作修復。
六、總結
在中的作用還是舉足輕重的,加上現在很多應用都開始采用網頁版功能,那么在這個過程中無法避免就是需要JS和本地交互,本文就詳細的介紹了現階段的三種交互方式,每種方式都有缺點和優點,當然最好的方式還是采用系統提供的也就是本文介紹的第一種方式,但是需要修復.2以下存在的漏洞問題即可。
手機看文章有點費勁,可以進入網頁版: