版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2017.08.17 |
前言
在這個(gè)信息爆炸的年代,特別是一些敏感的行業(yè),比如金融業(yè)和銀行卡相關(guān)等等,這都對(duì)
app
的安全機(jī)制有更高的需求,很多大公司都有安全 部門,用于檢測自己產(chǎn)品的安全性,但是及時(shí)是這樣,安全問題仍然被不斷曝出,接下來幾篇我們主要說一下app
的安全機(jī)制。
APP安全涉及方面
剛接觸app安全大家可能會(huì)有一些疑問,app安全到底涉及到哪些方面,或者說app安全應(yīng)該注意什么?
app安全主要應(yīng)該注意下面幾個(gè)方面:
ipa文件安全
我們?cè)?code>appleStore下載的加殼后的ipa
文件,里面會(huì)有很多的資源包,不要在.plist
文件、項(xiàng)目中的靜態(tài)文件中存儲(chǔ)關(guān)鍵的信息,如要保存,需要加密處理??梢岳肕AC上的PP軟件助手,將ipa文件拷貝到電腦,直接就能獲取ios的系統(tǒng)目錄。如下圖所示。
ipa文件的反編譯工具IDA
前面已經(jīng)說過了,從appleStore下載的都是加殼的ipa文件,想要去殼,可以使用clutch
、dumpdecrypted
、使用gdb
調(diào)試 等解密去殼工具,如果手機(jī)是越獄的,則可以從PP助手上下載ipa包,直接就是脫殼后的,還有就是xcode打包的ipa也是沒有殼的。
建立新的項(xiàng)目加幾句代碼:
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 70, 200, 100)];
label.text = @"CeShiLabel007";
label.backgroundColor = [UIColor redColor];
[self.view addSubview:label];
}
接著就是將項(xiàng)目打包,獲取的ipa文件解壓后得到.app文件。
下面就下載好IDA,并安裝打開如下所示。
利用IDA破解ipa文件,可以獲取下面的圖示。
由上面可見,字符串完全可以反編譯出來。所以盡量不要在代碼里放一些 關(guān)鍵的數(shù)據(jù),可以通過接口來獲取?;蛘甙褦?shù)據(jù)進(jìn)行加密。
Hopper Disassembler反編譯工具
具體方法還和IDA類似,就是下載軟件和進(jìn)行反編譯,下面引用一個(gè)技術(shù)大牛反編譯微信的圖,如下所示。
這里可以很清楚的看到QQContactInfoViewController
里面的代碼是如何寫的。上面兩種涉及到的都是代碼的反編譯,其實(shí)就是逆向工程。
沙盒安全
app的沙盒也是需要注意的地方,里面的文件比如sqlite、plist等等,不要保存敏感和關(guān)鍵信息,如要保存,同樣需要加密。 這里需要注意:
-
.app
文件里面存放的使用程序本身的數(shù)據(jù),打包時(shí)候的資源文件都在里面,這個(gè)目錄不會(huì)被iTunes同步; -
Documents
:存儲(chǔ)不可再生的關(guān)鍵性數(shù)據(jù),不會(huì)被iTunes同步; -
Library
:保存配置文件和一些其他文件,NSUserDefault
會(huì)存儲(chǔ)到Library
下的Preferences
中 的plist
文件中,所以不要在NSUserDefault
中存一些關(guān)鍵數(shù)據(jù),或者存儲(chǔ)的時(shí)候進(jìn)行AES
加密,會(huì)被iTunes
同步; -
temp
:臨時(shí)文件,不需要時(shí)候手動(dòng)刪除其內(nèi)的文件,這個(gè)目錄不會(huì)被iTunes同步。
下面重新回顧一下沙盒的文檔結(jié)構(gòu)。
源代碼安全
通過file
、class-dump
、theos
、otool
等工具,黑客可以分析編譯之后的二進(jìn)制程序文件,不過相對(duì)于這些工具來說,IDA
的威脅最大。IDA是一個(gè)收費(fèi)的反匯編工具,對(duì)于Objective-C代碼,它常常可以反匯編到可以方便閱讀的程度,這對(duì)于程序的安全性,也是一個(gè)很大的危害。因?yàn)橥ㄟ^閱讀源碼,黑客可以更加方便地分析出應(yīng)用的通信協(xié)議和數(shù)據(jù)加密方式。
同樣不要在代碼中存儲(chǔ)關(guān)鍵信息,比如通信接口的AES
加密的密鑰,這是因?yàn)橛妹摎すぞ呖梢詫?duì)加殼的ipa文件進(jìn)行處理,越獄手機(jī)就是這么越獄的,在利用IDA
、Hopper
進(jìn)行反編譯和分析,就可以得到很容易理解的偽代碼。
- 關(guān)鍵數(shù)據(jù)不要保存在本地,盡量通過接口進(jìn)行獲取。
- 如果非要保存關(guān)鍵數(shù)據(jù),那么一定要加密后保存,運(yùn)行時(shí)候解密獲取數(shù)據(jù)。
- 密鑰要定期更換,如果密鑰是才能夠服務(wù)端獲取,那么服務(wù)端進(jìn)行更新處理等。
- 密鑰如果寫在代碼里,app升級(jí)版本的時(shí)候,新版本app對(duì)應(yīng)接口版本修改為新的秘鑰,舊的接口版本和APP版本還有以前舊的秘鑰。
對(duì)于IDA這類工具,我們的應(yīng)對(duì)措施就比較少了。除了可以用一些宏來簡單混淆類名外,也可以將關(guān)鍵的邏輯用純C語言來實(shí)現(xiàn)。例如微信的iOS端的通信底層,就是用C語言實(shí)現(xiàn)的。這樣的方式除了能保證通信協(xié)議的安全外,也可以在iOS和Android等多個(gè)平臺(tái)使用同一套底層通信代碼,達(dá)到復(fù)用的目的。
網(wǎng)絡(luò)安全
網(wǎng)絡(luò)安全很大一部分就是網(wǎng)絡(luò)通信安全,在網(wǎng)絡(luò)傳輸?shù)倪^程中存在不安全的結(jié)點(diǎn),所以我們應(yīng)該對(duì)敏感數(shù)據(jù)進(jìn)行加密,同于保證用戶的信息安全,黑客可以設(shè)置網(wǎng)絡(luò)代理服務(wù)器,截獲所有的網(wǎng)絡(luò)請(qǐng)求,即使是https加密通信,黑客仍然可以使用中間人攻擊Man-In-The-Middle Attack
,指的是攻擊者與通信的兩端分別創(chuàng)建獨(dú)立的聯(lián)系,并交換其所收到的數(shù)據(jù),使通信的兩端認(rèn)為他們正在通過一個(gè)私密的連接與對(duì)方直接對(duì)話,但事實(shí)上,整個(gè)會(huì)話都被攻擊者完全控制)來截取通信內(nèi)容。
1. 通信協(xié)議安全相關(guān)
在成功破解了通信協(xié)議后,黑客可以模擬客戶端登錄,進(jìn)而偽造一些用戶行為,可能對(duì)用戶數(shù)據(jù)造成危害。
下面我們就先了解下關(guān)于https方面的內(nèi)容。
我們先了解下https ,HTTPS從最終的數(shù)據(jù)解析的角度,與HTTP沒有任何的區(qū)別,HTTPS就是將HTTP協(xié)議數(shù)據(jù)包放到SSL/TSL
層加密后,在TCP/IP
層組成IP數(shù)據(jù)報(bào)去傳輸,以此保證傳輸數(shù)據(jù)的安全;而對(duì)于接收端,在SSL/TSL將接收的數(shù)據(jù)包解密之后,將數(shù)據(jù)傳給HTTP協(xié)議層,就是普通的HTTP數(shù)據(jù)。HTTP和SSL/TSL都處于OSI模型的應(yīng)用層
。從HTTP切換到HTTPS是一個(gè)非常簡單的過程。
它雖然號(hào)稱是安全的,但是也是可以抓包和解析的,所以網(wǎng)絡(luò)通信一定要有自己的加密方式,接口返回的數(shù)據(jù)最好也加密。
下面我們就看一下charles
抓包。
http抓包
http抓包我們需要按照下面步驟配置charles
。
- 打開
Charles
程序。 - 查看Mac電腦的IP地址,如
192.168.1.7
。 - 打開iOS設(shè)置,進(jìn)入當(dāng)前wifi連接,設(shè)置HTTP代理Group,將服務(wù)器填為上一步中獲得的IP,即
192.168.1.7
,端口填8888
。 - iOS設(shè)備打開你要抓包的app進(jìn)行網(wǎng)絡(luò)操作。
- Charles彈出確認(rèn)框,點(diǎn)擊Allow按鈕即可。
https老版本抓包
- 下載Charles證書,解壓后導(dǎo)入到iOS設(shè)備中(將
crt
文件作為郵件附件發(fā)給自己,再在iOS設(shè)備中點(diǎn)擊附件即可安裝;也可上傳至dropbox
之類的網(wǎng)盤,通過safari下載安裝)。 - 在Charles的工具欄上點(diǎn)擊設(shè)置按鈕,選擇
Proxy Settings
,切換到SSL選項(xiàng)卡,選中Enable SSL Proxying
。 - 這一步跟
Fiddler
不同,F(xiàn)iddler安裝證書后就可以抓HTTPS網(wǎng)址的包了,Charles 還 需要在上一步的SSL選項(xiàng)卡的Locations表單填寫要抓包的域名和端口,點(diǎn)擊Add按鈕,在彈出的表單中Host
填寫域名,比如填api.instagram.com
,Port
填443
。
https新版本抓包
Charles新版本的 Proxy Settings 選項(xiàng)里是沒有 SSL選項(xiàng)卡的。在左側(cè)的域名上點(diǎn)右鍵
:Enable SSL Proxying
,就可以用了。
https相關(guān)代碼書寫
app中一般用的就是AFNetworking
這個(gè)框架,常見的問題包括:
- 信任任何證書
在AFNetworking
中定義allowInvalidCertificates = true
,就是表示忽略所有的證書。
AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates = YES;
這種情況的危險(xiǎn)就是可以用charles破解https加密的數(shù)據(jù),在一般測試環(huán)境不用CA發(fā)布的證書,而是自簽名證書,訪問的也不是域名,而是IP??梢允褂?code>#ifdef DEBUG來進(jìn)行設(shè)置。
#ifdef DEBUG
manager.securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy.validatesDomainName = NO;
#endif
- 信任證書管理機(jī)構(gòu)(CA)頒發(fā)的證書
黑客可以買到這個(gè)證書,AFNetworking2.5.2
以及之前的版本都有漏洞,在不安全網(wǎng)路中黑客就可以使用CA證書對(duì)該app的https加密數(shù)據(jù)進(jìn)行監(jiān)聽和篡改。
- 信任合法證書,采取服務(wù)器和客戶端雙向認(rèn)證
雖然安全性提高了不少不過還是可以破解的,可以看這篇文章Bypassing OpenSSL Certificate Pinning in iOS Apps
所以,不要完全信任HTTPS的安全性,任何的協(xié)議、代碼都是會(huì)有漏洞的,關(guān)鍵的數(shù)據(jù)一定要自己進(jìn)行加密。
有關(guān)證書的配置在AFNetworking上的代碼如下所示:
NSURL * url = [NSURL URLWithString:@"https://www.google.com"];
AFHTTPRequestOperationManager * requestOperationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
dispatch_queue_t requestQueue = dispatch_create_serial_queue_for_name("kRequestCompletionQueue");
requestOperationManager.completionQueue = requestQueue;
AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
//allowInvalidCertificates 是否允許無效證書(也就是自建的證書),默認(rèn)為NO
//如果是需要驗(yàn)證自建證書,需要設(shè)置為YES
securityPolicy.allowInvalidCertificates = YES;
//validatesDomainName 是否需要驗(yàn)證域名,默認(rèn)為YES;
//假如證書的域名與你請(qǐng)求的域名不一致,需把該項(xiàng)設(shè)置為NO
//主要用于這種情況:客戶端請(qǐng)求的是子域名,而證書上的是另外一個(gè)域名。因?yàn)镾SL證書上的域名是獨(dú)立的,假如證書上注冊(cè)的域名是www.google.com,那么mail.google.com是無法驗(yàn)證通過的;當(dāng)然,有錢可以注冊(cè)通配符的域名*.google.com,但這個(gè)還是比較貴的。
securityPolicy.validatesDomainName = NO;
//validatesCertificateChain 是否驗(yàn)證整個(gè)證書鏈,默認(rèn)為YES
//設(shè)置為YES,會(huì)將服務(wù)器返回的Trust Object上的證書鏈與本地導(dǎo)入的證書進(jìn)行對(duì)比,這就意味著,假如你的證書鏈?zhǔn)沁@樣的:
//GeoTrust Global CA
// Google Internet Authority G2
// *.google.com
//那么,除了導(dǎo)入*.google.com之外,還需要導(dǎo)入證書鏈上所有的CA證書(GeoTrust Global CA, Google Internet Authority G2);
//如是自建證書的時(shí)候,可以設(shè)置為YES,增強(qiáng)安全性;假如是信任的CA所簽發(fā)的證書,則建議關(guān)閉該驗(yàn)證;
securityPolicy.validatesCertificateChain = NO;
requestOperationManager.securityPolicy = securityPolicy;
2. 登錄安全相關(guān)
很多app都是明碼傳遞賬號(hào)和密碼的,那么黑客只要截獲網(wǎng)絡(luò)請(qǐng)求,就可以獲得該app的賬號(hào)和密碼,由于現(xiàn)代人的習(xí)慣,很多的賬號(hào)和密碼都是一個(gè),那么后果是不可以想象的。
關(guān)于登錄的加密其實(shí)有很多方法,這里介紹一種:先生成一對(duì)加密的公私鑰,客戶端登錄的時(shí)候,使用公鑰將用戶的密碼加密并傳輸?shù)椒?wù)器,服務(wù)器用私鑰進(jìn)行解密,然后加鹽處理,再多次進(jìn)行MD5處理,在和數(shù)據(jù)庫里面存儲(chǔ)的同樣方法處理過的密碼匹配,如果一致,匹配成功,則表示可以登錄。
3. IAP安全相關(guān)
iOS應(yīng)用內(nèi)支付(IAP)是眾多應(yīng)用贏利的方式,通過先讓用戶免費(fèi)試用或試玩,然后提供應(yīng)用內(nèi)支付來為愿意付費(fèi)的用戶提供更強(qiáng)大的功能,這種模式特別適合不習(xí)慣一開始就掏錢的中國用戶。但由于國內(nèi)越獄用戶的比例比較大,所以我們也需要注意應(yīng)用內(nèi)支付環(huán)節(jié)中的安全問題。簡單來說,越獄后的手機(jī)由于沒有沙盒作為保護(hù),黑客可以對(duì)系統(tǒng)進(jìn)行任意地修改,所以在支付過程中,蘋果返回的已付款成功的憑證可能是偽造的。客戶端拿到付款憑證之后,還需要將憑證上傳到自己的服務(wù)器上,進(jìn)行二次驗(yàn)證,以保證憑證的真實(shí)性。
另外,我們發(fā)現(xiàn)越獄用戶的手機(jī)上,很可能被黑客用中間人攻擊技術(shù)來劫持支付憑證。這對(duì)于黑客有什么好處呢?因?yàn)樘O果為了保護(hù)用戶的隱私,支付憑證中并不包含任何用戶的賬號(hào)信息,所以我們的應(yīng)用和服務(wù)器無法知道這個(gè)憑證是誰買的,而只能知道這個(gè)憑證是真的還是假的。所以在驗(yàn)證憑證時(shí),哪個(gè)賬號(hào)發(fā)起了驗(yàn)證請(qǐng)求,我們就默認(rèn)這個(gè)憑證是該賬號(hào)擁有的。如果黑客將憑證截獲,就可以偽裝成真實(shí)用戶來驗(yàn)證憑證或者轉(zhuǎn)手出售獲利。打個(gè)比方,這就類似于很多商場的購物卡一樣,由于是不記名的,黑客如果將你買的購物卡偷竊然后去刷卡購物,商場是無法簡單地區(qū)分出來的。因此,對(duì)于應(yīng)用內(nèi)支付,開發(fā)者除了需要仔細(xì)地驗(yàn)證購買憑證外,也需要告知用戶在越獄手機(jī)上進(jìn)行支付的風(fēng)險(xiǎn)。
Reveal UI布局安全
Reveal
是一個(gè)很好的UI查看軟件,大家調(diào)試的時(shí)候很多時(shí)候都使用過,但是這里我們知道如果手機(jī)不越獄,只能查看自己調(diào)試的APP,但是如果是越獄的手機(jī),那么還可以查看別的app,如淘寶、去哪兒網(wǎng)等等。
代碼調(diào)試安全
在release
環(huán)境下NSLog
不要打印日志 否則iOS系統(tǒng)日志里都可以查看到,在.pch
文件中加下面的幾行代碼就可以解決。
1 #ifdef DEBUG
2 #define NSLog(...) NSLog(__VA_ARGS__)
3 #define debugMethod() NSLog(@"%s", __func__)
4 #else
5 #define NSLog(...)
6 #define debugMethod()
7 #endif
現(xiàn)在很多app是用Swift
寫的,在Swift 文件中是允許用 NSLog 的語法來打印,但是 不要這么做,因?yàn)檫@樣就會(huì)導(dǎo)致這段代碼在 release環(huán)境 中也可以正常輸出。通過PP助手
、iTools
,可以直接 查看 iOS的系統(tǒng)日志。也可以直接通過Xcode-Window-Devices - 點(diǎn)最下面的向上的小箭頭
,來看日志。所以Swift中打印還是用print
吧。
參考文章
1. 如何確保APP的安全性
2. [iOS]APP安全方面做的幾個(gè)點(diǎn)總結(jié)
3. iOS應(yīng)用安全開發(fā),你不知道的那些事
4. iOS APP 如何做才安全
5. iOS APP安全雜談之三
6. Jonathan Zdziarski《Hacking and Securing ios Application》 沙梓社,吳航《ios應(yīng)用逆向工程》
后記
其實(shí)總的來說app安全,主要可以歸納為
網(wǎng)絡(luò)安全
、本地文件和數(shù)據(jù)安全
、源代碼
安全三個(gè)大的方面,每個(gè)方面都有很多措施可以保證安全性,也要注意細(xì)節(jié),接下來會(huì)和大家細(xì)說這幾個(gè)方面。未完,待續(xù)~~~