SSL pinning在构建一个高度安全的移动APP上扮演了一个十分重要的角色。然而如今好多用户在使用无线移动设备去访问无数不安全的无线网络。

  这篇文章主要覆盖了SSL pinning 技术,来帮助我们处理最常见的安全攻击--中间人攻击(MITM)。

  SSL(Secure Socket Layer 安全套接字层)确保客户端-服务器在HTTP请求的方式上将通讯内容加密----被指定为HTTPS(SSL上的HTTP)。这种加密体系是基于PKI(Pbulic Key Infrastructure,公钥体系)和(Session key,会话key)。其中Session key 被引进的原因是对于公钥/私钥的加密和解密会消耗处理能力,会是整个交流进程速度变慢。

  SSL 安全---鉴定

  SSL安全是基于证书的信任链。当一个通信开始的时候,客户端检查服务器的SSL证书,检查这个证书是否被信用根CA机构或者其他用户信任结构所信任。

  尽管SSL通信被认为是一个非常安全的和坚不可摧的,但是中间人攻击依然还是真实存在的威胁,它可以用好几种方法去实现,例如ARP 缓存中毒、DNS 欺骗等。

  对于ARP缓存中毒,可以简单理解为中间人通过地址解析协议的IP映射到设备的Mac地址这一特性进行攻击。例如,我们用一下三个角色来描述一个简单的网络:

  一个普通的用户设备U

  攻击者的设备A

  路由器R

  攻击者的设备A可以发送一个ARP依赖包给用户设备U,把他自己伪装成路由器R。为了完成中间人攻击,A发送另一个ARP依赖给R,告诉路由器它就是U。这样的话,A就成了U和R沟通的中间者,A就可以窃听和拦截信息。IP转发经常被用于攻击者在用户设备和路由器的无缝交流。也就是说通过IP转发,攻击者可以窃取和监听,但是用户和路由器是无感知的。

  DNS欺骗主要在于攻击者破话服务器的域名映射。攻击者尝试强迫DNS去返回一个不正确的地址,而这个地址就是攻击者的计算机地址。

  SSL pinning

  我们使用SSL pinning来确保app通信仅仅发生在指定的服务器上。其中的先决条件就是将目标服务器的SSL证书放到app里面。这个证书被用于会话配置。这里我简单介绍SSL pinning在NSURLSession上的使用。

  当谈到NSURLSession使用SSL pinning有点棘手,因为在AFNetworking中,其本身已经有封装好的类可以使用来进行配置。这里没有办法去设置一组证书来自动取消所有本地证书不匹配的response。我们需要手动执行检查来实现在NSURLSession上的SSL pinning。我们很荣幸的是我们可以用Security's framework C API。

  我们可以先来一个默认会话配置的NSURLSession对象。

  NSURLSessionConfiguration *seeConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:seeConfig delegate:self delegateQueue:nil];

  NSURLSession使用NSURLSessionTask来发送一个请求,我么使用dataTaskWithURL:completionHandler:方法来进行SSL pinning 测试。发送请求类似于下面这样:

    NSURLSessionDataTask *task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:testURL]];
[task resume];

该方法仅仅是返回了一个task对象,然后使用resume方法发送请求,或者说是执行任务。

使SSL pinning在:

URLSession:didReceiveChallenge:completionHandler:delegate

方法中实现。在NSURLSession对象上,我们设置自己为代理来调用方法。

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {

    //得到远程证书
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, );
//设置ssl政策来检测主域名
NSMutableArray *policies = [NSMutableArray array];
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host)];
//验证服务器证书
SecTrustResultType result;
SecTrustEvaluate(serverTrust, &result);
BOOL certificateIsValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
//得到本地和远程证书data
NSData *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来得到服务器的SSL证书数据。然后使用证书评估设置policies。证书使用SecTrustEvaluate评估,然后返回以下几种认证结果类型之一:

typedef uint32_t SecTrustResultType;
enum {
kSecTrustResultInvalid = ,
kSecTrustResultProceed = ,
kSecTrustResultConfirm SEC_DEPRECATED_ATTRIBUTE = ,
kSecTrustResultDeny = ,
kSecTrustResultUnspecified = ,
kSecTrustResultRecoverableTrustFailure = ,
kSecTrustResultFatalTrustFailure = ,
kSecTrustResultOtherError =
};

如果我们得到kSecTrustResultProceed和kSecTrustResultUnspecified之外的类型结果,我们可以认为证书是无效的(不被信任的)。

  至今为止我们除了检测远程服务器证书评估外,还没有做其他事情,对于SSL pinning 检测我们需要通过SecCertificateRef来得到他的NSData。这个SecCertificateRef来自于challenge.protectionSpace.serverTrust。而本地的NSData来自本地的.cer证书文件。然后我们使用isEqual来进行SSL pinning。

  如果远程服务器证书的NSData等于本地的证书data,那么就可以通过评估,我们可以验证服务器身份然后进行通信,而且还要使用completionHandler(NSURLSessionAuthChallengeUseCredential,credential)执行request。

  然而如果两个data不相等,我们使用completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,NULL)方法来取消dataTask的执行,这样就可以拒绝和服务器沟通。

  这就是在NSURLSession中使用SSL pinning。

 附源码:https://pan.baidu.com/s/1mio6ZnM

如何使用SSL pinning来使你的iOS APP更加安全的更多相关文章

  1. SSLPinning简介,使用Xposed+JustTrustMe来突破SSL Pinning

    0x00 前面 如果你是一干Web安全的,当你在测试目前大多数的手机APP应用程序时,你一定遇到过burpsuite无法抓到数据包的情况,开始你以为只是https的问题,但是当你使用了burpsuit ...

  2. iOS SSL Pinning 保护你的 API

    随着互联网的发展,网站全面 https 化已经越来越被重视,做为 App 开发人员,从一开始就让 API 都走 SSL 也是十分必要的.但是光这样就足够了吗? SSL 可以保护线上 API 数据不被篡 ...

  3. Burpsuite如何抓取使用了SSL或TLS传输的 IOS App流量

    之前一篇文章介绍了Burpsuite如何抓取使用了SSL或TLS传输的Android App流量,那么IOS中APP如何抓取HTTPS流量呢, 套路基本上与android相同,唯一不同的是将证书导入i ...

  4. 【转】使IFRAME在iOS设备上支持滚动

    原文链接: Scroll IFRAMEs on iOS原文日期: 2014年07月02日 翻译日期: 2014年07月10日翻译人员: 铁锚 很长时间以来, iOS设备上Safari中超出边界的元素将 ...

  5. 使IFRAME在iOS设备上支持滚动

    原文链接: Scroll IFRAMEs on iOS原文日期: 2014年07月02日 翻译日期: 2014年07月10日翻译人员: 铁锚很长时间以来, iOS设备上Safari中超出边界的元素将不 ...

  6. 苹果iOS APP配置HTTPS,iOS ATS配置SSL,苹果ATS标准解决方案

    参考沃通:

  7. 如何在使Xcode打包iOS应用时自动增加编译号

    在红框标注的输入框中输入:真机调试编译成功增加 echo $CONFIGURATION if [ "Release" == "${CONFIGURATION}" ...

  8. [App Store Connect帮助]三、管理 App 和版本(5)添加平台以创建通用购买

    您可以为 App 添加一个平台以创建通用购买.例如,为现有的 iOS App 添加相关的 Apple TVOS App,从而将该 Apple TVOS App 和 iOS App 一同出售. 与创建新 ...

  9. AFNetworking 2.x 的SSL身份认证

    一般来讲如果app用了web service , 我们需要防止数据嗅探来保证数据安全.通常的做法是用ssl来连接以防止数据抓包和嗅探 其实这么做的话还是不够的.我们还需要防止中间人攻击(不明白的自己去 ...

随机推荐

  1. Struts2 源码分析——过滤器(Filter)

    章节简言 上一章笔者试着建一个Hello world的例子.是一个空白的struts2例子.明白了运行struts2至少需要用到哪一些Jar包.而这一章笔者将根据前面章节(Struts2 源码分析—— ...

  2. Android事件分发机制理解

    预备知识 触摸事件 : 安卓中把触摸事件封装成了一个类MotionEvent,用户的一次点击.触摸或者滑动都会产生一系列的MotionEvent 这个类的内容很简单,就两个东西:事件类型+坐标xy 事 ...

  3. 完美且精准的 IE10- 版本检测。

    通过动态的写入条件注释的方式,来判断当前的ie浏览器的版本,优点是,对比userAgent字符匹配,要精准很多,应该说是100%正确,缺点就是要通过JS写入条件注释,拖慢页面的加载速度. 如果对于只判 ...

  4. html 组装table 指定列自动换行

    4列后自动换行思路:int i = 0;while (dr.Read()){    if (i % 4 == 0) 输出一行的开始     输出这个数据    if (i % 4 == 3) 输出一行 ...

  5. C#获取 URL参数

    假设当前页完整地址是:http://www.test.com/aaa/bbb.aspx?id=5&name=kelli "http://"是协议名 "www.te ...

  6. Note: This element neither has attached source nor attached Javadoc and hence no Javadoc could be found.

    在Eclipse中开发Android项目时,鼠标停放在想要查看帮助文档的类上面,发现没有显示帮助文档,显示了下面一句话: Note: This element neither has attached ...

  7. 一个奇葩常见的问题 nginx 403 forbidden错误

    今天安装dedecms,配置Nginx,然后生成一键生成静态页面,然后就没有然后了,所有栏目页面都显示nginx 403 forbidden. 一般来说nginx 的 403 Forbidden er ...

  8. Verilog学习笔记认识提升篇(一)...............时序的基本概念(待补充)

    建立和保持时间: 建立时间(Tsu)是指在时钟上升沿到来之前数据必须保持稳定的时间,保持时间(Th)是指在时钟上升沿到来以后数据必须保持稳定的时间.一个数据需要在时钟的上升沿被锁存,那么这个数据就必须 ...

  9. Android SDK 国内镜像及配置方法

    东软信息学院的 Android SDK 镜像,比配置代理下载快. 配置地址, http://mirrors.neusoft.edu.cn/configurations.we#android 配置步骤: ...

  10. GJM : 基于Actor模式的c#网络游戏服务器的实现和Unity游戏客户端的连接 [转载]

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...