iOS WebView通訊鏈路安全

最近在整理技術點的時候發現電腦上存有一些知識點的記錄,是之前在開發的過程當中遇到的一些問題,如今再從新梳理了出來web

項目需求:防止webview裏面的數據被抓包,給app中的webview也加上https校驗,防止攻擊
https校驗原理、加密原理、證書製做等已經有不少文章介紹,相信你們已經很熟悉了;本文只講在多家服務器資源訪問的狀況下對web實現https校驗的部分。objective-c

1、相關知識點

  1. 通常狀況下不少公司對於ATS的web content設置都是打開了的,沒有對證書進行校驗,或者只是作了單向的證書校驗,這樣的話僞造一個假的有效證書web部分是很容易被別人抓到包的,此次要說的是web content設置爲NO,而且是雙向驗證,採用的是證書鎖定的校驗模式,證書鎖定須要客戶端本地也存儲一份證書,工做原理是首先會驗證域名有效期等信息,其次會驗證本地證書和服務器證書是否一致,一致則握手連接,不一致則斷開連接,若是設置了代理而且即便配置了一個非當前公司服務器的有效證書也沒法抓到數據,能夠達到防止中間人攻擊的效果。
  2. 無論上面app採用哪種校驗方式,都是由服務器配置參數clientAuth來決定:
參數 描述
clientAuth=false 單向SSL驗證
clientAuth=true 雙向SSL驗證
clientAuth=want 不強制驗證客戶端證書

2、實現過程

下面展現的是常規的web雙向https校驗安全

SecTrustResultType result;
SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCerts);
OSStatus status = SecTrustEvaluate(serverTrust, &result);
 if (status == errSecSuccess &&
    (result == kSecTrustResultProceed ||
    result == kSecTrustResultUnspecified)) {
     NSURLCredential *card = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
     completionHandler(NSURLSessionAuthChallengeUseCredential,card);
  } else {
      completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
  }
  1. 以上就是常規的web實現https雙向校驗,可是運用到目前的項目一直校驗失敗;正常來講當web經過https請求數據的時候,服務器會返回所有證書鏈,一個域名和一個證書是一一對應的,不能更改,而一個證書鏈裏面又會包含有幾級證書,根證書-二級證書-…..,目前咱們web請求返回的每一個證書鏈裏面有3級證書;最後通過調試才發現某一個h5頁面在加載的時候,返回了除了咱們公司本身的證書之外還返回了阿里雲的證書(*.oss.aliyuncs.com),而且每一個h5界面返回的證書順序還可能不同,返回的第一個證書鏈多是咱們公司本身的證書鏈,也多是oss阿里雲的,順序不必定,這就是問題所在,因此當前h5頁面校驗會失敗沒法正常打開。
  2. 更改思路,經過CFBridgingRelease(SecCertificateCopySubjectSummary(SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, 0)))取出服務器證書的概要信息,判斷若是是當前本身公司域名下的證書,那麼進行校驗,不是好比oss阿里雲的不校驗,直接信任經過,通過測試無論本身服務器證書鏈在哪一個順序或者有沒有均可以正常顯示,而且測試沒法抓包:

在這裏插入圖片描述

  1. 若是好比上面返回了oss.aliyun.com的證書,那麼在plist中加上這個白名單就不會有阿里雲的證書鏈返回了,就不須要進行校驗,這樣也是一種思路。

3、最終實現的代碼以下

//從證書鏈中獲取概要信息
    NSString *summary = CFBridgingRelease(SecCertificateCopySubjectSummary(SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, 0)));
    NSLog(@"當前請求證書概要=%@",summary);
    //獲取信任管理對象,裏面包含了待驗證的證書,和自定義的策略
    SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        if ([summary containsString:@".xxxx.com"]) {
            NSString *path = [[NSBundle mainBundle] pathForResource:@"xxxx" ofType:@"der"];
            NSData *certData = [NSData dataWithContentsOfFile:path];
            //從der數據中建立證書對象
            NSMutableArray *pinnedCerts = [NSMutableArray arrayWithObjects:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData), nil];
            SecTrustResultType result;
            SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCerts);
            OSStatus status = SecTrustEvaluate(serverTrust, &result);
            if (status == errSecSuccess &&
                (result == kSecTrustResultProceed ||
                 result == kSecTrustResultUnspecified)) {
                    NSURLCredential *card = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                    completionHandler(NSURLSessionAuthChallengeUseCredential,card);
                } else {
                    //中斷本次連接
                    completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
                }
        }else {
            NSURLCredential *card = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,card);
        }
    }else {
        NSURLCredential *card = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, card);
    }

4、拓展

1.通過測試對於設置了web的ATS=NO,plist是否加白名單狀況:
(1)加了白名單
不論是https仍是http均可以正常訪問,因爲設置了ATS=NO,必需校驗,代理會收到校驗的回調
(2)未加白名單
a、https能夠訪問,前提條件(1)這個域名服務器證書有效沒有過時(2)webview的校驗代理沒有和本地證書匹配,直接經過,好比不是本身公司的域名訪問
b、http沒法正常訪問服務器

2.除了web當時還考慮到圖片的安全性問題;好比某個二維碼支付界面或者好友頭像,抓包工具中設置的其它有效證書那麼也就能抓到圖片,查看源碼知道SDWebimage是不校驗本地證書的,因此若是要考慮圖片的安全性須要改這裏的源碼,和webview中校驗的方法同樣就能夠了,原理相同。app

ps:除了以上校驗客戶端和服務端的證書所有信息之外,還能夠經過 SecTrustCopyPublicKey(trust) 取出各自證書信息裏面的公鑰進行對比,也是能夠達到一樣的效果,這裏就再也不細說了,感興趣的同窗能夠本身嘗試一下。工具

相關文章
相關標籤/搜索