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. Hyperledger区块数据的访问

    简介 本文介绍了访问Hyperledger区块数据的几种方法. REST API Hyperledger提供了多个REST API (https://hyperledger-fabric.readth ...

  2. 基于HT for Web的3D呈现A* Search Algorithm

    最近搞个游戏遇到最短路径的常规游戏问题,正巧看到老同事写的3D机房最短路径巡线文章,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现,算法基于开源 https://github.c ...

  3. Guid算法与标识列(自动增长字段)在表中的应用

    <<1>>int(bigint)+标识列(自动增长字段) 用标识列实现字段自增可以避免并发等问题.不需开发人员自己控制自增,用标识列的字段在Insert的时候不用指定主键的值. ...

  4. HTML的checkbox和radio的美化

    checkbox和radio的美化 checkbox: <style type="text/css"> input[type="checkbox"] ...

  5. 把DataTable转换为泛型List<T>或是JSON

    在开发ASP.NET Web API或ASP.NET MVC时,我们从数据库得到的数据往往是DataSet或是DataTable.为了能让前端JQuery能方便使用至这些数据,我们需要把这些数据转换为 ...

  6. SSH服务器与Android通信(1)--服务器端发送数据

    很多应用要求SSH服务器不仅和PC通信,还要和Android移动设备通信,这时就需要用到JSON了.其基本原理是服务器将数据转换成JSON格式,发送给Android客户端,客户端再将JSON格式的数据 ...

  7. 基于类型系统的面向对象编程语言Go

    (整理自网络) 面向对象编程 Go语言的面向对象编程(OOP)非常简洁而优雅.说它简洁,在于它没有了OOP中很多概念,比如:继承.虚函数.构造函数和析构函数.隐藏的this指针等等.说它优雅,是它的面 ...

  8. Java面试题总结系列 Servlet

    Servlet技术主要是为了使用Web上的HTTP协议而设计的.servlet是在WEB服务器上运行的程序.Java Servlet可以用于处理客户请求或生成动态Web网页.先一个实例.然后解释. 先 ...

  9. Java--Semaphore控制并发线程数量

    package com; import java.util.concurrent.Semaphore; /** * Created by yangyu on 16/11/28. */ /** * Se ...

  10. linux下MySQL表名忽略大小写设置

    最近公司项目的MySQL数据库要迁移到linux下,部署时日志总是显示报找不到一个表,用MYSQL查看明明有这个表.后来经百度,原来LINUX下的MYSQL默认是区分表名大小写的. 用命令查看当前是否 ...