前言
安全問題在互聯網,軟件領域從來都是不可忽視的,而隨著移動互聯網的發展,移動端不管是在設備持有量上,還是在用戶數量上,都已經超越傳統PC端,成為第一大入口端。因此提高對于移動安全領域的關注,加強移動端的安全等級,是很有必要的。
而一般情況下,移動端安全大致上可以分為以下幾個維度:
- Web安全
- 網絡通訊安全
- 本地安全
Web安全,主要考慮Web服務中每一層可能的漏洞,及由此衍生的一系列安全問題,如:存儲層中的SQL注入問題,Nginx(容器)層的DDoS問題,前端層級的XSS跨站腳本問題等。
網絡通訊安全,需要考慮通訊過程中信息的安全性,防止由于信息泄露導致的其他安全問題,比如:常見的各種形式的中間人問題等。
本地安全主要指客戶端本地環境與數據的安全,以及代碼被破解獲得所導致的安全問題,如:明文存儲問題,惡意二次打包問題,越權操作問題等。
其中,本地安全攻擊大多發生在攻擊者自己手機上,開發者和運維較難感知,所以容易被大家忽略,從而很容易成為整個鏈路的安全短板。本文將著重就本地安全,公司所采取的安全圖片方案跟大家做一個介紹,其中的一些細節基于安全考慮會略去,保留其基本思路,希望對大家有所幫助,也歡迎共同交流。
安全圖片解決方案
安全圖片方案解決了本地安全的幾個問題:
- 明文存儲,過度依賴系統安全性(iOS:KC/UserDefault;Android:KeyStore/SharedPreference)
- 惡意二次打包
- 容易被逆向,被調試
- 敏感信息寫入代碼
優點
- 使用便捷簡單
- 對工程及代碼侵入性較小
- 顯著提高APP的安全性
當然,該方案也存在一些問題,比如字段的存取需要走I/O以及二進制流處理,一定程度上會影響APP性能,同時安全性建立在SDK本身和安全圖片安全性的基礎上,容易在這一塊出現安全短板。
所幸,正常獲取字段的開銷時間一般都不會超過30毫秒(視具體算法而定)。而安全性問題,還是需要靠持續加強SDK安全性,強化安全圖片使用的算法,來提升短板,增大破解成本。
安全圖片
我們的安全圖片方案主要包含了安全圖片生成,安全圖片消費,二次打包檢查,調試檢查等功能,這些功能分布在安全SDK及圖片生成工具(以web形式提供)中。
結構如下:
可以看到,圖片文件作為信息加密和存儲的中心媒介,在其中起到了非常重要的作用。其實這里也可以用其他形式的文件,比如文本文件,視頻文件,音頻文件。
那么為什么要用圖片呢?綜合來看:
- 圖片資源在我們的移動項目中非常常見,有比較大的混淆性
- 圖片的易操作性比較強,比較容易插入想要加密的信息
- 讀取性能比較好,同時容易優化
所以技術選型過程中,根據實際業務形態,也可能選擇音頻、視頻、特殊文本等其他文件作為中心媒介,比如富含大量音視頻信息的APP/游戲,包含很多特殊格式電子書的電子書閱讀軟件,等等。
安全圖片方案-流程
從結構圖可以看出,我們的圖片解決方案包含了"獲取web端(圖片生成工具)生成的安全圖片","在APP中通過SDK使用安全圖片"這兩個流程。
獲取安全圖片
獲取安全圖片流程中,由于iOS和Android各自的包檢查依賴項不一樣,在輸入項上會有所區別,iOS使用BundleID、Android使用keystore的數字簽名SHA1值作為檢查項。
在獲取到用戶輸入信息之后,還需要一個加密的關鍵信息:加密密鑰。
這里可以有三種思路:
- 由server端生成密鑰,存儲在服務器端,之后通過安全的通訊協議(如https)從服務器獲取。
- 由server端生成密鑰,之后按照某些算法或者規則插入到圖片當中
- 從圖片中按照某種規則或者算法,生成一個密鑰
這三種方式各有利弊:
- 第一種方案的安全性基于通訊安全,能在本地安全被攻破的情況下保持安全鏈路完整,隔離不同業務方的密鑰安全性,但是隨之也帶來了一些新的問題,如:中間人攻擊、網絡性能問題等。
- 第二種針對業務方較多的情況下,安全等級較高,能做到不同業務方不同版本APP的安全性隔離,在密鑰生成算法或者密鑰規則泄露后(低概率),可以及時更新密鑰,阻止安全事故的擴大化;但同時也存在,可能對圖片的使用造成輕微影響,算法可能較為復雜,在讀取時對性能造成影響,算法門檻較高等問題。
- 最后一種較為簡單,門檻低,同時對圖片影響較小,讀取開銷相對較小,也能滿足一般情況下的密鑰獲取方案;但當密鑰獲取算法或規則泄露后(低概率),阻止安全事故擴大化的成本相對較高,容易成為安全短板。
在得到了密鑰之后,結合用戶輸入的信息,通過對稱加密算法,生成加密后的密文再寫入圖片之中。
寫入圖片的方法很多,比如如下兩種:
- 在jpg中,可以通過寫入Exif區,這塊區域存入了相機拍攝信息:時間、拍攝地點等等,可以在這個區域存入加密后的信息,實現圖片的無損加密。
- 在png中,可以在IEND(png文件尾部)區域后追加加密信息,在此區域追加的信息不會影響圖像的正常讀取。但是用png格式需要注意在編譯的時候會被編譯器自動壓縮,從而失去加密的信息。可以考慮動態獲取安全圖片來規避這個問題,比如從網絡中加載圖片再寫入本地。
上述方案相對比較簡單,如果對安全性有更高的需求,可以從圖片本身結構入手,比如通過你要加密的信息構造出RGB、alpha等信息,然后按照標準png/jpg/bmp等格式構造出一張全新的圖片,也可以在中間按照某種規則穿插一些混淆數據。這樣生成的圖片加密程度較高,不容易破解,但相對來說開發成本較高。
消費安全圖片
目前我們的方案中,用戶拿到包含密文和密鑰的安全圖片之后,需要把安全圖片導入工程文件中(圖片可以正常使用),然后由安全SDK獲取圖片中的密鑰及密文,用密鑰解密密文后,獲取用戶所需要的信息。這里的過程基本就是安全圖片生成流程的一個反向過程。
不過和圖片生成流程不同的是,安全SDK同時需要考慮SDK本身的安全性,所需要做一些額外的事情,比如:
- 檢測APP是否被二次打包
- 檢測是否正在被調試
- SDK關鍵方法混淆
- 使用c/c++增加逆向成本
限于篇幅,這里暫不展開討論。
使用
使用工具生成安全圖片
我們的工具是基于h5和node構建的,入口放在了內部移動門戶上,使用非常方便。
界面如圖:
只需要填入對應的BundleID(SHA1)/Key/Value,再傳入一張APP中用到的圖片,工具就會根據傳入信息生成安全圖片,并讓用戶下載至本地。
使用安全圖片獲取KEY
整合SDK到APP中,并導入安全圖片后,SDK的使用方式非常簡單,直接在APP中調用如下代碼,即可獲取所需key對應的value:
String value = SecuritySDK.get(String key);
總結
本文闡述了我們實現安全圖片方案的基本思路,以及安全圖片方案的流程。當然,其中還有一些具體實現,以及我們仍未完成但計劃去完善的東西,包括但不僅限于以下:
- 包加固,APP加固
- 混淆的解決方案
- 防調試的方法
- 防逆向的方法
- 安全環境監測/風險控制/設備指紋
- 等等
這些在短短的一篇博客中都難以詳盡表述,所以會在后續的文章中,再一一和大家詳細說明,共同探討。也歡迎各位不吝賜教,暢所欲言,發表自己的意見和感想。