IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> SSL Pinning札记 -> 正文阅读

[网络协议]SSL Pinning札记

1. 准备知识

如果需要明白SSL/TLS的工作原理,首先需要明白HTTPS的工作原理,它和HTTP之间的区别是什么?

1.1 HTTP的介绍

HTTP(超文本传输协议)被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此,HTTP协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。

1.2 HTTPS的介绍

HTTPS(安全套接字层超文本传输协议),解决了HTTP的这一缺陷。为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL/TLS协议,SSL/TLS依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比HTTP协议安全
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

1.3 HTTP和HTTPS的主要区别

  1. HTTPS协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
  2. HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的ssl/tls加密传输协议。
  3. HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  4. HTTP的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。

2. SSL/TLS

2.1 SSL/TLS历史

1994年,NetScape公司设计了SSL协议(Secure Sockets Layer)的1.0版,但是未发布。
1995年,NetScape公司发布SSL 2.0版,很快发现有严重漏洞。
1996年,SSL 3.0版问世,得到大规模应用。
1999年,互联网标准化组织ISOC接替NetScape公司,发布了SSL的升级版TLS 1.0版。
2006年和2008年,TLS进行了两次升级,分别为TLS 1.1版和TLS 1.2版。最新的变动是2011年TLS 1.2的修订版,在2018年也发布了TLS1.3版本。
TLS 1.0通常被标示为SSL 3.1,TLS 1.1为SSL 3.2,TLS 1.2为SSL 3.3。
目前应用的最广泛的 TLS 是 1.2,而之前的协议(TLS1.1/1.0、SSLv3/v2)都已经被认为是不安全的了。

2.2 SSL/TLS协议基本过程(TLS1.2)

  1. 客户端向服务器端索要并验证公钥。
  2. 双方协商生成"对话密钥"。
  3. 双方采用"对话密钥"进行加密通信。

2.3 SSL/TLS协议详细过程(TLS1.2)

如果不做深入研究,可以跳过本小节

  1. 客户端发出请求(ClientHello)
    (1) 支持的协议版本,比如TLS 1.2版。
    (2) 一个客户端生成的随机数1,稍后用于生成"对话密钥"。
    (3) 【支持的密码套件】支持的加密方法,比如RSA公钥加密。
    (4) 支持的压缩方法。
    (5) 一个session id,标识是否复用服务器之前的tls连接(需要服务器支持)
  2. 服务器回应(SeverHello)
    (1) 确认使用的加密通信协议版本,比如TLS 1.2版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
    (2) 一个服务器生成的随机数2,稍后用于生成"对话密钥"。
    (3) 【确认密码套件】确认使用的加密方法,比如RSA公钥加密,此时带有公钥信息。
    (4) 一个session id(若同意复用连接)
  3. 服务器回应(Server Certificate)
    (1)服务器证书(该证书即包含服务器公钥)。
  4. 服务器回应(Server Key Exchange)
    (1)服务器算法变更通知,服务端给客户端一个用于 ECDHE 算法的公钥
  5. 服务器回应(Server CertificateRequest)
    (1)请求客户端证书,一般银行等需要客户端也加密的才有,比如 U 盾。
  6. 服务器回应(Server ServerHelloDone)- 标识着 serverHello 这个握手过程结束了。
  7. 客户端回应(Client Certificate)- 回应客户端证书
  8. 客户端回应(ClientKeyExchange)
    (1)客户端在验证完服务器的证书后,生成一个新的随机数(pre_master),通过服务器的公钥加密后发给服务器。
    到这里,服务端与客户端将 生成最终通信的对称加密秘钥:master_secret
    计算过程根据上面得到的三个随机数:
    随机数 1(客户端随机数):在 ClientHello 消息里,由客户端生成的随机数1
    随机数 2(服务端随机数):在 ServerHello 消息里,由服务端生成的随机数2
    随机数 3(pre_master):通过秘钥交换算法 ECDHE 计算出的,我们叫它 pre_master。
    最终的对称加密秘钥 master_secret,就是根据这三个随机数共同计算出来的。
  9. 客户端回应(Client CertificateVerif)
    (1)验证客户端证书有效性,本次不涉及
  10. 客户端回应(Client ChangeCipherSpec)
    (1)秘钥改变通知,此时客户端已经生成了 master_secret,之后的消息将都通过 master secret 来加密。
  11. 客户端回应(Client Finish)
    (1) 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。
  12. 服务器回应(Server ChangeCipherSpec)
    (1)秘钥改变通知,此时服务端也已经生成了 master_secret 了,后面的通信都用此值加密。
  13. 服务器回应(Server Finish)
    (1)同 Client Finish,服务器端发送握手结束通知,同时会带上前面所发内容的hash签名到客户端,保证前面通信数据的正确性。

上述流程简易版(不包含验证客户端证书):

  1. client --> server ClientHello
    客户端生成随机数,并发送一组密码学套件供服务端选
  2. server–> client ServerHello
    服务端生成随机数,并从上述密码学套件组里选一个
  3. server–> client Certificate
    服务端发给客户端证书
  4. server–> client ServerKeyExchange
    服务端发给客户端秘钥交换算法所需的值
  5. server–> client ServerHelloDone
    服务端 hello 阶段结束
  6. client --> server ClientKeyExchange
    客户端发给服务端秘钥交换算法所需的值pre_master
  7. client --> server ChangeCipherSpec
    客户端告诉服务端,我已经知道秘钥了,之后的消息我就都加密发送了。
  8. client --> server Finish
    结束并验证
  9. server --> server ChangeCipherSpec
    服务端告诉客户端,我已经知道秘钥了,之后的消息我就都加密发送了。
  10. server–> client Finish
    结束并验证

2.4 HTTPS的缺点

HTTPS很安全,很古老也很成熟,为什么一直到今天我们还有66%的网站不支持HTTPS呢?

  1. 慢,HTTPS未经任何优化的情况下要比HTTP慢几百毫秒以上,特别在移动端可能要慢500毫秒以上,关于HTTPS慢和如何优化已经是一个非常系统和复杂的话题
  2. 贵,特别在计算性能和服务器成本方面。HTTPS为什么会增加服务器的成本?相信大家也都清楚HTTPS要额外计算,要频繁地做加密和解密操作,几乎每一个字节都需要做加解密,这就产生了服务器成本
  3. 大量的计算。SSL的每一个字节都涉及到较为复杂的计算。即使是clientHello,也需要在握手完成时做校验。
  4. TLS协议的封装和解析。HTTPS所有数据都是按照TLS record格式进行封装和解析的。
  5. 协议的网络交互。从TLS的握手过程可以看出,即使不需要进行任何计算,TLS的握手也需要至少1个RTT(round trip time)以上的网络交互。

RTT(Round-Trip Time): 往返时延。在计算机网络中它是一个重要的性能指标,表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。

  1. HTTPS降低用户访问速度(需多次握手)
  2. 网站改用 HTTPS 以后,由 HTTP 跳转到 HTTPS 的方式增加了用户访问耗时(多数网站采用 301、302 跳转)
  3. HTTPS 涉及到的安全算法会消耗 CPU 资源,需要增加服务器资源(https 访问过程需要加解密)

3. SSL/TLS Pinning

3.1 概述

证书锁定(SSL/TLS Pinning)顾名思义,将服务器提供的SSL/TLS证书内置到移动端开发的APP客户端中,当客户端发起请求时,通过比对内置的证书和服务器端证书的内容,以确定这个连接的合法性。

3.2 预备知识

  1. 可信CA:CA(Certificate Authority)是数字证书认证中心的简称,是指发放、管理、废除数字证书的机构.CA的作用是检查证书持有者身份的合法性,并签发证书,以防证书被伪造或篡改,以及对证书和密钥进行管理。
  2. 双向锁定
    在客户端锁定服务端证书的基础上,服务端对客户端的证书也进行锁定,需要客户端再做一次证书预埋.多见于金融业务。
  3. 证书链
    证书链就是Root CA签发二级Intermediate CA,二级Intermediate CA可以签发三级Intermediate CA,也可以直接签发用户证书.从Root CA到用户证书之间构成了一个信任链:信任Root CA,就应该信任它所信任的二级Intermediate CA,从而就应该信任三级Intermediate CA直至信任用户证书。
  4. 逐级验证
    客户端对于收到的多级证书,需要从站点证书(leaf certificate)开始逐级验证, 直至出现操作系统或浏览器内置的受信任CA 根证书(root certificate)。

通常逐级检测点如下:

  1. 是否由上级证书签发
  2. 是否吊销
  3. 是否过期
  4. 是否遵循上级证书的策略

3.3 原理

证书锁定(SSL/TLS Pinning)提供了两种锁定方式: Certificate Pinning 和 Public Key Pinning。

  1. 证书锁定
    我们需要将APP代码内置仅接受指定域名的证书,而不接受操作系统或浏览器内置的CA根证书对应的任何证书,通过这种授权方式,保障了APP与服务端通信的唯一性和安全性,因此我们移动端APP与服务端(例如API网关)之间的通信是可以保证绝对安全。但是CA签发证书都存在有效期问题,所以缺点是在证书续期后需要将证书重新内置到APP中。
  2. 公钥锁定
    公钥锁定则是提取证书中的公钥并内置到移动端APP中,通过与服务器对比公钥值来验证连接的合法性,我们在制作证书密钥时,公钥在证书的续期前后都可以保持不变(即密钥对不变),所以可以避免证书有效期问题。

3.3 证书锁定的收益

安全性提升,更加有效覆盖对抗中间人攻击场景。
证书锁定本质是对抗中间人攻击.并非用于对抗破解抓包的.但如果程序逻辑未被注入运行在"可信环境"中倒是有些作用。

  • SSL对抗的攻击场景:
    中间人攻击部分场景
    ARP欺骗
    DNS劫持
    钓鱼WIFI
    伪基站
  • ssl pinning新增对抗场景:
    客户端安装恶意证书
    一些WiFi需要你添加根证书信任才能使用互联网
    其他CA恶意签发站点证书

4. Android SSL证书设置和锁定

https://zhuanlan.zhihu.com/p/127847550

我们认识到在移动端开发中安全性设置非常重要,尤其是目前非常流程H5混合式开发APP,在Android开发中,我们可以通过证书锁定的方式来增加客户端与服务端的安全保障

4.1 HttpsURLConnection SSL pinning

使用传统的HttpURLConnection类封装请求,客户端锁定操作需要实现X509TrustManager接口的checkServerTrusted方法,通过对比预埋证书信息与请求网站的的证书来判断。

public void checkServerTrusted(X509Certificate[] chain, String authType)
      throws CertificateException
  {
    if (cache.contains(chain[0])) {
      return;
    }

    // Note: We do this so that we'll never be doing worse than the default
    // system validation.  It's duplicate work, however, and can be factored
    // out if we make the verification below more complete.
    checkSystemTrust(chain, authType);
    checkPinTrust(chain);
    cache.add(chain[0]);
  }

4.2 OkHttp SSL pinning

okhttp将锁定操作封装的更人性化,你只要在client build时加入域名和证书hash即可。okhttp3.x 锁定证书示例代码。

String hostname = "yourdomain.com";
 CertificatePinner certificatePinner = new CertificatePinner.Builder()
     .add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
     .build();
 OkHttpClient client = OkHttpClient.Builder()
     .certificatePinner(certificatePinner)
     .build();

 Request request = new Request.Builder()
     .url("https://" + hostname)
     .build();
 client.newCall(request).execute();

5. iOS SSL证书设置和锁定

6. Andorid证书认定的解除

https://github.com/WooyunDota/DroidSSLUnpinning

6.1 针对HttpsURLConnection

注入SSLContext的init方法替换信任所有证书的TrustManger

// Get a handle on the init() on the SSLContext class
var SSLContext_init = SSLContext.init.overload(
    '[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom');

// Override the init method, specifying our new TrustManager
SSLContext_init.implementation = function (keyManager, trustManager, secureRandom) {

    quiet_send('Overriding SSLContext.init() with the custom TrustManager');

    SSLContext_init.call(this, null, TrustManagers, null);
};

6.2 针对OkHttp

frida Unpinning script for okhttp

setTimeout(function(){
        Java.perform(function () {
            //okttp3.x unpinning
            try {
                var CertificatePinner = Java.use("okhttp3.CertificatePinner");
                CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(p0, p1){
                    // do nothing
                    console.log("Called! [Certificate]");
                    return;
                };
                CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(p0, p1){
                    // do nothing
                    console.log("Called! [List]");
                    return;
                };
            } catch (e) {
             console.log("okhttp3 not found");
            }
            //okhttp unpinning
            try {
                var OkHttpClient = Java.use("com.squareup.okhttp.OkHttpClient");
                OkHttpClient.setCertificatePinner.implementation = function(certificatePinner){
                    // do nothing
                    console.log("Called!");
                    return this;
                };

                // Invalidate the certificate pinnet checks (if "setCertificatePinner" was called before the previous invalidation)
                var CertificatePinner = Java.use("com.squareup.okhttp.CertificatePinner");
                CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(p0, p1){
                    // do nothing
                    console.log("Called! [Certificate]");
                    return;
                };
                CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(p0, p1){
                    // do nothing
                    console.log("Called! [List]");
                    return;
                };
            } catch (e) {
             console.log("okhttp not found");
            }
        });
},0);

6.3 官方推荐的方案

https://developer.android.com/preview/features/security-config.html

  • 在manifest中添加网络安全配置文件
    <?xml version="1.0" encoding="utf-8"?>
    <manifest ... >
        <application android:networkSecurityConfig="@xml/network_security_config"
                        ... >
            ...
        </application>
    </manifest>
  • 自定义可信CA
    假设您要连接到使用自签名 SSL 证书的主机,或者连接到其 SSL 证书由您信任的非公共 CA(如公司的内部 CA)颁发的主机。
    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <domain-config>
            <domain includeSubdomains="true">example.com</domain>
            <trust-anchors>
                <certificates src="@raw/my_ca"/>
            </trust-anchors>
        </domain-config>
    </network-security-config>
    

其他配置可见官方文档,不再赘述。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 13:08:02  更:2022-10-17 13:10:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:36:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码