安全動態(tài)

Android應用存儲安全與加固

來源:聚銘網絡    發(fā)布時間:2016-07-13    瀏覽次數:
 

信息來源:比特網 

       

       目前移動領域已經出現(xiàn)了相當部分的安全問題,新的惡意軟件層出不窮,另一方面,企業(yè)對敏感數據保密性意識日益提高,作為移動開發(fā)者,有責任對最終用戶的隱私和安全承擔更多責任。

本文主要討論移動安全存儲策略,設計了安全加固方案,實現(xiàn)了移動應用逆向分析、安全代碼自動注入等全流程的一鍵式加固工具,并進行了驗證。

1.移動數據存儲

Android平臺實現(xiàn)數據存儲的5種基本方式:

數據共享(SharedPreferences)

--內部存儲(File)

--SQLite數據庫存儲

--外部存儲

--網絡存儲

本文主要討論前三種數據存儲類型,實現(xiàn)了加密解密SDK,并實現(xiàn)對APP的安全存儲注入。首先我們來簡單討論下Android中數據存儲的位置——考慮數據安全,有必要更改android應用的存儲位置嗎?

在非root設備上,數據已可通過沙盒得到很好地安全保護(當然,我們也不可以完全忽略設備存在內核漏洞或虛擬機漏洞時可能發(fā)生的后果)?!白远x存儲位置”也是一種設計方式,使破解者難以確定存儲的路徑,并完全控制了存儲實現(xiàn),以進行加密和解密保護。但這樣做,失去了Android自身完善的特權分離機制(安全沙盒),將數據文件完全暴露在沙盒外,弊大于利,實際上意義不大。

因此這里仍選擇沙盒作為數據的存儲位置,接下來主要討論對于root的設備,如何增強數據的安全性。在root設備上,需要通過數據擦除或數據加密,實現(xiàn)數據的安全存儲,降低數據暴露的可能性。

2.加密方案選擇

涉及到了加密,我們需要選擇一種加密算法,加密算法的選擇無窮無盡,本文采用AES加密算法,選擇128位秘鑰加密方式。以下是三種存儲類型在AES算法下的具體實現(xiàn)方式:

SharedPreferences存儲加密解密方式:對key和value同時加密,存儲類型都為String類型,數據讀取時根據需要進行類型轉換。

File文件存儲加密解密方式:對數據流進行加密解密。

SQLite數據庫存儲加密解密方式:基于Sqlcipher進行實現(xiàn)。

3.代碼注入方案設計3.1注入方案比較

在”哪里”或者如何將我們提供的SDK注入到已有APP中,以及如何修改此APP中的實現(xiàn)。這里注入的層面可以是:java字節(jié)碼(.class)或DEX字節(jié)碼(.smali),二者分別對應反編譯和反匯編過程。這里選擇后者作為注入方案,原因如下:

(1) smali語法定義明確,易于直接替換對象類型;

(2)在反編譯流程中,更直接。

3.2 DEX字節(jié)碼

Dalvik虛擬機運行Dalvik字節(jié)碼,由java字節(jié)碼轉換而來,又稱為” Dalvik匯編語言”,是Dalvik指令集組成的代碼,Dalvik指令集是Dalvik虛擬機為自己專門設計的一套指令集。但嚴格說它不屬于正式語言,它的特點如下:

Dalvik指令在調用格式上模仿了C語言的調用約定;

--根據字節(jié)碼的大小與不同,一些字節(jié)碼添加了名稱后綴以消除歧義;

32位常規(guī)類型的字節(jié)碼未添加任何后綴

64位常規(guī)類型的字節(jié)碼添加-wide后綴

特殊類型的字節(jié)碼根據具體類型添加后綴,如-boolean、-byte、-char、-void等

--根據字節(jié)碼的布局與選項不同,一些字節(jié)碼添加了字節(jié)碼后綴以消除歧義,這些后綴通過在字節(jié)碼主名稱后添加斜杠(/)來分隔開;

--在指令集的描述中,寬度值中每隔字母表示寬度為4位。

我們來看一下它對方法的定義:

invoke-virtual {p0, v2, v3},

Landroid/content/Context;->getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences;

move-result-object v1

這里調用了類android.content.Context的getSharedPreferences方法,其中p0寄存器存儲context實例,方法的參數是兩個:一個是java.lang.String類型,一個是int類型,兩個參數分別保存在寄存器v2和v3中,返回值是android.content.SharedPreferences類型,并把返回值保存到v1寄存器中。

Dalvik字節(jié)碼中使用了寄存器保存變量和參數。我們知道,Java虛擬機基于棧架構,程序需頻繁從棧上讀取或寫入數據,會耗費CPU(指令分派、內存訪問次數);Dalvik虛擬機基于寄存器架構,數據訪問通過寄存器直接傳遞。兩者都為每個線程維護一個PC計數器與調用棧,PC計數器以字節(jié)為單位記錄當前運行位置距離方法開頭的偏移量。不同的是,Java棧記錄Java方法調用的活動記錄,以幀為單位保存線程的運行狀態(tài),每調用一個方法就會分配新的棧幀壓入Java棧上,方法返回則彈出并撤銷相應的棧幀;而Dalvik棧維護一份寄存器表。

每個Dalvik寄存器都是32位,對于大于這個長度的類型,用兩個相鄰寄存器存儲。寄存器被設計為兩種表示方法:v命名法和p命名法。具體請參考相關資料。

4.加固流程設計

App加固總流程如下:

apk反匯編 -> sdk注入 -> Smali文件掃描 -> 代碼修正 -> 正向匯編 -> apk簽名

5.加固流程實現(xiàn)

這里以SharedPreferences存儲為例,例舉SDK和代碼修正的實現(xiàn)方式。(其他步驟實現(xiàn)略)

5.1安全存儲SDK

SDK中提供了針對SharedPreferences存儲類型的加密解密方式,我們對外提供了一個SecureSharedPreferences類,它實現(xiàn)了android.content.SharedPreferences接口,并實現(xiàn)了接口所提供的各個方法,將android.content.SharedPreferences類型實例作為參數,傳遞給構造方法。當讀取數據時,使用這個參數進行查詢并返回值,當存儲數據時,在edit方法處,返回一個實現(xiàn)android.content.SharedPreferences.Editor接口的類,進行數據的添加。

這樣的SDK設計使得代碼注入可行,并只需要較少的修正量。

5.2 代碼修正

在調用SharedPreferences存儲時,某種實現(xiàn)方式可以是(java代碼):

SharedPreferences sp =context.getSharedPreferences("config", 0);

我們需要將其修正為調用我們提供的SDK方式來實例化sp對象。DEX字節(jié)碼如下:

invoke-virtual {p0, v2, v3},

Landroid/content/Context;->getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences;

我們首先將這個結果保存到一個寄存器下,這里可以使用v2或者v3寄存器,它們分別對應兩個類型的參數:java.lang.String和int,而且之后不會再對它們進行使用,因而它們是可用的兩個寄存器。這里我們選擇v3寄存器:

move-result-object v3

接下來新建一個SecureSharedPreferences對象,并將它放到某寄存器下,這個寄存器需要是java中sp對象存儲的寄存器,并且用這個寄存器的值進行SharedPreferences方法的調用,如v1寄存器:

new-instance v1,Lcom/…/SecureSharedPreferences;

繼而需要調用這個對象的構造函數,并把之前保存在v3寄存器中的值作為參數傳遞(SharedPreferences類型):

invoke-direct {v1, v3},

Lcom/…/SecureSharedPreferences;->(Landroid/content/SharedPreferences;)V

這樣就完成了修正過程。

其他存儲類型以及調用方式的修正方式與以上類似,這里不再贅述。

6.驗證實踐

這里我們將整個流程所需的各個依賴包、庫文件、各個工具、代碼修正實現(xiàn)及我們提供的SDK集成到一起,形成一個一鍵式的加固工具(bat形式)。以一個DEMO為例,DEMO中實現(xiàn)了以上三種存儲方式的數據存儲和讀取,其中存儲都以默認方式(明文)實現(xiàn),沒有進行安全加密。

將DEMO APK放到工作目錄下,啟動并得到加固后的安全APK(secure_demo.apk),其中demo文件夾為中間過程產生的數據文件。

將它運行到一個root的Android測試機上,并使用R.E.Explorer工具查看存儲,可見數據已經過了加密存儲,并能夠正確的解密并獲得原始數據。SQLite數據庫對存儲本身進行了加密,因而加密后,通過工具(android內置查看器或SQLite Expert Professional查看工具)已無法打開db文件。

7.總結與討論

本文主要討論了Android設備數據存儲安全問題,重點關注于針對一個已有的、非安全存儲的移動應用,如何將其加固為一個達到安全存儲結果的應用。

希望各位讀者們批評指正,并如若有更好的實踐或心得,及時交流和討論,十分感謝。最后附加了實現(xiàn)中幾點細節(jié)的討論:

(1)ART架構

Android Art架構和Dalvik架構主要區(qū)別在于應用的執(zhí)行是否使用即時編譯器,對于Art架構來說,以軟件安裝即時性為犧牲,完成了代碼編譯,以提高程序運行效率,而Dalvik架構仍然需要即時編譯器的輔助。而無論是哪種架構,與本文中討論的加固方案應該是不發(fā)生沖突的。

(2)AES Seed

AES算法中是目前電子數據加密中被廣泛接受的方案,雖然密鑰是隨機生成的,但仍然需要一個密鑰種子,而這個秘鑰種子的安全性也是決定整個加密算法安全性的關鍵。在一個移動應用中,密鑰種子的生成算法可以以本地代碼方式提供(.so),雖然so文件也不是絕對不可以被反編譯的,但是相對的會提高安全性。此外,谷歌還提出一種基于云存儲的方案:

Google recently announced a cloud-based storagesolution for apps, so you could consider storing the key there. Or its seemsthat getting the key outside the device, like on a server, is better.”

(3)加密效率

AES算法處理過程復雜,導致大數據文件加密和解密效率不是很高,對于幾十兆的大文件加密,不是一個很好的選擇,因而企業(yè)在選擇大數據文件作為敏感數據保護目標的話,需要對加密方式另行評估。


 
 

上一篇:思科安全——企業(yè)安全棋局的“宇宙流”

下一篇:“聚力、賦能” 阿里安全峰會在京召開 用生態(tài)的觀點做安全