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. 小技巧找出一个php的cron脚本出问题的代码行

    这个小技巧虽然很小,但是很有用. 我写了一个cron脚本,但是隔一天发现,这个昨天的cron脚本还一直在跑着,没有停下来,一定是里面有个程序堵住了. 但是如果我重新跑又需要很多时间.这个怎么办? 现在 ...

  2. PHP内核研究(内存管理1)

    PHP内存管理 PHP在5.3之前采用的是引用计数法 PHP在5.3之后采用了新的垃圾回收机制 操作系统在申请内存空间的时候回引发系统调用 在操作系统申请内存空间的时候,会将CPU从用户态切换到内核态 ...

  3. C# 视频流操作

    发送视频流 void SendVideoBuffer(object bufferIn) { try { TcpClient tcp = ); NetworkStream ns = tcp.GetStr ...

  4. VS2012 JSON、XML自动生成对应的类

    在VS编辑下拉框中,选择选择性粘贴(Paste Special)

  5. 【转】NoSQL初探之人人都爱Redis:(1)Redis简介与简单安装

    一.NoSQL的风生水起 1.1 后Web2.0时代的发展要求 随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类型的Web2.0纯动态网站已经 ...

  6. html的<meta>标签的作用

    <meta>标签包含了页面文档的上下文信息. 主要包含的上下文信息: 1.配置了服务器向浏览器响应时,http协议的head信息,浏览器根据head执行相应操作. 2.对页面的描述信息,便 ...

  7. Nancy 引用源码与NuGet安装差异

    使用NuGet安装Nancy和直接引用源码项目存在一些差异,如序列化,授权验证问题. 如果引用源码的话,自定义JsonSerializer,如下: 注意,需要使用NuGet安装Newtonsoft.J ...

  8. go语言操作mysql范例(增删查改)

    http://blog.csdn.net/jesseyoung/article/details/40398321 go语言连接mysql简介    go官方仅提供了database package,d ...

  9. Android版的菜谱客户端应用源码完整版

    Android版的菜谱客户端应用源码完整版,这个文章是从安卓教程网转载过来的,不是本人的原创,希望能够帮到大家的学习吧. <ignore_js_op> 152936qc7jdnv6vo0c ...

  10. Oracle 表分组 group by和模糊查询like

    分组group by写法 select 字段名 from 表名 group by 字段名 查询这个字段名里的种类分组后可以加聚合函数select 字段名,聚合函数 from 表名 group by 字 ...