Android WebView that accepts all certificates¶
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
Click to see the query in the CodeQL repository
If the onReceivedSslError method of an Android WebViewClient always calls proceed on the given SslErrorHandler, it trusts any certificate. This allows an attacker to perform a machine-in-the-middle attack against the application, therefore breaking any security Transport Layer Security (TLS) gives.
An attack might look like this:
- The vulnerable application connects to - https://example.com.
- The attacker intercepts this connection and presents a valid, self-signed certificate for - https://example.com.
- The vulnerable application calls the - onReceivedSslErrormethod to check whether it should trust the certificate.
- The - onReceivedSslErrormethod of your- WebViewClientcalls- SslErrorHandler.proceed.
- The vulnerable application accepts the certificate and proceeds with the connection since your - WevViewClienttrusted it by proceeding.
- The attacker can now read the data your application sends to - https://example.comand/or alter its replies while the application thinks the connection is secure.
Recommendation¶
Do not use a call SslerrorHandler.proceed unconditionally. If you have to use a self-signed certificate, only accept that certificate, not all certificates.
Example¶
In the first (bad) example, the WebViewClient trusts all certificates by always calling SslErrorHandler.proceed. In the second (good) example, only certificates signed by a certain public key are accepted.
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();
        }
    }    
}
References¶
- Common Weakness Enumeration: CWE-295. 



