劉龍錦 張志杰 梁世民
【摘要】? ? 截止至2020年6月,Android系統(tǒng)占據(jù)了手機系統(tǒng)74.6%市場份額,剩余26.4%市場份額由其他系統(tǒng)瓜分,絕對優(yōu)勢的市場占有率造就了繁榮的Android生態(tài)及數(shù)量龐大的開發(fā)者。開發(fā)者水平的高低則給Android開發(fā)帶來了許多安全性問題。本文將從Android應用抓包防護,Java代碼防護,So代碼防護,簽名加密算法,服務端校驗方面進行研究,為應用的風險控制方案設計提供理論依據(jù)。
【關鍵詞】? ? Android? ? 抓包? ? 反編譯? ? 服務端
引言:
保護用戶數(shù)據(jù),保護信息安全是每一個開發(fā)者,每一家互聯(lián)網(wǎng)公司都應該重點布防的區(qū)域。一套完整高效的風險控制方案,是開發(fā)者或公司開發(fā)實力的體現(xiàn),也是高效保護用戶數(shù)據(jù),信息安全,人人公平的重要手段。目前國內(nèi)外在應用安全方面都比較著重,市場上也有阿里云、360、數(shù)美、數(shù)盟等安全服務廠商為Android應用提供安全加密服務。僅僅只靠第三方廠商提供的安全防護是遠遠不足的,我們需要控制用戶操作的完整鏈路,才能設計出一套優(yōu)秀的風險控制系統(tǒng)。
一、防護方式
多數(shù)Android應用的操作邏輯為:客戶端進行操作,系統(tǒng)發(fā)送請求到服務器,服務端校驗請求合法及參數(shù)并返回數(shù)據(jù),客戶端根據(jù)服務端返回數(shù)據(jù)進行相應界面展示。在這套操作邏輯中,客戶端的操作及數(shù)據(jù)發(fā)送部分存在風險。攻擊者通過反編譯Apk包,逆向出Android應用與服務端的通信協(xié)議,偽造非法請求攻擊。針對上述的攻擊方式,開發(fā)者會在Android應用的通信協(xié)議層進行防護,提高攻擊者抓包的難度,在請求中嵌入加密算法。收集設備信息,如設備型號,網(wǎng)卡地址,系統(tǒng)版本,IP地址等,綜合判斷本次請求是否合法。
二、抓包防護
抓包是研究應用程序的開始,通過抓包獲取數(shù)據(jù)進行分析,確認目標請求的地址、參數(shù)、加密字段等。主流的Android應用與服務端之間使用HTTPS/TLSv1.2協(xié)議通信,某些Android應用使用QUIC/Http3并強制使用TLSv1.3協(xié)議。隨著Android系統(tǒng)的版本更新,系統(tǒng)層面強制要求開發(fā)者使用HTTPS協(xié)議進行通信,開發(fā)者也重視數(shù)據(jù)傳輸過程中的安全,攻擊者對應用的抓包越發(fā)困難。
抓包通常采用中間人方式,常用抓包軟件有Fiddler、Charles等。中間人方式抓包需要解決兩個問題:如何偽裝Server、如何偽裝Client。以Fiddler軟件為例子,偽裝Server時需要安裝根證書到系統(tǒng)根目錄,偽裝Client則客戶端需要安裝Fiddler的自簽證書。Android系統(tǒng)將CA證書分為用戶CA與系統(tǒng)CA證書,系統(tǒng)CA證書擁有的權限較高但需要設備擁有root權限才可進行添加和刪除操作。
在擁有root權限的設備上,抓包非常容易實現(xiàn)。電腦端步驟:安裝Fiddler,安裝Fiddler根證書到系統(tǒng),配置解密通道。手機端步驟:設置代理到電腦,安裝Fiddler自簽證書,安裝Xposed框架,安裝JustTrustMe插件,配置完成,即可抓取大多數(shù)應用數(shù)據(jù)包。對于抓包的防護,防護辦法有以下幾種:應用targetSdkVersion設置為大于24、雙向SSL認證、使用SSL重協(xié)商、使用其他通信協(xié)議。無論使用那種方式都不可能避免不被抓包,對于Android系統(tǒng)的限制可降低Android版本,證書固定方式可以Hook移除相關代碼,雙向SSL認證可逆向拿到私鑰進行破解抓包。開發(fā)者盡可能的提高抓包難度,增大攻擊者抓包的成本即可。
三、Java代碼防護
Android應用與服務端通信時,在請求中嵌入Token或者加密的字段是常見的方式。高級的風險控制系統(tǒng)還會收集用戶的操作行為日記上傳到服務器,通過分析用戶的操作行為日記來判定本次請求是否有效。在請求中嵌入加密字段需要開發(fā)者在Java代碼層進行代碼編寫,由于Android開源的特性,經(jīng)過開發(fā)工具編譯生成的Apk安裝包如若未經(jīng)過任何技術處理,使用Jadx工具進行反編譯即可查看得到與源程序匹配度高達95%的代碼。對于攻擊者而言,能查看到程序的源碼能夠極大的加快破解的速度,為了延緩攻擊者得到Android應用在Java層的算法,通常采用以下手段進行防護:
(一)代碼混淆
使用Proguard-rules工具進行代碼混淆,加大攻擊者閱讀難度,延緩破解算法的速度。代碼混淆方法僅僅只能延緩算法被破解的速度,可以把一些水平較低的破解者攔在門外,對于編程功底較為深厚攻擊者,此方法終究會被破解。
(二)Apk簽名校驗
進行APK打包操作時,開發(fā)人員要進行簽名操作。簽名文件是開發(fā)者獨有的,攻擊者通常不可能有相同的文件,可以使用Android SDK中PackageManager類的getPackageInfo簽名校驗方法保護Apk。
(三)重打包對抗
對Apk進行重打包,修改代碼實現(xiàn)抓包也是常用的攻擊方式。重打包常用的工具是ApkTool,ApkTool對Png文件會按照Png格式處理,將一個非Png格式的文件修改為Png格式,ApkTool打包時會出錯,可以在Apk的資源文件放入一些非法文件干擾ApkTool工具。
(四)調(diào)試器檢測
防止Apk被動態(tài)調(diào)試,可以檢測是否有調(diào)試器鏈接,使用Application類的isDebuggerConnected方法檢測,有調(diào)試器鏈接則采取防護措施。
(五)Dex文件校驗
重編譯Apk安裝包會重新編譯Dex文件,生成的Dex文件的Hash值就會發(fā)生改變,記錄軟件初始發(fā)布時Dex文件哈希值與客戶端運行時Hash值進行對比判斷應用是否被修改過。
(六)加殼保護
第三方廠商提供的加殼程序?qū)pk進行加殼也是一種有效的方式。但Apk加殼是在Java層代碼實現(xiàn)的,被反編譯的風險仍然很大。
四、So代碼防護
由于Android系統(tǒng)開源的特性,在Java層進行的防護都會被破解。Google為開發(fā)者提供了So文件的支持。So文件是Unix操作系統(tǒng)的動態(tài)鏈接庫,相當于Windows下的Dll文件,它由Native C/C++代碼編譯而來,在Android系統(tǒng)中充當JNI與Java交互的角色,能被Android Runtime加載并能被Java層調(diào)用。對比Java語言,C/C++在效率方面,混淆后的閱讀方面及加殼破解難度方面都有較大的提升。加密算法以及網(wǎng)絡通信協(xié)議在寫在so層是目前主流的做法,但So層的代碼也不是不能被破解的,只是破解的難度相較Java層的代碼會有一個較大的提升。反編譯So文件的主流軟件是Ida Pro,使用Ida軟件反編譯可以得到So文件的內(nèi)容。為了加大攻擊者閱讀So文件的難度,需要對So文件進行加固以及混淆。So文件是可以被單獨調(diào)試的,所以需要對So文件進行反調(diào)試的保護,對So層的保護主要有以下幾種方式:
(一)代碼混淆
基于LLVM的混淆,通過指令替換、控制流扁平化和虛假控制等方法混淆。增加了虛假控制流、指令替換和控制流平坦化的處理?;贚LVM的混淆比較靈活,根據(jù)不同的安全需求策略,混淆程度越高,則性能影響越大,文件膨脹越多。
(二)調(diào)試檢測
Ida軟件具有動態(tài)調(diào)試So文件的功能,可以方便的還原出So層的算法。在So文件的JNI_Onload方法中加入調(diào)試檢測的代碼防止So文件被Ida軟件動態(tài)調(diào)試,可以在一定程度上防止算法被還原。
(三)防止調(diào)用
So文件可以作為一個庫單獨運行,確定了關鍵函數(shù)的地址后,直接調(diào)用即可得到返回值,為了防止被直接調(diào)用,應該在So文件中置入代碼,通過檢測上下文環(huán)境參數(shù)確認函數(shù)是被自身調(diào)用,防止直接調(diào)用攻擊。
(五)加殼保護
使用加殼程序?qū)o文件進行加殼,由于So層的加殼程序使用C/C++編寫,執(zhí)行的效率相對比Java層更高,代碼復雜度也比Java語言復雜一些,對應的脫殼難度也更高,可以更有效的提升應用安全。
五、簽名加密算法
除了常規(guī)Token認證之外,在每一個請求中都會對請求的參數(shù)進行簽名加密。加密得到的字符串嵌入在請求中參數(shù)中,服務端接收到數(shù)據(jù)后根據(jù)雙方約定好的算法對參數(shù)計算得到加密字符串,再與客戶端傳輸?shù)淖址M行對比,如果雙方計算結果相同則暫時認為請求是合法的。
加密算法寫在Java層代碼非常容易遭到破解,大部分應用都會將加密算法寫在So層。常用的加密算法有MD5,AES,HMAC_MD5,RSA等,通常會使用多種加密算法結合計算以提升加密強度。加密算法無論是寫在Java層還是So層,都是可以被逆向出來的,寫在So層只是能延緩攻擊者破解的速度,對So文件進行脫殼修復,去LLVM混淆化,將So層的代碼邏輯進行修復后可以得到對應的加密算法。
六、服務端檢驗
客戶端發(fā)出的請求最終都由服務端校驗處理,Android應用無法做到完全隱藏程序代碼,對于客戶端的請求,服務端應該從多個方面進行校驗,校驗通過之后才能判定本次請求有效。服務端主要從以下方面進行判斷:
(一)簽名加密算法
服務端與客戶端通過雙方約定好的算法分別對數(shù)據(jù)進行加密后得到的字符串進行對比,對比不通過則代表本次請求為惡意請求,直接返回錯誤。
(二)IP地址來源
對從云服務器廠商發(fā)出的請求、同一個IP在某個時間段內(nèi)頻繁發(fā)出的請求、頻繁更換IP地址進行訪問的請求進行一定的限制。如果是需要登錄的應用,可以在登錄時記錄對應的IP地址,后續(xù)發(fā)出的請求如果超過登錄IP的范圍,在環(huán)境校驗失敗之后應該做一定的請求限制。
(三)設備環(huán)境信息
判斷設備的型號、品牌、系統(tǒng)版本等信息生成對應權重的設備ID。對系統(tǒng)版本較低,設備已經(jīng)Root,安裝有Xposed框架的設備適當降低權重或者將其直接風控。
(四)用戶操作行為
上傳某個時間段內(nèi)用戶的操作信息,綜合判斷該操作是否有效。
七、結束語
Android應用的風險控制系統(tǒng)的設計需要進行多方面綜合考慮,它對開發(fā)者的專業(yè)技術提出了更高的要求,需要在與攻擊者的對抗中不斷進行完善,不斷進行優(yōu)化。
作者單位:劉龍錦? ? 張志杰? ? 梁世民? ? 北海職業(yè)學院
參? 考? 文? 獻
[1]韓子諾,劉嘉勇.基于Android平臺的SO加固技術研究[j].現(xiàn)代計算機(專業(yè)版), 2015(24):49-53
[2]李志明,劉壽春,等基于JNI機制與云平臺的細粒度Android應用加固方法[j].小型微型計算機系統(tǒng), 2021(42):640-646
[3]徐尤華,熊傳玉.Android應用的反編譯[j].電腦與信息技術, 2012(20):50-51