1

我正在使用 SSL 在两个对等方之间形成可信连接。每个对等点都知道在给定时间它希望连接到谁(或接受来自谁的连接)。它应该只接受有效的证书,而且它应该只接受具有某些属性的证书(可能通过检查规范名称)。

到目前为止,我可以根据this question中的示例及其答案让双方进行对话。每一方都可以打印出对方出示的证书。

不过,我不确定验证这些证书的正确方法是什么。显而易见的方法是在建立连接后只查看证书,如果它不符合我们的期望,则断开连接。

有没有更正确的方法来做到这一点?是否有一个回调,它给出了对等方提供的证书并且可以给它一个大拇指或大拇指向下?还是在 SSL 完成工作后处理它是正确的?

4

2 回答 2

1

不过,我不确定验证这些证书的正确方法是什么。显而易见的方法是在建立连接后只查看证书,如果它不符合我们的期望,则断开连接。

这有很多,其中一些并不明显。我将把答案分成几部分,但所有部分都试图回答你的问题。


首先,您可以验证证书格式是否正确。在 Web 上下文中负责的组是 CA/浏览器论坛。他们对创建证书有基线和扩展要求:

例如,在基线文档中,您会发现列为通用名称 (CN) 的 IP 也必须列在主题备用名称 (SAN) 中。在扩展文档中,您会发现私有 IP(根据 RFC 1918 保留)不能出现在扩展验证 (EV) 证书中;EV 证书不能包含通配符。


其次,您可以根据 RFC 5280、Internet X.509 公钥基础设施证书和证书撤销列表 (CRL) 配置文件http: //www.ietf.org/rfc/rfc5280.txt 执行常规验证。

常规检查是主机名匹配、时间段有效性检查以及验证最终实体或叶证书(客户端或服务器证书)链回根。在使用 CA 的浏览器中,有数百个受信任的根或中间体。

如果您选择执行吊销检查,那么您可能会对您的应用程序进行 DoS(这很明显!)。3G 网络上的移动客户端无法下载和处理 30MB CRL - 它肯定会挂起应用程序。当 URL 错误时,应用程序无法执行 OCSP 查询 - 这肯定会失败。

此外,如果您正在执行包含通配符的主机名匹配,则必须注意正确处理 ccTLD。ccTLD 类似于 *.eu、*.us 或 இலங்கை (nic.lk)。其中大约有 5000 个,Mozilla 在http://publicsuffix.org/上提供了一个列表(或者,https: //mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw= 1 )。


第三,CA 没有任何保证,因此您从 CA 获得的答案毫无价值。如果您不相信我,请查看他们的认证实践声明 (CPS)。例如,以下是 Apple 的证书颁发机构认证实践声明(2013 年 9 月 18 日,第 6 页)的摘录:

2.4.1. Warranties to Subscribers
The AAI Sub-CA does not warrant the use of any Certificate to any Subscriber.

2.4.2. CA disclaimers of warranties
To the extent permitted by applicable law, Subscriber agreements, if applicable,
disclaim warranties from Apple, including any warranty of merchantability or
fitness for a particular purpose

这意味着他们不保证通过发行人的签名将公钥绑定到组织。这就是 X509! 的全部目的!


第四,DNS 不提供真实的答案。因此,您可能会从 DNS 得到一个错误的答案,然后愉快地转移到由您的对手控制的服务器。或者,美国控制的 13 台根 DNS 服务器中有 10 台可能以美国国家安全的名义串通一气,给你一个错误的答案。

试图从非美国服务器获得真实响应几乎是不可能的。“安全 DNS”部分(无 DNSSEC)仍在不断发展,我不知道有任何主流实现。

在勾结美国服务器的情况下,法定人数将不起作用,因为美国拥有压倒性多数。


这里的问题是您正在根据来自外部服务(CA 和 DNS)的输入做出安全决策。从本质上讲,您也必须信任不值得信赖的演员。

解决 PKI 和 PKIX 问题的一个很好的方法是 Peter Gutmann 博士的工程安全,网址为 www.cs.auckland.ac.nz/~pgut001/pubs/book.pdf。请务必阅读第 1 章和第 6 章。Gutmann 博士具有诙谐的幽默感,因此阅读起来并不枯燥。另一本很棒的书是 Ross Anderson 的《安全工程》,网址为http://www.cl.cam.ac.uk/~rja14/book.html


对于由 PKI、PKIX 和 CA 引起的所有问题,您有几个防御措施。首先,您可以在自己的证书颁发机构中运行私有 PKI。在这种情况下,您不信任外人。应捕获错误的 DNS 答案和流氓服务器,因为服务器的证书不会形成有效的链。

其次,您可以采用安全多元化策略。Gutmann 在他的《工程安全》一书中对此进行了描述,您应该从第 292 页开始访问“通过多样性实现安全”和第 296 页的“Internet 应用程序的风险多样化”部分。

第三,您可以采用首次使用信任 (TOFU) 或密钥连续性策略。这类似于 Wendlandt、Anderson 和 Perrig 的Perspectives: Improvement SSH-style Host Authentication with Multi-Path Probing或 SSH 的StrictHostKeyChecking选项。在此策略中,您进行常规检查,然后固定证书或公钥。您还可以询问其他人对证书或公钥的看法。意外的证书或密钥更改应该敲响警钟。

OWASP 在https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning对证书和公钥固定进行了处理。注意:有些地方每 30 天左右轮换一次证书,所以如果可能的话,你应该固定公钥。频繁轮换列表包括 Google,它是 Certificate Patrol 等工具产生如此大噪音的原因之一。

于 2013-12-02T04:37:34.187 回答
1

在这种情况下,我是 CA,因此信任 CA 不是问题。我代表我的用户签署这些证书。规范名称甚至不是域名。用户点对点连接。我希望我分发的客户端软件验证连接用户是否拥有我签署的证书并且是正确的用户。

听起来您正在运行私有 PKI。SSL_CTX_load_verify_locations只需使用或将信任链的根加载到 OpenSSL 中SSL_load_verify_locations

请务必使用SSL_PEER_VERIFY以确保 OpenSSL 执行验证。电话可能看起来像SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);. 如果对等验证失败,connect则将失败。

有一些方法可以确保connect成功,然后再捕获错误。诀窍是设置验证回调,让验证回调始终返回1,然后SSL_get_verify_result在建立连接后调用。有关示例,请参阅SSL/TLS 客户端。

注意:在所有情况下,您仍然必须手动执行名称检查。OpenSSL 目前不这样做(它在 OpenSSL 1.1.0 的 HEAD 中)。请参阅libcurlPostgreSQL 或 PostgreSQL 以获取您可以破解的一些代码。

OpenSSL 在其 wiki 中提供了 SSL/TLS 客户端的示例。请参阅SSL/TLS 客户端。目前没有服务器代码或示例。

于 2013-12-16T20:42:27.987 回答