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. SQL Server - 把星期一(周一)当作每个星期的开始在一年中求取周数

    先感叹一句!好长时间没有更新博客了!偶尔看到一句话,觉得被电击了 - 庸人败于懒,能人败于傲! 因此,不能再懒惰了! 今天想写一个有关计算 Week Number 的函数,刚开始觉得应该很简单,凭着感 ...

  2. 利用getBoundingClientRect方法实现简洁的sticky组件

    补充于2016-03-20: 本文实现有不足,不完美的地方,请在了解本文相关内容后,移步阅读<sticky组件的改进实现>了解更佳的实现. sticky组件,通常应用于导航条或者工具栏,当 ...

  3. HTML基础—插曲

    HTML基础学习 1:我们在网上添加图片的时候最好是缩略图,而不是直接在代码中限制图片的大小.可以为了用户减少流量.Alt=""属性是为了让图片在现实不出来时显示的文字,Title ...

  4. html5掷骰子的小demo

    代码如下: <!DOCTYPE> <html> <title>柯乐义</title> <head> <script> var l ...

  5. Asp.Net WebForm和MVC同样优秀!

    不是说MVC不好,而是WebForm并没有那么不堪,和Mvc同样优秀.对说WebForm缺点多的,表示不服,求指教,虽然本人有些见解可能比较浅薄. 看过很多文章和书籍,都会拿MVC模式和WebForm ...

  6. c#获取当前应用程序所在路径

    一.获取当前文件的路径1.   System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName     获取模块的完整路径,包括文 ...

  7. iOS 阶段学习第25天笔记(iOS沙盒机制介绍)

    iOS学习(OC语言)知识点整理 一.iOS沙盒机制介绍 1)概念: 每个ios应用都有自己的应用沙盒,应用沙盒就是文件系统目录,与其他应用放入文件 系统隔离,ios系统不允许访问 其他应用的应用沙盒 ...

  8. vim 使用说明

    =========================================================本使用说明与 把VIM打造成IDE 配套======================= ...

  9. Android控件颜色设置为透明

    开发Widget时,经常想把Widget的背景设置成透明的,显得比较有品位.如果想让控件的颜色是透明的,可以定义以下的颜色: <color name="black"># ...

  10. 使用Monkey进行压力测试

    Android可以使用Monkey向应用发送一连串的随机操作,就好像把手机交给一只猴子让它任意操作一样,以此来检测应用是否健壮,是否容易出错或崩溃.操作的类型包括触屏.移动.按键等. Monkey的语 ...