你的位置:首页 > 操作系统

[操作系统]iOS 安全:UIWebView访问Https站点防止中间人攻击


尽管Https协议能够提供数据的加密、身份的认证等安全服务,但并不是没有漏洞。HTTPS协议安全隐患的存在可能使用户受到各种极具破坏力的网络攻击。其中中间人攻击(Man In The Middle, MITM)就是非常危险的一种攻击方式。

场景分析:假设用户手机接入了不安全的wifi,这时发生了dns被篡改的情况。如用户访问了Https://www.taobao.com, 被跳转到了类似淘宝的钓鱼站点,且该站点用的是真实ca证书,这时用户的账户安全将受到巨大威胁。

这里介绍一个ios中能大大降低此类风险的做法,即公钥证书匹配。

1. 在终端执行,openssl s_client -connect www.taobao.com:443 -showcerts ,获取公钥内容。

 0 s:/C=CN/ST=ZheJiang/L=HangZhou/O=Alibaba (China) Technology Co., Ltd./CN=*.tmall.com  i:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - G2-----BEGIN CERTIFICATE-----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-----END CERTIFICATE-----

2. 将公钥内容(-----BEGIN CERTIFICATE----- 至-----END CERTIFICATE-----)保存成.PEM格式文件。

3. 执行命令 openssl x509 -inform PEM -outform DER -in cert.pem -out cert.der , 将.pem证书转换成.der格式。

4. 在app工程中,导入生成好的.der证书。

5. 在实现UIWebViewDelegate 的View Controller.h中添加

@interface TargetViewController : UIViewController<UIWebViewDelegate, NSURLConnectionDelegate, NSURLConnectionDataDelegate>

6. 在init方法中添加读取证书的逻辑,并存到self.trustedCerts数组中

        

    //读取ssl证书信息    if (!hasReadLocalCerts) {      certsFile = [NSMutableArray arrayWithObjects: @"taobao.com.der", nil];      self.trustedCerts = [NSMutableArray array];      for (NSString *file in certsFile) {        NSString *fpath = [[NSBundle mainBundle] pathForResource:file ofType:@"der"];        NSData * cerData = [NSData dataWithContentsOfFile:fpath];        SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(cerData));        [self.trustedCerts addObject:CFBridgingRelease(certificate)];      }      hasReadLocalCerts = YES;    }    

 

7. 在

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request

 navigationType:(UIWebViewNavigationType)navigationType

方法中添加https站点的处理逻辑:

  NSURL *url = [request URL];  NSString *schema = [[url scheme] lowercaseString];
   //未有过证书验证,将失败的请求纪录下来 if ([schema isEqualToString:@"https"]){ if (!authenticated) { NSLog(@"Authenticated failed!"); [self.webView stopLoading]; failedRequest = request; [[[NSURLConnection alloc] initWithRequest:request delegate:self] start] ; return NO; }   return YES; }

 

8. 实现证书验证

#pragma mark ------ NSURLConnectionDelegate- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{  NSLog(@"Check ssl cert.");    //获取trust object  SecTrustRef trust = challenge.protectionSpace.serverTrust;  SecTrustResultType result;    //这里将之前导入的证书设置成下面验证的Trust Object的anchor certificate  SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)self.trustedCerts);    //SecTrustEvaluate会查找前面SecTrustSetAnchorCertificates设置的证书或者系统默认提供的证书,对trust进行验证  OSStatus status = SecTrustEvaluate(trust, &result);  if (status == errSecSuccess &&    (result == kSecTrustResultProceed ||     result == kSecTrustResultUnspecified)) {      //验证成功,生成NSURLCredential凭证cred,告知challenge的sender使用这个凭证来继续连接      NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];      [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];      NSLog(@"SSL cert match!");    }  else {    //验证失败,取消这次验证流程    [challenge.sender cancelAuthenticationChallenge:challenge];    NSLog(@"SSL cert missmatch!");  }    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];}

#pragma mark ------ NSURLConnectionDataDelegate-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)pResponse {  authenticated = YES;  [connection cancel];
   //验证通过,继续执行之前被拦截下来的请求 [self.webView loadRequest:failedRequest];}

 

转载请注明:

http://www.cnblogs.com/lijizhuang/p/4884868.html