1 背景

爱奇艺SRC团队会对启用https的域名进行监控,检查包括:使用的协议版本、加密套件是否存在漏洞、证书是否过期等。Apple对使用https进行连接有更加严格的要求,叫做App Transport Security(简称ATS)。不符合ATS规范的,不能进行HTTPS链接,目前,ATS规范当前还没有强制实施。

调研之后,我们使用python3实现了检测代码,便于日后ATS强制实施时,对业务部门进行提醒,避免出现HTTPS连接被阻断的情况。

2 ATS有哪几个要求

这里翻译官方的文档,想要做到ATS,需要你的APP的http连接使用https并且满足下列安全要求:

  1. 数字证书必须满足下列一个需求:

    • 由证书颁发机构(CA)颁发,其根证书被合并到操作系统中

    • 由受信任的根CA发出,并由用户或系统管理员安装

  2. 协商的TLS版本必须是TLS 1.2。默认情况下,会拒绝没有TLS/SSL保护的情况下连接,或使用TLS/SSL的旧版本连接。

  3. 连接必须使用AES-128 或 AES-256对称加密。协商的TLS连接加密套件必须使用椭圆曲线Diffie-Hellman Ephemeral (ECDHE)密钥交换算法,支持完全前向保密(PFS),并且必须是以下加密套件:

    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

  4. 对叶服务器证书进行签名必须使用以下类型的密钥之一:

    • RSA,密钥长度最少2048位

    • ECC,密钥长度最少256位

  5. 此外,叶服务器证书哈希算法必须是SHA-2其摘要长度(或称为“指纹”)至少为256(即SHA-256或更高)。

3 检测方法

互联网上公开检测ATS 大致有2种方式

  1. myssl等外部网站提供的检测页面

  2. mac下的nscurl工具,使用方法:nscurl --ats-diagnostics --verbose https://www.iqiyi.com

myssl这类方法,只能单个域名,不方便批量检测,也可能会导致域名相关的敏感信息泄露。nscurl结果可视化很差,且只能在mac上使用。因此,我们自己开发一个程序,完成上述检测功能,由python3实现,在证书检测过程中,我们最开始使用了python3 socket库来进行https连接并获取证书,但是发现效果很差,有2点

  1. 针对配置了SNI的域名,即1个IP根据Hostname不同会返回不同的证书情况,socket不能同时配置IP和域名来进行连接,只使用IP连接时会出现返回不正确证书情况

  2. 没有直接获取加密套件的函数,需要单独实现,且暂时没找到很方便快速简洁获取加密套件的方式

所以我们找到了sslyze这个库,它的包里封装的很多函数解决了上述问题,以下就是具体每点的检测方式

3.1 权威机构颁发检测

首先要建立连接,并获取证书及证书链

我们用sslyze这个库的子函数ServerConnectivityTester来进行HTTPS链接,然后获取证书及证书链信息,可指定每个域名的具体IP进行连接,代码如下:

然后证书链、证书信息、证书有效区间、域名匹配host信息我们就可以获取了,其实如果证书失效,如过期、域名不匹配也会导致不符合ATS要求,在这一步中,我们也顺便检查了这2项

1.证书不过期,获取证书有效期间,当前日期是否在范围内

info['notBefore'] = cert.not_valid_before

info['notAfter'] = cert.not_valid_after

2.证书匹配host info['match_hostname'] = result.certificate_matches_hostname判断证书可使用的域名和当前域名是否一致

3.CA颁发

如何验证根证书是权威机构颁发的呢?正常我们通过浏览器访问https网站,浏览器及操作系统都会存储权威机构CA颁发的根证书列表,windows、macOS、linux都有,我们使用其中的一个就可以了

目前我们使用linux下的 /etc/pki/tls/certs/ca-bundle.crt

还可以使用Apple提供的列表进行对比https://support.apple.com/en-us/HT202858

从证书链获取根证书,然后在ca-bundle.crt里面查找,如果找到即表示证书链根证书是权威机构颁发,如果证书链中的根证书是自己信任的机构颁发,则可以对比受信任的颁发机构根证书和证书链根证书一致即可。

3.2 加密套件要求

使用sslyze的CipherSuiteScanCommand插件来获取每种协议支持的加密套件

代码如下:

获取加密套件后,检查ATS要求的加密套件是否在TLS 1.2协议所支持的套件中,若不存在,则不符合要求。

3.3 使用TLS1.2

利用上一步获取的加密套件字典,如果TLS 1.2内没有加密套件,即未使用TLS 1.2,即可判断是否使用TLS1.2

或者使用socket库使用TLS1.2协议进行链接,看是否正确获取证书,此处代码不列出

3.4 证书签名算法密钥长度要求

利用第一步中获取的cert对象,判断签名算法

如果是使用RSA,判断cert.public_key().key_size长度是否大于2048

如果使用的是ECDSA,判断cert.public_key().key_size是否大于256

3.5 哈希算法及摘要长度

根据 cert.signature_hash_algorithm.name获取hash算法,判断是否使用sha256或在更高级的hash算法

4 结尾

通过上述几项检测,就可以很方便地监控ATS合规性。ATS检测只是我们证书、SSL\TLS检测的一个功能,利用sslyze库还可以做很多其他证书监控的工作,同时也弥补了python sokcet库功能不足的缺点,减少了代码开发的工作。

声明:本文来自爱奇艺安全应急响应中心,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。