1. 程式人生 > >Android中利用ZipEntry漏洞實現免root寫惡意檔案到應用的沙盒中

Android中利用ZipEntry漏洞實現免root寫惡意檔案到應用的沙盒中

http://blog.csdn.net/jiangwei0910410003/article/details/52118575

 

版權宣告:本文為博主原創文章,未經博主允許不得轉載。

目錄(?)[-]

  1. 一前言
  2. 二漏洞場景分析
  3. 三漏洞出現的原因
  4. 四漏洞案例分析
  5. 六問題延展
  6. 七漏洞總結
  7. 八總結

一、前言

Android中的漏洞真的很多,一不小心就踩到坑了,最近開發過程中遇到一個問題,解決發現一個很大的漏洞,而這個漏洞到現在也沒有修復,google也沒有想過修復,下面就來看看這個漏洞的場景。

 

二、漏洞場景分析

Android中現在開發過程中會有很多場景中使用到解壓縮檔案,比如動態載入機制,可能下載了apk/zip檔案,然後在本地做解壓工作,還有就是一些資源在本地佔用apk包的大小,就也打包成zip放到服務端,使用的時候在下發。本地在做解壓工作。那麼在Android中解壓zip檔案,使用的是ZipInputStream和ZipEntry類,程式碼比較簡單:

程式碼看上去很簡單,但是這段程式碼中就存在一個問題,就是那個zipEntry.getName方法,這個方法返回的是zip檔案中的子檔名稱,按照正常邏輯,解壓這個子檔案到本地都是直接用相同的名字即可,但是這裡zip檔案就存在一個漏洞:

zip檔案中的子檔名格式沒有格式要求,也就是可以包含特殊字元。

但是在系統中是有限制的,比如Windows中:

在Linux中:

這些系統中是不允許檔名包含一些特殊字元的,但是在ZipInputStream/ZipOutputStream類卻是可以的。

 

也就是說使用ZipOutputStream類進行壓縮檔案,這裡可以對檔名不做任何限制,壓縮程式碼也簡單:

只用ZipEntry類做單個檔案壓縮:

這裡的ZipEntry可以指定隨意的名稱,而這個名稱就是檔案在zip中的檔名。但是問題是這裡對名稱沒有任何限制,那麼如果我們的zip包被人惡意的攔截,然後進行修改,當然這裡他可以使用ZipInputStream/ZipOutputStream類,寫一個簡單的小程式,就可以把惡意檔案寫入到zip中

 

三、漏洞出現的原因

這裡的惡意漏洞的問題就在於:

因為檔名沒有限制,所以攻擊者可以把惡意檔名稱命名為:../../../../data/data/xxx.xxx.x/hacker.dex,因為Android是基於Linux系統的,在Linux系統中../這個符號代表是回到上層目錄,那麼這裡可以多弄幾個這個符號,這樣就會回到Android系統的根目錄,然後在進入當前應用的沙盒目錄下,寫一個檔案了。當然這裡只能寫入本應用中,而不能寫入其他應用。

存在的風險:比如現在知道了一個應用的沙盒資料的詳細資訊,比如一些隱私資料存放在SharedPreferences.xml中,或者是有動態載入機制,需要載入的dex存放在一個目錄中,那麼這時候我們可以利用這個漏洞,把幾個惡意檔案,命名成

../../../../data/data/xxx.xxx.xxx/shared_pref/info.xml,或者是../../../../data/data/xxx.xxx.xxx/dexfile/dynamic.dex等

這樣在使用ZipEntry進行解壓檔案的時候,因為直接使用了ZipEntry.getName方法或者檔名,然後直接釋放解壓到本地了,所以這時候就相當於替換了本應用的沙盒資料了,這個也是利用了app本身的許可權來寫入沙盒資料。

 

四、漏洞案例分析

上面分析完了漏洞,下面就用一個簡單的例子來看看問題吧:

因為,我們上面分析知道,在本地系統中命名這樣特殊格式的檔案,在進行壓縮成zip檔案是不行的,因為系統不支援這種命名格式,所以這裡需要寫一個小程式,把這個特殊的檔名的檔案壓縮成zip,便於測試,然後在進行解壓:

先進行壓縮檔案,方便測試,產生一個demo.zip檔案,然後在進行解壓驗證漏洞問題,這裡驗證問題的重點是:

這裡把zip中需要解壓的檔名前加上字首:../../../data/data/cn.wjdiankong.androidzipleakdemo/ 這樣解壓之後的目錄就是本應用的沙盒中了,注意這裡的../這樣的符號不要太多,只要能回到根目錄就可以了。

這裡為了方便,直接使用echo命令,寫入aaa內容到demo.txt檔案中,然後點選壓縮,再次檢視多了demo.zip檔案了:

看到了,這裡就把zip中的惡意檔案demo.txt釋放到了應用的沙盒中了,如果這個檔案是dex或者啥,替換原來應用的一些重要檔案,那麼後果會很嚴重的。

 

五、如何避免這個漏洞問題

上面的問題,我們瞭解了,主要是因為ZipEntry在進行壓縮檔案的時候,名稱沒有做任何限制,而在Android系統中../這種特殊符號代表的是回到上層目錄,又因為這個解壓工作在本應用中,可以藉助app的自生許可權,把惡意檔名改成:../../../data/data/...即可在解壓的時候把檔案解壓到了應用的沙盒中。

那麼其實問題在於最後一步解壓,因為我們不會去修改解壓之後的檔名,預設都是直接解壓即可,那麼這裡修復這個漏洞問題很簡單了,有很多種方式,核心就一個就是不要讓有特殊字元,比如:../ 的檔案成功解壓,或者是解壓到本地檔名稱不能包含這種特殊字元即可:

這裡可以直接過濾來防護這個問題了。

 

六、問題延展

上面分析了現在應用很多都有從服務端下載zip檔案,然後在本地進行解壓的功能,在解壓的過程中預設不回去進行檔名的操作,所以就存在一些特殊字元的檔名被釋放到了本地,從而產生重大後果。但是這裡有一個前提,就是你需要下載的zip檔案被攻擊者攔截到了,並且替換了。但是如果在下載的過程中就做一層安全其實也是可以的,比如使用https協議,然後在結合檔案的MD5比對功能,這樣就可以防止zip包被人攔截替換了。本地也就不會存在這樣的風險了。

所以現在Android中動態載入技術和外掛化開發已經很普遍了,但是在下載這個階段一定要好防護工作,一個是服務端可以採用https協議,而客戶端需要做檔案的MD5比對,以及這種解壓工作的防護過濾。

如果你的專案現在正好有解壓zip的功能,請看完這篇文章之後,儘快去審查一下專案中解壓有沒有做防護,沒有的話就儘快加上吧!

 

七、漏洞總結

本文主要介紹了一個不起眼的漏洞,但是隱藏著很嚴重的問題,這個漏洞主要是因為如下幾點綜合產生的:

1、ZipEntry對壓縮檔名沒有特殊要求

2、在Android系統中../特殊字元代表著回到上級目錄

3、藉助本應用的許可權,把資料寫入沙盒中

因為這三點,就可以在解壓過程中把惡意檔案解壓到應用的沙盒中,當然這裡有一個前提就是你的zip包被人攔截並且篡改加入這種特殊字元的惡意檔案了。

 

關於這個漏洞的修復,Google一直沒有修復,只是在Api中做了提醒:

可以看到google對該方法給出了一個安全提示,提示開發者如果該方法的返回值中包含有"../"跳轉符,需要特別注意不要將檔案寫到了目標資料夾之外。如果不對"../"跳轉符做過濾,就有可能遍歷目錄,在解壓zip檔案時以本app的許可權覆蓋任意檔案。

 

專案下載:http://download.csdn.net/detail/jiangwei0910410003/9594958

 

八、總結

人生處處是坑,Android系統處處是漏洞,開發中碰到這個問題,真的很難注意到,但是卻隱藏這很大的風險,所以有專案中用到了zip解壓的速度檢查專案,如果有的話,看看有沒有新增防護過濾,保證我們的專案沒有這個漏洞的風險!