首页 > 解决方案 > 在 HostnameVerifier 中信任 peerHost 是否安全?

问题描述

其中一条规则中, 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();

但是在SSLSession.getPeerHost()的 javadoc 中,我可以读到:

此值未经身份验证,不应依赖。它主要用作 SSLSession 缓存策略的提示。

这让我很困惑。如果该getPeerHost()值不可信,那么它如何成为修复漏洞的推荐合规代码?它安全吗?它阻止了哪些攻击,哪些攻击没有阻止?

标签: javasecuritysslsonarqube

解决方案


虽然使用“peerHost”而不是笼统的“返回真实”肯定要好得多,但它仍然不是没有风险。'peerHost'可以通过反向 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


推荐阅读