HTTPS与中间人攻击

预备知识

对称加密

加密和解密使用同一个秘钥。在HTTPS建立连接的过程中如果只采用对称加密,双方通信的开始总会以明文的方式传输密钥,显然是不安全的。

常见的对称加密算法有:DES(数据加密标准) AES

非对称加密

加密和解密不使用同一个秘钥。用公钥加密只能用私钥解密,用私钥加密只能用公钥解密。

常见的非对称加密算法有:RSA

数字摘要

数字摘要是将任意长度的消息变成固定长度的短消息,它类似于一个自变量是消息的函数,也就是Hash函数。数字摘要就是采用单向Hash函数将需要加密的明文“摘要”成一串固定长度(128位)的密文这一串密文又称为数字指纹,它有固定的长度,而且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致。

一个Hash函数的好坏是由发生碰撞的概率决定的。如果攻击者能够轻易地构造出两个消息具有相同的Hash值,那么这样的Hash函数是很危险的。一般来说,安全Hash标准的输出长度为160位,这样才能保证它足够的安全。 这一加密方法亦称安全Hash编码法(SHA:Secure Hash Algorithm)或MD5(MD Standards for Message Digest),由Ron Rivest所设计。该编码法采用单向Hash函数将需加密的明文“摘要”成一串128bit的密文,这一串密文亦称为数字指纹(Finger Print),它有固定的长度,且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致。这样这摘要便可成为验证明文是否是“真身”的“指纹”了。

数字签名

数字签名确保文件来自签名的一方,并且未被修改。签名的基本原理是:

(1) 被发送文件用SHA编码加密产生128bit的数字摘要。

(2) 发送方用自己的私用密钥对摘要再加密,这就形成了数字签名。

(3) 将原文和加密的摘要同时发送给对方。

(4) 对方用发送方的公共密钥对数字签名解密,同时对收到的文件用SHA编码加密产生又一摘要。

(5) 将解密后的摘要和收到的文件在接收方重新加密产生的摘要相互对比。如两者一致,则说明传送过程中信息没有被破坏或篡改过。否则不然。

数字证书

PKI (Public Key Infrastructure),公开密钥基础设施。它是一个标准, 在这个标准之下发展出的为了实现安全基础服务目的的技术统称为PKI。 权威的第三方机构CA(certificate authority ,认证中心)是PKI的核心, CA负责核实公钥的拥有者的信息,并颁发认证”证书”,同时能够为使用者提供证书验证服务。 x.509是PKI中最重要的标准,它定义了公钥证书的基本结构。

先简单介绍下CA证书申请以及验证过程:

1、服务器首先生成公钥和私钥对,然后确认申请信息(域名、申请者信息、公钥),最后封装为一个.csr文件(文件内不包含私钥,私钥只在服务端存在)。

2、服务端将申请信息发送到CA,CA通过线上、线下多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法、该组织是否拥有本域名的所有权等。

3、如果信息审核通过,CA会向申请者签发认证文件——证书。证书包含以下信息:申请者公钥、申请者组织信息、签发机构CA信息、有效时间、证书序列号等信息的明文,同时还会包含一个签名和签名产生的算法。

4、客户端向服务器第一次发出请求时,服务端返回证书文件;

5、客户端读取证书中的明文信息,采用相同的散列函数计算出信息摘要,然后利用对应CA的公钥解密证书中的签名数据,对比证书的信息摘要,如果一致,则可以认定证书合法。

6、客户端还会验证证书相关的其他信息,如域名信息、有效时间等。

ps:

自签名证书

自签名证书不是第三方信任CA颁发的证书。自签名证书可以使用 OpenSSL, Java’s keytool, Adobe Reader, and Apple’s Keychain等工具免费制作获得。自签名证书不受浏览器信任,访问的时候会给出警告,同时也容易被中间人攻击。

一般而言,CA 颁发的证书,价格昂贵,根证书一般保存在操作系统/浏览器下,受到信任。

什么是HTTPS

HTTPS 是运行在 TLS/SSL 之上的 HTTP,与普通的 HTTP 相比,在数据传输的安全性上有很大的提升。

HTTPS建立连接的过程

图片来源于网络

HTTPS建立连接握手的过程采用非对称加密,后续通信过程使用对称加密。

HTTPS证书校验过程

HTTPS证书以证书链的形式组织,在颁发证书的时候首先要有根CA机构颁发的根证书,再由根CA机构颁发一个中级CA机构的证书,最后由中级CA机构颁发具体的SSL证书。在验证证书的时候,浏览器会调用系统的证书管理器接口对证书路径中的所有证书一级一级的进行验证,只有路径中所有的证书都是受信的,整个验证的结果才是受信。

根证书是最关键的一个证书,如果根证书不受信任,它下面颁发的所有证书都不受信任。操作系统在安装过程中会默认安装一些受信任的CA机构的根证书。根证书的有效期长,支持的用途多以方便颁发不同用途类型的中级证书;中级证书用途单一,有效期相对短一些,但是比具体的SSL证书要长很多。

SSL证书验证失败有以下三点原因:

1、SSL证书不是由受信任的CA机构颁发的

2、证书过期

3、访问的网站域名与证书绑定的域名不一致

img

当客户端走 HTTPS 访问站点时,服务器会返回整个证书链。以上图的证书链为例:

要验证 .wikipedia.org 这个证书有没被篡改,就要用到 GlobalSign Organization Validation CA - SHA256 - G2 提供的公钥解密前者的签名得到摘要 Digest1,我们的客户端也计算前者证书的内容得到摘要 Digest2。对比这两个摘要就能知道前者是否被篡改。后者同理,使用 GlobalSign Root CA 提供的公钥验证。当验证到到受信任的根证书时,就能确定 .wikipedia.org 这个证书是可信的。

HTTPS中间人攻击

HTTPS也不是绝对安全的,对HTTPS最常见的攻击手段就是SSL证书欺骗或者叫SSL劫持,是一种典型的中间人攻击,Charles抓包就是利用中间人攻击。如下图所示为中间人劫持攻击,中间人可以获取到客户端与服务器之间所有的通信内容。

图片来源于网络

中间人截取客户端发送给服务器的请求,然后伪装成客户端与服务器进行通信;将服务器返回给客户端的内容发送给客户端,伪装成服务器与客户端进行通信。
通过这样的手段,便可以获取客户端和服务器之间通信的所有内容。
使用中间人攻击手段,必须要让客户端信任中间人的证书,如果客户端不信任,则这种攻击手段也无法发挥作用。

反抓包策略

那我们应该如何防止被抓包呢?可以使用SSL-Pinning技术来反抓包。因为被抓包主要是由于伪造了一个假的服务端证书给了客户端,音粗可以同时在客户端也保存一份服务端的证书,就可以知道数据来源的证书是不是真实服务端来源了。SSL-pinning有两种方式: 证书锁定(Certificate Pinning) 公钥锁定(Public Key Pinning)

证书锁定

证书锁定是SSL/TLS加密的额外保证手段。它会将服务器的证书公钥预先保存在客户端。在建立安全连接的过程中,客户端会将预置的公钥和接受的证书做比较。如果一致,就建立连接,否则就拒绝连接。在客户端设置证书只允许设置指定域名的证书,而不接受操作系统或浏览器内置的CA根证书对应的任何证书。

公钥锁定

HTTP公钥锁定是HTTPS网站防止攻击者CA机构错误签发的证书进行中间人攻击的一种安全机制,用于预防CA遭受入侵或其他会造成CA签发未授权证书的情况。采用公钥锁定时,网站会提供已授权公钥的哈希列表,指示客户端在后续通讯中只接受列表上的公钥。提取证书中的公钥并内置到客户端中,通过与服务器对比公钥值来验证连接的正确性。

iOS中证书校验

iOS中利用Security框架的API对证书进行校验。

AFNetworking中的证书验证

AFHTTPSessionManager.securityPolicy = self.securityPolicy;
- (AFSecurityPolicy *)securityPolicy {
    if (!_securityPolicy) {
        NSMutableSet *certificates = [NSMutableSet set];
        NSArray *domains = @[@"a.com",@"a.cn",@"a.net",@"ab.com"];
        for (NSString *domain in domains) {
            NSString *certPath = [[NSBundle bundleForClass:[self class]] pathForResource:domain ofType:@"cer"];
            NSData *certData = [NSData dataWithContentsOfFile:certPath];
            if (certData) {
                [certificates addObject:certData];
            }
        }
    #ifndef DEBUG
        if ([certificates count] > 0) {
            _securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
            _securityPolicy.allowInvalidCertificates = NO;
            _securityPolicy.validatesDomainName = YES;
            _securityPolicy.pinnedCertificates = certificates;
        } else
    #endif
        {
            _securityPolicy = [AFSecurityPolicy defaultPolicy];
        }
    }
    return _securityPolicy;
}

HTTPS中间人攻击实践(原理·实践)

[腾讯Bugly] iOS 中 HTTPS 证书验证浅析

iOS 中对 HTTPS 证书链的验证

HTTPS实战之单向验证和双向验证

HTTPS

HTTPS进阶

NodeJs 搭建https服务

iOS12 Network框架 自签名证书认证

HTTPS Server Trust Evaluation

Swift 适配HTTPS