在其中一个规则中,SonarQube不允许盲目接受每个主机的虚拟HostnameVerifier
:
Client client = ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String requestedHost, SSLSession remoteServerSession) {
return true; // Noncompliant
}
}).build();
此示例作为合规代码提供:
Client client = ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String requestedHost, SSLSession remoteServerSession) {
return requestedHost.equalsIgnoreCase(remoteServerSession.getPeerHost()); // Compliant
}
}).build();
但是在 javadoc for SSLSession.getPeerHost(( 中,我可以读到:
此值未经身份验证,不应依赖。它主要用作SSLSession缓存策略的提示。
这让我很困惑。如果getPeerHost()
值不可信,那么它如何成为推荐的合规代码来修复漏洞?安全与否?它阻止了什么样的攻击,它无法防止哪些攻击?
虽然使用"peerHost"而不是一揽子的"return true"肯定要好得多,但它仍然不是没有风险。 "对等主机"可以通过反向 DNS 检索。这导致了 CWE-350 的一个缺陷:依赖反向 DNS 解析执行安全关键操作,MITRE 对此表示如下:
由于 DNS 名称很容易被欺骗或误报,并且软件可能很难检测受信任的 DNS 服务器是否已遭到入侵,因此 DNS 名称不构成有效的身份验证机制。
当软件对 IP 地址执行反向 DNS 解析时,如果攻击者控制该 IP 地址的服务器,则攻击者可能导致服务器返回任意主机名。因此,攻击者可能能够绕过身份验证,导致在日志文件中记录错误的主机名以隐藏活动,或执行其他攻击。
攻击者可以通过 (1( 破坏 DNS 服务器并修改其记录(有时称为 DNS 缓存中毒(或 (2( 合法控制与其 IP 地址关联的 DNS 服务器来欺骗 DNS 名称。
最好的做法是解决给定的主机名与证书中的主机名不匹配的根本问题。 请注意,SonarSource 已更新其示例代码以反映这一点:https://rules.sonarsource.com/java/RSPEC-5527