接受所有证书的 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
如果 Android WebViewClient
的 onReceivedSslError
方法始终在给定的 SslErrorHandler
上调用 proceed
,则它会信任任何证书。这允许攻击者对应用程序执行中间人攻击,从而破坏传输层安全性 (TLS) 提供的任何安全性。
攻击可能如下所示
易受攻击的应用程序连接到
https://example.com
。攻击者拦截此连接,并为
https://example.com
提供有效的自签名证书。易受攻击的应用程序调用
onReceivedSslError
方法以检查是否应该信任该证书。您的
WebViewClient
的onReceivedSslError
方法调用了SslErrorHandler.proceed
。由于您的
WevViewClient
通过继续操作信任了证书,因此易受攻击的应用程序会接受该证书并继续连接。攻击者现在可以读取您的应用程序发送到
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();
}
}
}