如何使用SSL pinning来使你的iOS APP更加安全
SSL pinning在構(gòu)建一個高度安全的移動APP上扮演了一個十分重要的角色。然而如今好多用戶在使用無線移動設(shè)備去訪問無數(shù)不安全的無線網(wǎng)絡(luò)。
這篇文章主要覆蓋了SSL pinning 技術(shù),來幫助我們處理最常見的安全攻擊--中間人攻擊(MITM)。
SSL(Secure Socket Layer 安全套接字層)確保客戶端-服務(wù)器在HTTP請求的方式上將通訊內(nèi)容加密----被指定為HTTPS(SSL上的HTTP)。這種加密體系是基于PKI(Pbulic Key Infrastructure,公鑰體系)和(Session key,會話key)。其中Session key 被引進(jìn)的原因是對于公鑰/私鑰的加密和解密會消耗處理能力,會是整個交流進(jìn)程速度變慢。
SSL 安全---鑒定
SSL安全是基于證書的信任鏈。當(dāng)一個通信開始的時候,客戶端檢查服務(wù)器的SSL證書,檢查這個證書是否被信用根CA機(jī)構(gòu)或者其他用戶信任結(jié)構(gòu)所信任。
盡管SSL通信被認(rèn)為是一個非常安全的和堅(jiān)不可摧的,但是中間人攻擊依然還是真實(shí)存在的威脅,它可以用好幾種方法去實(shí)現(xiàn),例如ARP 緩存中毒、DNS 欺騙等。
對于ARP緩存中毒,可以簡單理解為中間人通過地址解析協(xié)議的IP映射到設(shè)備的Mac地址這一特性進(jìn)行攻擊。例如,我們用一下三個角色來描述一個簡單的網(wǎng)絡(luò):
一個普通的用戶設(shè)備U
攻擊者的設(shè)備A
路由器R
攻擊者的設(shè)備A可以發(fā)送一個ARP依賴包給用戶設(shè)備U,把他自己偽裝成路由器R。為了完成中間人攻擊,A發(fā)送另一個ARP依賴給R,告訴路由器它就是U。這樣的話,A就成了U和R溝通的中間者,A就可以竊聽和攔截信息。IP轉(zhuǎn)發(fā)經(jīng)常被用于攻擊者在用戶設(shè)備和路由器的無縫交流。也就是說通過IP轉(zhuǎn)發(fā),攻擊者可以竊取和監(jiān)聽,但是用戶和路由器是無感知的。
DNS欺騙主要在于攻擊者破話服務(wù)器的域名映射。攻擊者嘗試強(qiáng)迫DNS去返回一個不正確的地址,而這個地址就是攻擊者的計(jì)算機(jī)地址。
SSL pinning
我們使用SSL pinning來確保app通信僅僅發(fā)生在指定的服務(wù)器上。其中的先決條件就是將目標(biāo)服務(wù)器的SSL證書放到app里面。這個證書被用于會話配置。這里我簡單介紹SSL pinning在NSURLSession上的使用。
當(dāng)談到NSURLSession使用SSL pinning有點(diǎn)棘手,因?yàn)樵贏FNetworking中,其本身已經(jīng)有封裝好的類可以使用來進(jìn)行配置。這里沒有辦法去設(shè)置一組證書來自動取消所有本地證書不匹配的response。我們需要手動執(zhí)行檢查來實(shí)現(xiàn)在NSURLSession上的SSL pinning。我們很榮幸的是我們可以用Security's framework C API。
我們可以先來一個默認(rèn)會話配置的NSURLSession對象。
??NSURLSessionConfiguration *seeConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
? ? NSURLSession *session = [NSURLSession sessionWithConfiguration:seeConfig delegate:self delegateQueue:nil];
NSURLSession使用NSURLSessionTask來發(fā)送一個請求,我么使用dataTaskWithURL:completionHandler:方法來進(jìn)行SSL pinning 測試。發(fā)送請求類似于下面這樣:
NSURLSessionDataTask *task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:testURL]];[task resume];該方法僅僅是返回了一個task對象,然后使用resume方法發(fā)送請求,或者說是執(zhí)行任務(wù)。
使SSL pinning在:
URLSession:didReceiveChallenge:completionHandler:delegate方法中實(shí)現(xiàn)。在NSURLSession對象上,我們設(shè)置自己為代理來調(diào)用方法。
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {//得到遠(yuǎn)程證書SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);//設(shè)置ssl政策來檢測主域名NSMutableArray *policies = [NSMutableArray array];[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host)];//驗(yàn)證服務(wù)器證書 SecTrustResultType result;SecTrustEvaluate(serverTrust, &result);BOOL certificateIsValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);//得到本地和遠(yuǎn)程證書dataNSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));NSString *pathToCer = [[NSBundle mainBundle] pathForResource:@"brhttp" ofType:@"cer"];NSData *localCertificate = [NSData dataWithContentsOfFile:pathToCer];//檢查if ([remoteCertificateData isEqualToData:localCertificate] && certificateIsValid) {NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];completionHandler(NSURLSessionAuthChallengeUseCredential,credential);}else {completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,NULL);} }在方法的開始,我們使用SecTrustGetCertificateAtIndex來得到服務(wù)器的SSL證書數(shù)據(jù)。然后使用證書評估設(shè)置policies。證書使用SecTrustEvaluate評估,然后返回以下幾種認(rèn)證結(jié)果類型之一:
typedef uint32_t SecTrustResultType; enum {kSecTrustResultInvalid = 0,kSecTrustResultProceed = 1,kSecTrustResultConfirm SEC_DEPRECATED_ATTRIBUTE = 2,kSecTrustResultDeny = 3,kSecTrustResultUnspecified = 4,kSecTrustResultRecoverableTrustFailure = 5,kSecTrustResultFatalTrustFailure = 6,kSecTrustResultOtherError = 7 };如果我們得到kSecTrustResultProceed和kSecTrustResultUnspecified之外的類型結(jié)果,我們可以認(rèn)為證書是無效的(不被信任的)。
至今為止我們除了檢測遠(yuǎn)程服務(wù)器證書評估外,還沒有做其他事情,對于SSL pinning 檢測我們需要通過SecCertificateRef來得到他的NSData。這個SecCertificateRef來自于challenge.protectionSpace.serverTrust。而本地的NSData來自本地的.cer證書文件。然后我們使用isEqual來進(jìn)行SSL pinning。
如果遠(yuǎn)程服務(wù)器證書的NSData等于本地的證書data,那么就可以通過評估,我們可以驗(yàn)證服務(wù)器身份然后進(jìn)行通信,而且還要使用completionHandler(NSURLSessionAuthChallengeUseCredential,credential)執(zhí)行request。
然而如果兩個data不相等,我們使用completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,NULL)方法來取消dataTask的執(zhí)行,這樣就可以拒絕和服務(wù)器溝通。
這就是在NSURLSession中使用SSL pinning。
附源碼:https://pan.baidu.com/s/1mio6ZnM
轉(zhuǎn)載于:https://www.cnblogs.com/zhanggui/p/5754977.html
總結(jié)
以上是生活随笔為你收集整理的如何使用SSL pinning来使你的iOS APP更加安全的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于hibernate中提示can no
- 下一篇: poj-2336 Ferry Loadi