這篇文章之前自己在公司的技術(shù)分享學(xué)院發(fā)表了⊥╇現(xiàn)在發(fā)到自己的博客上。
現(xiàn)在很多iOS的app沒有做任何的安全防范措施。今天我們就聊聊iOS開發(fā)人員平時怎么做才更安全分蓖。
一、網(wǎng)絡(luò)方面
用抓包工具可以抓取手機(jī)通信接口的數(shù)據(jù)尔许。以Charles為例么鹤,用Charles可以獲取http的所有明文數(shù)據(jù),配置好它的證書后就可以模擬中間人攻擊母债,獲取https加密前的明文數(shù)據(jù)午磁。
先簡要的說下什么是中間人攻擊:
①客戶端:“我是客戶端,給我你的公鑰”-> 服務(wù)端(被中間人截獲)毡们。
所以現(xiàn)在是:
客戶端->中間人迅皇,
②然后中間人把消息轉(zhuǎn)給服務(wù)端,也就是:
中間人->服務(wù)端衙熔。
③服務(wù)端把帶有公鑰的信息發(fā)送給客戶端登颓,但是被中間截獲。所以是:
服務(wù)端-[服務(wù)端的公鑰] ->中間人红氯。
④中間人把服務(wù)端的公鑰替換成自己的公鑰框咙,發(fā)送給客戶端咕痛,聲稱是服務(wù)端的公鑰:
中間人-[中間人的公鑰] ->客戶端
⑤客戶端用得到的公鑰加密,實際是用的中間人的公鑰進(jìn)行的加密喇嘱,所以中間人可以用自己的私鑰解密茉贡,獲取原始數(shù)據(jù),然后再用服務(wù)端的公鑰對原始數(shù)據(jù)(或者修改原始數(shù)據(jù)內(nèi)容)加密后發(fā)送給服務(wù)端者铜。
這樣中間人就可以獲取到雙方的通信數(shù)據(jù)腔丧,并可以制造虛假數(shù)據(jù)。
下面開始說如何防范:
1作烟、SSL Pinning
SSL Pinning的原理就是把服務(wù)端的公鑰存到客戶端中愉粤,客戶端會校驗服務(wù)端返回的證書是否和客戶端保存的一致,這樣就避免了中間人替換證書進(jìn)行的攻擊拿撩。
SSL Pinning的實現(xiàn)比較簡單衣厘,只需要把CA證書放入項目中,通過Security framework實現(xiàn)NSURLSession上的SSL Pinning压恒。如果用的是AFNetworking影暴,代碼更簡單一點(diǎn):
這樣通過Charles抓包就會報錯。
證書驗證有可以只驗證公鑰(AFSSLPinningModePublicKey)涎显,也可以完全驗證證書(AFSSLPinningModeCertificate)坤检。
但是用SSL Pinning有個很嚴(yán)重的問題,就是如果證書有問題期吓,只有發(fā)布新版本才能解決早歇。如果新版本一直審核不通過,app的網(wǎng)絡(luò)通信就全部掛掉了讨勤。
比如賽門鐵克(Symantec)證書被google和iOS12不信任的問題箭跳。如果app內(nèi)置了證書,就必須要重新發(fā)版潭千。
2谱姓、接口內(nèi)容進(jìn)行加密
很多的app接口只對請求的參數(shù)進(jìn)行加密和各種驗證,而接口返回過來的數(shù)據(jù)就是明文刨晴。如果不用SSL Pinning來防止中間人攻擊屉来,也可以把接口返回的數(shù)據(jù)也進(jìn)行加密,這樣抓包工具抓到包后也依然不能破解狈癞。
比如微信茄靠,微信中的接口用的是http協(xié)議,但是內(nèi)容全部進(jìn)行了加密蝶桶。
現(xiàn)在常用的是對稱加密慨绳,加密效率比較快。如果app里有的數(shù)據(jù)特別重要,還是要用非對稱加密脐雪,非對稱加密更安全厌小,但是效率會比較慢。
二战秋、日志
1璧亚、Swift日志
Swift中打印日志的語法可以用print,也可以用NSLog获询。但是盡量別用NSLog涨岁,因為Swift中用NSLog,系統(tǒng)日志中是能查到的吉嚣。可以通過pp助手蹬铺、iTools或者Xcode的Devices and Simulators 來查看系統(tǒng)日志尝哆。
用print打印日志就不會出現(xiàn)在系統(tǒng)日志中。
2甜攀、OC日志
在release環(huán)境下不要輸出NSLog日志秋泄。一般大家都會用宏定義解決,比如:
三规阀、信息的存儲
1恒序、密鑰
大部分的程序員喜歡直接把密鑰放到宏或者常量里。
如:#define AES_KEY @“aaa123"
這樣做很容易就可以被反編譯出來谁撼。安全性比較差歧胁。可以用以下方法加強(qiáng)安全厉碟,增加破解的難度喊巍。
1.1、對密鑰(A)進(jìn)行加密后定義為宏(B)箍鼓,使用的時候進(jìn)行解密得到密鑰(A)崭参。其中對密鑰A加密的密鑰為C。
因為在宏定義的時候我們?nèi)绻x成字符串款咖,會直接存在data段何暮,這樣破解者很容易獲取到。比較安全的做法是把C和B定義成uint8_t[]數(shù)組铐殃,這樣每個字符就會放到text段的每個單獨(dú)指令中海洼。指令執(zhí)行后生成字符串。這樣就會很安全背稼。
1.2贰军、用一段長文本,按規(guī)則提取出里面的密鑰,密鑰是隨機(jī)的词疼。
在服務(wù)端和客戶端定義一段長文本俯树,app端隨機(jī)生成起始位置和長度,把起始位置和長度進(jìn)行移位等操作贰盗,生成相應(yīng)的數(shù)字许饿,對數(shù)字進(jìn)行Base64編碼,生成的字符串 傳給服務(wù)端舵盈,服務(wù)端根據(jù)這個字符串 就能 解析出相關(guān)的密鑰陋率。
代碼如下:
這樣只是增加了破解者獲取密鑰的難度,其實并不能完全阻止破解者獲取秽晚。
2瓦糟、Keychain
越獄的iPhone可以查看導(dǎo)出Keychain保存的信息。Keychains的內(nèi)容存放在sqlite中赴蝇,目錄為:/private/var/Keychains菩浙。可以通過keychain-dump可以查看鑰匙串里存放的的內(nèi)容句伶。
所以保存到Keychain的數(shù)據(jù)一定要是加密之后的數(shù)據(jù)劲蜻。
3、plist考余、sqlite
plist先嬉、sqlite可以直接在ipa安裝文件中獲取到,所以不要在這些文件中存放重要信息楚堤,如果要保存疫蔓,就進(jìn)行加密后再存放。
四钾军、app加固
1鳄袍、代碼混淆
代碼混淆就是把易讀的類名、方法名替換成不易讀的名字吏恭。常用的方法有宏替換和腳本替換拗小。
比如本來方法名為:- (void)loadNetData; 進(jìn)行代碼混淆后,用class-dump導(dǎo)出頭文件后會顯示成修改后的方法名:- (void)showxhevaluatess;
2樱哼、用C語言
核心代碼用C語言寫哀九,但是C語言的函數(shù)也可以被hook,比如用fishhook搅幅。開發(fā)人員可以用靜態(tài)內(nèi)聯(lián)函數(shù)來防止hock阅束,破解者就只能去理解代碼的邏輯。
3茄唐、檢測tweak
可以檢測/Library/MobileSubstrate/DynamicLibraries 下的plist 文件里是否包含自己app的bundle id息裸。如果包含蝇更,可以進(jìn)行限制app的功能、提示該手機(jī)不安全 等呼盆。