CodeQL 文档

接受所有证书的 Android WebView

ID: java/improper-webview-certificate-validation
Kind: problem
Security severity: 7.5
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-295
Query suites:
   - java-code-scanning.qls
   - java-security-extended.qls
   - java-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

如果 Android WebViewClientonReceivedSslError 方法始终在给定的 SslErrorHandler 上调用 proceed,则它会信任任何证书。这允许攻击者对应用程序执行中间人攻击,从而破坏传输层安全性 (TLS) 提供的任何安全性。

攻击可能如下所示

  1. 易受攻击的应用程序连接到 https://example.com

  2. 攻击者拦截此连接,并为 https://example.com 提供有效的自签名证书。

  3. 易受攻击的应用程序调用 onReceivedSslError 方法以检查是否应该信任该证书。

  4. 您的 WebViewClientonReceivedSslError 方法调用了 SslErrorHandler.proceed

  5. 由于您的 WevViewClient 通过继续操作信任了证书,因此易受攻击的应用程序会接受该证书并继续连接。

  6. 攻击者现在可以读取您的应用程序发送到 https://example.com 的数据,和/或在其回复时对其进行更改,而应用程序认为连接是安全的。

建议

不要无条件地使用调用 SslerrorHandler.proceed。如果您必须使用自签名证书,请仅接受该证书,而不是所有证书。

示例

在第一个(错误)示例中,WebViewClient 通过始终调用 SslErrorHandler.proceed 来信任所有证书。在第二个(正确)示例中,只接受由某个公钥签名的证书。

class Bad extends WebViewClient {
    // BAD: All certificates are trusted.
    public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { // $hasResult
        handler.proceed(); 
    }
}

class Good extends WebViewClient {
    PublicKey myPubKey = ...;

    // GOOD: Only certificates signed by a certain public key are trusted.
    public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { // $hasResult
        try {
            X509Certificate cert = error.getCertificate().getX509Certificate();
            cert.verify(this.myPubKey);
            handler.proceed();
        }
        catch (CertificateException|NoSuchAlgorithmException|InvalidKeyException|NoSuchProviderException|SignatureException e) {
            handler.cancel();
        }
    }    
}

参考

  • ©GitHub 公司
  • 条款
  • 隐私