可以使用伪造的开放 WiFi 服务来设置典型的攻击。我想说,当人们坐在酒吧或任何类似的情况下,他们会尝试连接到他们可以找到的开放 WiFi 网络,这是非常现实的。
尤其是在移动设备上,警告消息似乎比桌面软件上的更加晦涩难懂(此外,在酒吧中,用户血液中的少量酒精可能会促使警告更加被忽略)。假设某些应用程序可能会定期轮询其服务器也是相当现实的,即使设备在用户的口袋里:编程不当的应用程序很可能会以这种方式泄露凭据或其他信息。
BBC 新闻最近的一篇文章( Android 应用程序“泄露”个人详细信息)指出了这篇论文:为什么 Eve 和 Mallory 喜欢 Android:Android SSL (In)Security 的分析。
以这种方式指责 Android 听起来有点危言耸听,但不幸的是,它确实反映了许多应用程序的状态。Android 的情况可能来自 Java 传统,默认情况下不进行主机名验证,如果您直接使用SSLSocket
.
iOS 家族的情况可能会好一些,因为苹果似乎拒绝了禁用证书验证的应用程序(我对此没有任何个人经验)。不过,我不确定是否允许匿名密码套件,这可能与此类拒绝政策不一致。
我认为开发人员倾向于认为证书很复杂,也许不是每个人,但至少有相当数量的开发人员。诚然,证书处理起来有点麻烦,但如果你妥善管理它们的使用,为开发设置测试 CA 并不比为单元测试设置其他形式的虚拟数据难多少(让我们只是假设您在测试环境中不需要 CRL/OCSP,尽管理想情况下您也需要)。
您是否想责怪图书馆或开发人员是有争议的。
并非所有库都是平等的,也并非所有库都针对相同类别的用户/开发人员。
SSL/TLS 堆栈默认不验证主机名的一大原因是主机名验证机制取决于顶部使用的应用程序协议。最常见的一种当然是 HTTPS(RFC 2818,第 3.1 节)。这通常被用作不在那里实施主机名验证的原因。不过情况正在发生变化:RFC 6125尝试在所有协议中统一主机名验证方法。它尚未广泛实施,但无论如何它与 HTTPS 行为并没有太大区别。此外,Java 7 现在有一种使用特定SSLParameters
(启用X509ExtendedTrustManager
)验证主机名的方法,这使得打开主机名验证更加方便,即使使用SSLSocket
直接(没有额外的层HttpsURLConnection
)。
同样的原因不应该适用于更高级别的库,例如那些提供 HTTPS 访问的库。不幸的是,一些用户无论如何都希望以一种或另一种方式禁用证书验证。(不幸的是,有些图书馆似乎不想解决这个问题。)
根据我在 StackOverflow 上的经验,有很多关于忽略证书错误的问题(今天又是一个)。一些建议完全禁用任何信任管理的答案被接受,有时甚至得到高度评价。(有时,您甚至会因为建议做正确的事情而遭到反对,尽管不可否认,这确实不能完全回答问题。)
我不确定在这种情况下更好的默认库行为是否会有所帮助,因为那些询问的人只想忽略错误。考虑 Java 示例,大多数人抱怨当他们收到异常时发生的错误,因为远程主机不受信任。关于如何验证主机名的问题要少得多(SSLSocket
直接使用 s 时默认不会这样做)。
我不确定 SO 社区的代表性有多大,但有些人只想快速修复,至少要开始使用应用程序的其余部分。我的猜测是,即使在它保留在“发布前修复”列表中的情况下,由于它是静默的,在某些情况下它实际上从未得到修复(特别是因为“正在使用 SSL/TLS”框仍然打勾) .
当然,提前发布的压力加上对证书似乎缺乏了解导致了这类问题。
并非该领域的所有参与者都有帮助(例如,一些主要的认证机构)。如果您是一个对证书知之甚少的开发人员,并尝试从您从 CA 站点获得的文档中学习,这通常会很困难。(经典的是,大多数 CA 暗示他们提供执行 256 位加密的证书,这充其量是误导性的。其他人的常见问题解答中充满了错误和/或误导性信息。其他人让您购买“SSL”(请参阅页面底部)。)