天天看點

Android應用安全開發之淺談密鑰寫死

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

1 簡介

在阿裡聚安全的漏洞掃描器中和人工app安全審計中,經常發現有開發者将密鑰寫死在java代碼、檔案中,這樣做會引起很大風險。資訊安全的基礎在于密碼學,而常用的密碼學算法都是公開的,加密内容的保密依靠的是密鑰的保密,密鑰如果洩露,對于對稱密碼算法,根據用到的密鑰算法和加密後的密文,很容易得到加密前的明文;對于非對稱密碼算法或者簽名算法,根據密鑰和要加密的明文,很容易獲得計算出簽名值,進而僞造簽名。

密鑰寫死在代碼中,而根據密鑰的用途不同,這導緻了不同的安全風險,有的導緻加密資料被破解,資料不再保密,有的導緻和伺服器通信的加簽被破解,引發各種血案,以下借用烏雲上已公布的幾個app漏洞來講講。

某p2p應用用戶端,用來加密資料的des算法的密鑰寫死在java代碼中,而des算法是對稱密碼算法,既加密密鑰和解密密鑰相同。 

反編譯app,發現des算法:

Android應用安全開發之淺談密鑰寫死

發現des算法的密鑰,寫死為“yrdappke”,用來加密手勢密碼:

Android應用安全開發之淺談密鑰寫死

将手勢密碼用des加密後存放在本地locuspasswordview.xml檔案中:

Android應用安全開發之淺談密鑰寫死

知道了密文和加密算法以及密鑰,通過解密操作,可以從檔案中恢複出原始的手勢密碼。或者使用新的生成新的手勢密碼

而與伺服器通信時接口中的jason字段也用了des算法和密鑰寫死為“yrdappky”:

Android應用安全開發之淺談密鑰寫死
Android應用安全開發之淺談密鑰寫死

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

某租車app與伺服器通信的接口采用http傳輸資料,并且有對傳輸的部分參數進行了加密,加密算法采用aes,但是密鑰寫死在java代碼中為“shenzhoucar123123”,可被逆向分析出來,導緻僞造請求,結合伺服器端的漏洞,引起越權通路的風險,如越權檢視其它使用者的訂單等。 

和伺服器通信時的資料為:

Android應用安全開發之淺談密鑰寫死

q字段是加密後的内容。逆向app,從登入activity入手:

Android應用安全開發之淺談密鑰寫死

分析登入流程:v1是使用者名,v2是密碼,v3是pushid,在使用者名和密碼不為空并且長度不小于11情況下,執行loginoperate相關操作,追蹤loginoperate的實作,發現繼承自baseoperate,繼續追蹤baseoperate的實作:

Android應用安全開發之淺談密鑰寫死

在baseoperate的initurl()方法中,找到了app是怎麼生成請求資料的:

Android應用安全開發之淺談密鑰寫死

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

Android應用安全開發之淺談密鑰寫死

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

Android應用安全開發之淺談密鑰寫死

在onencrypt()函數中調用了encrypt()函數用來加密資料,追蹤encrypt()函數的實作,發現其使用aes算法,并且密鑰寫死在java代碼中為“shenzhoucar123123”

Android應用安全開發之淺談密鑰寫死

到現在請求中的資料加密如何實作的就清晰了,另外由于伺服器權限控制不嚴,就可以構造訂單id的請求,達到越權通路到其他使用者的訂單。 

構造{“id”:”11468061”}的請求:

Android應用安全開發之淺談密鑰寫死

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

Android應用安全開發之淺談密鑰寫死

攻擊者完全可以做到使用其他腳本重新實作相同的加密功能并拼接出各個接口請求,批量的刷取訂單資訊和使用者其他資訊。

某酒店app和伺服器通信時接口采用http通信,資料進行了加密,并且對傳輸參數進行簽名,在伺服器端校驗簽名,以檢查傳輸的資料是否被篡改,但是加簽算法和密鑰被逆向分析,可導緻加簽機制失效,攻擊者可任意僞造請求包,若結合伺服器端的權限控制有漏洞,則可引發越權風險等。

app和伺服器通信的原始包如下圖,可以看到有加簽字段sign:

Android應用安全開發之淺談密鑰寫死

逆向app定位到加密算法的邏輯代碼,com.htinns.biz.httputils.class,其實作邏輯為:

Android應用安全開發之淺談密鑰寫死

原始資料是unsigndata,使用rc4算法加密,密鑰為key變量所代表的值,加密後的資料為signdata,傳輸的資料時的data字段為signdata。 

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

sendsign()算法是用c或c++寫的,放入了so庫,其他重要算法都是用java寫的。 

可以使用ida逆向分析so庫,找到sendsign()方法

Android應用安全開發之淺談密鑰寫死

而烏雲漏洞送出者采用的是分析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層提供多層次全方位立體防護,另外還有安全沙箱、白盒加密、底層加強共同保證用戶端資料安全。攻防是不斷變化演進的,阿裡聚安全提供的服務能實時更新用戶端子產品,通過阿裡聚安全的漏洞掃描來檢測應用是否具有密鑰寫死風險,保證在攻防對抗中永遠處于上風。

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

阿裡聚安全由阿裡巴巴移動安全部出品,面向企業和開發者提供企業安全解決方案,全面覆寫移動安全、資料風控、内容安全、實人認證等次元,并在業界率先提出“以業務為中心的安全”,賦能生态,與行業共享阿裡巴巴集團多年沉澱的專業安全能力。