我想使用 SSL Pinning 保护我的应用免受中间人 (mitm) 攻击。
默认情况下,可以使用像 Charles 或 mitmproxy 这样的代理来拦截流量,并使用自签名证书对其进行解密。
经过广泛的研究,我发现了几种选择:
添加
NSPinnedDomains > MY_DOMAIN > NSPinnedLeafIdentities
到Info.plist
Apple 文档:Identity Pinning
Guardsquare:利用基于 Info.plist 的证书固定
优点:简单
缺点:一旦更新证书/私钥(通常在几个月后),应用程序将无法使用添加
NSPinnedDomains > MY_DOMAIN > NSPinnedCAIdentities
到Info.plist
Apple 文档:与上述相同
优点:简单。叶证书更新没有失败,因为根 CA 被固定(过期日期为几十年)
缺点:似乎多余,因为大多数根 CA已经包含在操作系统中检查代码中的证书
URLSessionDelegate
>SecTrustEvaluateWithError
(或 Alamofire 包装器)
Ray Wenderlich:使用 SSL Pinning 防止 iOS 中的中间人攻击
Apple 文档:处理身份验证挑战
Medium 文章:关于 SSL Pinning 需要了解的一切
Medium 文章:保护 iOS具有 SSL Pinning
优点的应用程序:更大的灵活性。可能更安全。Apple 推荐(参见上面的 Apple 链接)。
缺点:(1)或(2)的一个更费力的版本。关于叶子到期/根 CA 冗余的缺点与 (1) 和 (2) 相同。更复杂。添加 NSExceptionDomains > MY_DOMAIN > NSRequiresCertificateTransparency 到 Info.plist
Apple 文档:部分 Info.plist 键“证书透明度”
优点:非常简单。没有多余的 CA 集成。
缺点:文档不清楚这是否应该用于 ssl pinning
经过评估,我得出以下结论:
- 由于证书过期,不适合生产应用程序
- 可能是简单性、安全性和可持续性之间的最佳平衡——但我不喜欢重复添加系统已经知道的根 CA
- 太复杂,太冒险,任何实现错误都可能锁死应用
- 我的首选方式。简单的。在我的测试中有效,但文档不明确。
我很想使用选项(4),但我不确定这是否真的适用于 ssl pinning。
在文档中它说:
证书透明度 (CT) 是 ATS 可用于识别错误或恶意颁发的 X.509 证书的协议。将 NSRequiresCertificateTransparency 键的值设置为 YES 以要求对于给定域,服务器证书由来自 Apple 信任的至少两个 CT 日志的有效签名 CT 时间戳支持。有关证书透明度的更多信息,请参阅 RFC6962。
并在链接的 RFC6962 中:
本文档描述了一个实验性协议,用于公开记录传输层安全 (TLS) 证书的存在 [...]
术语“实验性协议”和“公开日志记录”对我来说是一个标志,虽然在 Info.plist 中启用该功能似乎可以解决 SSL 固定问题,但我不确定是否应该使用它。
我绝不是安全专家,我需要一个非常简单的解决方案,它可以为我提供体面的保护,同时保护我免于因可能过期/更改的证书而窒息我自己的应用程序。
我的问题:
我应该NSRequiresCertificateTransparency
在我的应用程序上使用 ssl pinning 和防止 mitm-attacks 吗?
如果不:
我应该改用什么?
PS:
在这个线程中基本上已经提出了同样的问题:
https ://developer.apple.com/forums/thread/675791
然而,答案是模糊的NSRequiresCertificateTransparency
(4。在我上面的列表中):
对,证书透明度是一个很好的工具,用于验证提供的叶子是否包含一组 SCT(签名证书时间戳),或者嵌入在证书(RFC 6962)中,通过 TLS 扩展(可以在数据包跟踪中看到),或者通过检查证书的 OCSP 日志。当您在应用程序中做出信任决定时,我建议您通过 SecPolicyRef 对象查看 is 属性。
附加说明:
作为一家具有安全意识的公司,我对 Apple 的期望是,默认情况下会启用对根 CA 的固定,并且我必须手动添加异常,例如允许在调试版本时使用 Charles 代理。我听说Android就是这样做的。