不安全的证书信任¶
ID: java/unsafe-cert-trust
Kind: problem
Security severity: 9.8
Severity: warning
Precision: medium
Tags:
- security
- external/cwe/cwe-273
Query suites:
- java-security-extended.qls
- java-security-and-quality.qls
Java 提供了两种 SSL 身份验证机制 - 信任管理器和主机名验证器(后者由 java/insecure-hostname-verifier
查询检查)。信任管理器验证对等方的证书链,而主机名验证则确保 URL 中的主机名与服务器身份中的主机名匹配。
当 SSLSocket
或 SSLEngine
在没有安全 setEndpointIdentificationAlgorithm
的情况下创建时,主机名验证默认情况下会被禁用。
此查询检查 setEndpointIdentificationAlgorithm
是否缺失,从而使应用程序容易受到中间人攻击。此查询还涵盖了 com.rabbitmq.client.ConnectionFactory
的不安全配置。
建议¶
在 SSL 身份验证中验证 SSL 证书。
示例¶
以下两个示例展示了两种配置 SSLSocket/SSLEngine 的方法。在“BAD”情况下,没有调用 setEndpointIdentificationAlgorithm
,因此不会进行主机名验证。在“GOOD”情况下,调用了 setEndpointIdentificationAlgorithm
。
public static void main(String[] args) {
{
SSLContext sslContext = SSLContext.getInstance("TLS");
SSLEngine sslEngine = sslContext.createSSLEngine();
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); //GOOD: Set a valid endpointIdentificationAlgorithm for SSL engine to trigger hostname verification
sslEngine.setSSLParameters(sslParameters);
}
{
SSLContext sslContext = SSLContext.getInstance("TLS");
SSLEngine sslEngine = sslContext.createSSLEngine(); //BAD: No endpointIdentificationAlgorithm set
}
{
SSLContext sslContext = SSLContext.getInstance("TLS");
final SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443);
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); //GOOD: Set a valid endpointIdentificationAlgorithm for SSL socket to trigger hostname verification
socket.setSSLParameters(sslParameters);
}
{
com.rabbitmq.client.ConnectionFactory connectionFactory = new com.rabbitmq.client.ConnectionFactory();
connectionFactory.useSslProtocol();
connectionFactory.enableHostnameVerification(); //GOOD: Enable hostname verification for rabbitmq ConnectionFactory
}
{
com.rabbitmq.client.ConnectionFactory connectionFactory = new com.rabbitmq.client.ConnectionFactory();
connectionFactory.useSslProtocol(); //BAD: Hostname verification for rabbitmq ConnectionFactory is not enabled
}
}
参考¶
RabbitMQ: 在 Java 客户端中使用 TLS.
CVE-2018-8034:Apache Tomcat - 使用 TLS 与 WebSocket 客户端通信时存在主机名验证问题.
通用弱点枚举:CWE-273.