在阿里聚安全的漏洞掃描器中和人工APP安全審計中,常常發現有開發者將密鑰硬編碼在Java代碼、文件中,這樣作會引發很大風險。信息安全的基礎在於密碼學,而經常使用的密碼學算法都是公開的,加密內容的保密依靠的是密鑰的保密,密鑰若是泄露,對於對稱密碼算法,根據用到的密鑰算法和加密後的密文,很容易獲得加密前的明文;對於非對稱密碼算法或者簽名算法,根據密鑰和要加密的明文,很容易得到計算出簽名值,從而僞造簽名。java
密鑰硬編碼在代碼中,而根據密鑰的用途不一樣,這致使了不一樣的安全風險,有的致使加密數據被破解,數據再也不保密,有的致使和服務器通訊的加簽被破解,引起各類血案,如下借用烏雲上已公佈的幾個APP漏洞來說講。c++
某P2P應用客戶端,用來加密數據的DES算法的密鑰硬編碼在Java代碼中,而DES算法是對稱密碼算法,既加密密鑰和解密密鑰相同。 算法
反編譯APP,發現DES算法:安全
發現DES算法的密鑰,硬編碼爲「yrdAppKe」,用來加密手勢密碼:服務器
將手勢密碼用DES加密後存放在本地LocusPassWordView.xml文件中:app
知道了密文和加密算法以及密鑰,經過解密操做,能夠從文件中恢復出原始的手勢密碼。或者使用新的生成新的手勢密碼,而與服務器通訊時接口中的Jason字段也用了DES算法和密鑰硬編碼爲「yRdappKY」:函數
和服務器通訊採用http傳輸,沒有使用https來加密通訊,若是採用中間人攻擊或者路由器鏡像,得到流量數據,能夠破解出用戶的通訊內容。測試
某租車APP與服務器通訊的接口採用http傳輸數據,而且有對傳輸的部分參數進行了加密,加密算法採用AES,可是密鑰硬編碼在java代碼中爲「shenzhoucar123123」,可被逆向分析出來,致使僞造請求,結合服務器端的漏洞,引發越權訪問的風險,如越權查看其它用戶的訂單等。 ui
和服務器通訊時的數據爲:編碼
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便可,能夠成功看到其餘人的訂單:
攻擊者徹底能夠作到使用其餘腳本從新實現相同的加密功能並拼接出各個接口請求,批量的刷取訂單信息和用戶其餘信息。
某酒店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庫,來生成字典。
簽名破解之後,就能夠構造發送給服務器的數據包進行其餘方面的安全測試,好比越權、重置密碼等。
經過以上案例,並總結下本身平時發現密鑰硬編碼的主要形式有:
一、密鑰直接明文存在sharedprefs文件中,這是最不安全的。
二、密鑰直接硬編碼在Java代碼中,這很不安全,dex文件很容易被逆向成java代碼。
三、將密鑰分紅不一樣的幾段,有的存儲在文件中、有的存儲在代碼中,最後將他們拼接起來,能夠將整個操做寫的很複雜,這由於仍是在java層,逆向者只要花點時間,也很容易被逆向。
四、用ndk開發,將密鑰放在so文件,加密解密操做都在so文件裏,這從必定程度上提升了的安全性,擋住了一些逆向者,可是有經驗的逆向者仍是會使用IDA破解的。
五、在so文件中不存儲密鑰,so文件中對密鑰進行加解密操做,將密鑰加密後的密鑰命名爲其餘普通文件,存放在assets目錄下或者其餘目錄下,接着在so文件裏面添加無關代碼(花指令),雖然能夠增長靜態分析難度,可是可使用動態調式的方法,追蹤加密解密函數,也能夠查找到密鑰內容。
保證密鑰的安全確是件難事,涉及到密鑰分發,存儲,失效回收,APP防反編譯和防調試,還有風險評估。能夠說在設備上安全存儲密鑰這個基本無解,只能選擇增大攻擊者的逆向成本,讓攻擊者知難而退。而要是普通開發者的話,作妥善保護密鑰這些事情這須要耗費很大的心血。
產品設計者或者開發者要明白本身的密鑰是作什麼用的,重要程度怎麼樣,密鑰被逆向出來會形成什麼風險,經過評估APP應用的重要程度來選擇相應的技術方案。
因此建議不妨試試阿里聚安全的安全加固和安全組件,其中安全組件中的安全加密功能提供了開發者密鑰的安全管理與加密算法實現,保證密鑰的安全性,實現安全的加解密操做;安全簽名功能實現客戶端請求的簽名處理,保證客戶端與服務端通訊請求不被僞造。安全加固提高安全等級,防止應用被逆向破解。這樣同時從應用層、運行層、native層提供多層次全方位立體防禦,另外還有安全沙箱、白盒加密、底層加固共同保證客戶端數據安全。攻防是不斷變化演進的,阿里聚安全提供的服務能實時更新客戶端模塊,經過阿里聚安全的漏洞掃描來檢測應用是否具備密鑰硬編碼風險,保證在攻防對抗中永遠處於上風。
專業的事情交給專業的人來作,本身的主要精力用來作功能開發或者業務邏輯,快速打造能贏得市場的可靠產品纔是王道。
[1] http://www.wooyun.org/bugs/wooyun-2010-0187287
[2] http://www.wooyun.org/bugs/wooyun-2010-0105766
[3] http://www.wooyun.org/bugs/wooyun-2015-0162907
[4] http://jaq.alibaba.com/safety?spm=a313e.7837752.1000001.1.zwCPfa
[5] https://www.zhihu.com/question/35136485/answer/84491440
做者:伊樵、呆狐@阿里聚安全,更多安全技術文章,請訪問阿里聚安全博客