1、前言
經常發現有開發者將密鑰硬編碼在Java代碼、文件中,這樣做會引起很大風險。
信息安全的基礎在於密碼學,而常用的密碼學算法都是公開的,加密內容的保密依靠的是密鑰的保密,密鑰如果泄露,對於對稱密碼算法,根據用到的密鑰算法和加密後的密文,很容易得到加密前的明文;對於非對稱密碼算法或者簽名算法,根據密鑰和要加密的明文,很容易獲得計算出簽名值,從而偽造簽名。
密鑰硬編碼在代碼中,而根據密鑰的用途不同,這導致了不同的安全風險,有的導致加密數據被破解,數據不再保密,有的導致和服務器通信的加簽被破解,引發各種血案,本文主要借用烏雲上已公佈的幾個APP漏洞來講講這其中的潛在風險和危害。
2、風險案例(一):某互聯網金融APP加密算法被破解導致敏感信息泄露
某P2P應用客户端,用來加密數據的DES算法的密鑰硬編碼在Java代碼中,而DES算法是對稱密碼算法,既加密密鑰和解密密鑰相同。反編譯APP,發現DES算法:
發現DES算法的密鑰,硬編碼為“yrdAppKe”,用來加密手勢密碼:
將手勢密碼用DES加密後存放在本地LocusPassWordView.xml文件中:
知道了密文和加密算法以及密鑰,通過解密操作,可以從文件中恢復出原始的手勢密碼。或者使用新的生成新的手勢密碼,而與服務器通信時接口中的Jason字段也用了DES算法和密鑰硬編碼為“yRdappKY”:
和服務器通信採用http傳輸,沒有使用https來加密通信,如果採用中間人攻擊或者路由器鏡像,獲得流量數據,可以破解出用户的通信內容。
3、風險案例(二):某租車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”:”11468061”}的請求:到現在請求中的數據加密如何實現的就清晰了,另外由於服務器權限控制不嚴,就可以構造訂單id的請求,達到越權訪問到其他用户的訂單。
其中uid設置為你自己的uid即可,可以成功看到其他人的訂單:
攻擊者完全可以做到使用其他腳本重新實現相同的加密功能並拼接出各個接口請求,批量的刷取訂單信息和用户其他信息。
4、風險案例(三):某酒店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庫,來生成字典。簽名破解以後,就可以構造發送給服務器的數據包進行其他方面的安全測試,比如越權、重置密碼等。
5、總結及建議
通過以上案例,並總結下自己平時發現密鑰硬編碼的主要形式有:
1)密鑰直接明文存在sharedprefs文件中,這是最不安全的。
2)密鑰直接硬編碼在Java代碼中,這很不安全,dex文件很容易被逆向成java代碼。
3)將密鑰分成不同的幾段,有的存儲在文件中、有的存儲在代碼中,最後將他們拼接起來,可以將整個操作寫的很複雜,這因為還是在java層,逆向者只要花點時間,也很容易被逆向。
4)用ndk開發,將密鑰放在so文件,加密解密操作都在so文件裏,這從一定程度上提高了的安全性,擋住了一些逆向者,但是有經驗的逆向者還是會使用IDA破解的。
5)在so文件中不存儲密鑰,so文件中對密鑰進行加解密操作,將密鑰加密後的密鑰命名為其他普通文件,存放在assets目錄下或者其他目錄下,接着在so文件裏面添加無關代碼(花指令),雖然可以增加靜態分析難度,但是可以使用動態調式的方法,追蹤加密解密函數,也可以查找到密鑰內容。
保證密鑰的安全確是件難事,涉及到密鑰分發,存儲,失效回收,APP防反編譯和防調試,還有風險評估。可以説在設備上安全存儲密鑰這個基本無解,只能選擇增大攻擊者的逆向成本,讓攻擊者知難而退。而要是普通開發者的話,做妥善保護密鑰這些事情這需要耗費很大的心血。
產品設計者或者開發者要明白自己的密鑰是做什麼用的,重要程度怎麼樣,密鑰被逆向出來會造成什麼風險,通過評估APP應用的重要程度來選擇相應的技術方案。
6、參考資料
[1] https://www.zhihu.com/question/35136485/answer/84491440
[2] 傳輸層安全協議SSL/TLS的Java平台實現簡介和Demo演示》
[3] 理論聯繫實際:一套典型的IM通信協議設計詳解(含安全層設計)》
[4] 微信新一代通信安全解決方案:基於TLS1.3的MMTLS詳解》
[5] 來自阿里OpenIM:打造安全可靠即時通訊服務的技術實踐分享》
[6] 簡述實時音視頻聊天中端到端加密(E2EE)的工作原理》
[7] 移動端安全通信的利器——端到端加密(E2EE)技術詳解》
[8] Web端即時通訊安全:跨站點WebSocket劫持漏洞詳解(含示例代碼)》
[9] 通俗易懂:一篇掌握即時通訊的消息傳輸安全原理》
[10] IM開發基礎知識補課(四):正確理解HTTP短連接中的Cookie、Session和Token》
[11] 快速讀懂量子通信、量子加密技術》
[12] 一分鐘理解 HTTPS 到底解決了什麼問題》
[13] 一篇讀懂HTTPS:加密原理、安全邏輯、數字證書等》
[14] 基於Netty的IM聊天加密技術學習:一文理清常見的加密概念、術語等》
[15] 手把手教你為基於Netty的IM生成自簽名SSL/TLS證書》
[16] 微信技術分享:揭秘微信後台安全特徵數據倉庫的架構設計》
[17] 即時通訊初學者必知必會的20個網絡編程和通信安全知識點》
[18] 零基礎IM開發入門(五):什麼是IM系統的端到端加密?》
7、IM安全系列文章
本文是IM通訊安全知識系列文章中的第 3 篇,總目錄如下:
《即時通訊安全篇(一):正確地理解和使用Android端加密算法》
《即時通訊安全篇(二):探討組合加密算法在IM中的應用》
《即時通訊安全篇(三):常用加解密算法與通訊安全講解》
《即時通訊安全篇(四):實例分析Android中密鑰硬編碼的風險》(☜ 本文)
《即時通訊安全篇(五):對稱加密技術在Android上的應用實踐》
《即時通訊安全篇(六):非對稱加密技術的原理與應用實踐》
《即時通訊安全篇(七):用JWT技術解決IM系統Socket長連接的身份認證痛點》
《即時通訊安全篇(八):如果這樣來理解HTTPS原理,一篇就夠了》
《即時通訊安全篇(九):你知道,HTTPS用的是對稱加密還是非對稱加密?》
《即時通訊安全篇(十):為什麼要用HTTPS?深入淺出,探密短連接的安全性》
《即時通訊安全篇(十一):IM聊天系統安全手段之通信連接層加密技術》
《即時通訊安全篇(十二):IM聊天系統安全手段之傳輸內容端到端加密技術》
《即時通訊安全篇(十三):信創必學,一文讀懂什麼是國密算法》
《即時通訊安全篇(十四):網絡端口的安全防護技術實踐》
《即時通訊安全篇(十五):詳解硬編碼密碼的泄漏風險及其掃描原理和工具》
(本文已同步發佈於:http://www.52im.net/thread-312-1-1.html)