Android安全開發之淺談密鑰硬編碼

近日小編會陸續在專欄里推送Android安全開發系列的文章,系列文章有部分是在聚安全的官方博客里更新過,時間跨度比較長,所以小編統一整理到專欄里。對Android開發感興趣的小夥伴請關注聚安全和我們的安全專欄!當然,對APP安全有需求的小夥伴,也請記得聯繫我哦~

Android安全開發文章回顧

Android安全開發之安全使用HTTPS

Android安全開發之淺談加密演算法的坑

---------------------------------------------------- 正文分割線

一、簡介

在阿里聚安全的漏洞掃描器中和人工APP安全審計中,經常發現有開發者將密鑰硬編碼在Java代碼、文件中,這樣做會引起很大風險。信息安全的基礎在於密碼學,而常用的密碼學演算法都是公開的,加密內容的保密依靠的是密鑰的保密,密鑰如果泄露,對於對稱密碼演算法,根據用到的密鑰演算法和加密後的密文,很容易得到加密前的明文;對於非對稱密碼演算法或者簽名演算法,根據密鑰和要加密的明文,很容易獲得計算出簽名值,從而偽造簽名。

二、風險案例

密鑰硬編碼在代碼中,而根據密鑰的用途不同,這導致了不同的安全風險,有的導致加密數據被破解,數據不再保密,有的導致和伺服器通信的加簽被破解,引發各種血案,以下借用幾個APP漏洞案例來講講。

2.1 某互聯網金融APP加密演算法被破解導致敏感信息泄露

某P2P應用客戶端,用來加密數據的DES演算法的密鑰硬編碼在Java代碼中,而DES演算法是對稱密碼演算法,既加密密鑰和解密密鑰相同。

反編譯APP,發現DES演算法:

發現DES演算法的密鑰,硬編碼為「yrdAppKe」,用來加密手勢密碼:

將手勢密碼用DES加密後存放在本地LocusPassWordView.xml文件中:

知道了密文和加密演算法以及密鑰,通過解密操作,可以從文件中恢復出原始的手勢密碼。或者使用新的生成新的手勢密碼,而與伺服器通信時介面中的Jason欄位也用了DES演算法和密鑰硬編碼為「yRdappKY」:

和伺服器通信採用http傳輸,沒有使用https來加密通信,如果採用中間人攻擊或者路由器鏡像,獲得流量數據,可以破解出用戶的通信內容。

2.2 某租車APP加密演算法被破解導致一些列風險

某租車APP與伺服器通信的介面採用http傳輸數據,並且有對傳輸的部分參數進行了加密,加密演算法採用AES,但是密鑰硬編碼在java代碼中為「shenzhoucar123123」,可被逆向分析出來,導致偽造請求,結合伺服器端的漏洞,引起越權訪問的風險,如越權查看其它用戶的訂單等。

伺服器通信時的數據為:

q欄位是加密後的內容。逆向APP,從登錄Activity入手:

分析登錄流程:v1是用戶名,v2是密碼,v3是PushId,在用戶名和密碼不為空並且長度不小於11情況下,執行LoginOperate相關操作,追蹤LoginOperate的實現,發現繼承自BaseOperate,繼續追蹤BaseOperate的實現:

在BaseOperate的initUrl()方法中,找到了APP是怎麼生成請求數據的:

繼續追蹤上圖中的initJsonUrl()方法,發現其調用了AES加密:

繼續追蹤aes.onEncrypt()函數:

在onEncrypt()函數中調用了encrypt()函數用來加密數據,追蹤encrypt()函數的實現,發現其使用AES演算法,並且密鑰硬編碼在java代碼中為「shenzhoucar123123」

到現在請求中的數據加密如何實現的就清晰了,另外由於伺服器許可權控制不嚴,就可以構造訂單id的請求,達到越權訪問到其他用戶的訂單。

構造{「id」:」11468061」}的請求:

其中uid設置為你自己的uid即可,可以成功看到其他人的訂單:

攻擊者完全可以做到使用其他腳本重新實現相同的加密功能並拼接出各個介面請求,批量的刷取訂單信息和用戶其他信息。

2.3 某酒店APP加簽演算法被破解導致一系列風險

某酒店APP和伺服器通信時介面採用http通信,數據進行了加密,並且對傳輸參數進行簽名,在伺服器端校驗簽名,以檢查傳輸的數據是否被篡改,但是加簽演算法和密鑰被逆向分析,可導致加簽機制失效,攻擊者可任意偽造請求包,若結合伺服器端的許可權控制有漏洞,則可引發越權風險等。

APP和伺服器通信的原始包如下圖,可以看到有加簽欄位sign:

逆向APP定位到加密演算法的邏輯代碼,com.htinns.biz.HttpUtils.class,其實現邏輯為:

原始數據是unSignData,使用RC4演算法加密,密鑰為KEY變數所代表的值,加密後的數據為signData,傳輸的數據時的data欄位為signData。

加簽欄位signd的生成方法是用unsignData拼接時間戳time和resultkey,然後做md5,再進行base64編碼。時間戳保證了每次請求包都不一樣。

sendSign()演算法是用c或c++寫的,放入了so庫,其他重要演算法都是用java寫的。 可以使用IDA逆向分析so庫,找到sendSign()方法

而漏洞提交者採用的是分析sign和getSign(sign)的數據,做一個演算法破解字典。其實還有種方法直接調用此so庫,來生成字典。

簽名破解以後,就可以構造發送給伺服器的數據包進行其他方面的安全測試,比如越權、重置密碼等。

三、阿里聚安全對開發者的建議

通過以上案例,並總結下自己平時發現密鑰硬編碼的主要形式有:

1、密鑰直接明文存在sharedprefs文件中,這是最不安全的。

2、密鑰直接硬編碼在Java代碼中,這很不安全,dex文件很容易被逆向成java代碼。

3、將密鑰分成不同的幾段,有的存儲在文件中、有的存儲在代碼中,最後將他們拼接起來,可以將整個操作寫的很複雜,這因為還是在java層,逆向者只要花點時間,也很容易被逆向。

4、用ndk開發,將密鑰放在so文件,加密解密操作都在so文件里,這從一定程度上提高了的安全性,擋住了一些逆向者,但是有經驗的逆向者還是會使用IDA破解的。

5、在so文件中不存儲密鑰,so文件中對密鑰進行加解密操作,將密鑰加密後的密鑰命名為其他普通文件,存放在assets目錄下或者其他目錄下,接著在so文件裡面添加無關代碼(花指令),雖然可以增加靜態分析難度,但是可以使用動態調式的方法,追蹤加密解密函數,也可以查找到密鑰內容。

保證密鑰的安全確是件難事,涉及到密鑰分發,存儲,失效回收,APP防反編譯和防調試,還有風險評估。可以說在設備上安全存儲密鑰這個基本無解,只能選擇增大攻擊者的逆向成本,讓攻擊者知難而退。而要是普通開發者的話,做妥善保護密鑰這些事情這需要耗費很大的心血。

產品設計者或者開發者要明白自己的密鑰是做什麼用的,重要程度怎麼樣,密鑰被逆向出來會造成什麼風險,通過評估APP應用的重要程度來選擇相應的技術方案。

所以建議不妨試試阿里聚安全的安全加固和安全組件,其中安全組件中的安全加密功能提供了開發者密鑰的安全管理與加密演算法實現,保證密鑰的安全性,實現安全的加解密操作;安全簽名功能實現客戶端請求的簽名處理,保證客戶端與服務端通信請求不被偽造。安全加固提升安全等級,防止應用被逆向破解。這樣同時從應用層、運行層、native層提供多層次全方位立體防護,另外還有安全沙箱、白盒加密、底層加固共同保證客戶端數據安全。

攻防是不斷變化演進的,阿里聚安全提供的服務能實時更新客戶端模塊,通過阿里聚安全的漏洞掃描來檢測應用是否具有密鑰硬編碼風險,保證在攻防對抗中永遠處於上風。

專業的事情交給專業的人來做,自己的主要精力用來做功能開發或者業務邏輯,快速打造能贏得市場的可靠產品才是王道。

作者:伊樵、呆狐@阿里聚安全

更多Android、iOS安全技術文章,請持續關注阿里聚安全的安全專欄

推薦閱讀:

okhttp和http 2.0相遇引發的"血案"
基於 Appium 的 Android UI 自動化測試
給力!據說裝了這些APP,就能讓你的安卓機徹底和卡頓說再見
SRC 對於音質會有怎樣的影響?

TAG:Android | 密码破译 | 移动安全 |