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 yourWebViewClientcallsSslErrorHandler.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.