This sample connects to https://tlsexpired.no, which has an expired SSL certificate, and demonstrates how a WebView ignores SSL/TLS errors by overriding the onReceivedSslError(...) method without proper validation. The app calls proceed() unconditionally, which allows the connection to continue even when there are TLS errors.
packageorg.owasp.mastestappimportandroid.content.Contextimportandroid.net.http.SslErrorimportandroid.util.Logimportandroid.webkit.SslErrorHandlerimportandroid.webkit.WebViewimportandroid.webkit.WebViewClientclassMastgTestWebView(privatevalcontext:Context){funmastgTest(webView:WebView){webView.apply{webViewClient=object:WebViewClient(){overridefunonReceivedSslError(view:WebView,handler:SslErrorHandler,error:SslError){valmessage=getSslErrorMessage(error)Log.e("MastgTestWebView","SSL errors onReceivedSslError: $message")Log.e("MastgTestWebView",error.toString())handler.proceed()}}loadUrl("https://tlsexpired.no")}}privatefungetSslErrorMessage(error:SslError):String=when(error.primaryError){SslError.SSL_UNTRUSTED->"The certificate authority is not trusted."SslError.SSL_EXPIRED->"The certificate has expired."SslError.SSL_IDMISMATCH->"The certificate Hostname mismatch."SslError.SSL_NOTYETVALID->"The certificate is not yet valid."SslError.SSL_DATE_INVALID->"The date of the certificate is invalid."else->"SSL Certificate error."}}
packageorg.owasp.mastestapp;importandroid.content.Context;importandroid.net.http.SslError;importandroid.util.Log;importandroid.webkit.SslErrorHandler;importandroid.webkit.WebView;importandroid.webkit.WebViewClient;importkotlin.Metadata;importkotlin.jvm.internal.Intrinsics;/* compiled from: MastgTestWebView.kt */@Metadata(d1={"\u0000*\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0003\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0018\u0002\n\u0000\b\u0007\u0018\u00002\u00020\u0001B\u000f\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0004\b\u0004\u0010\u0005J\u000e\u0010\u0006\u001a\u00020\u00072\u0006\u0010\b\u001a\u00020\tJ\u0010\u0010\n\u001a\u00020\u000b2\u0006\u0010\f\u001a\u00020\rH\u0002R\u000e\u0010\u0002\u001a\u00020\u0003X\u0082\u0004¢\u0006\u0002\n\u0000¨\u0006\u000e"},d2={"Lorg/owasp/mastestapp/MastgTestWebView;","","context","Landroid/content/Context;","<init>","(Landroid/content/Context;)V","mastgTest","","webView","Landroid/webkit/WebView;","getSslErrorMessage","","error","Landroid/net/http/SslError;","app_debug"},k=1,mv={2,0,0},xi=48)/* loaded from: classes3.dex */publicfinalclassMastgTestWebView{publicstaticfinalint$stable=8;privatefinalContextcontext;publicMastgTestWebView(Contextcontext){Intrinsics.checkNotNullParameter(context,"context");this.context=context;}publicfinalvoidmastgTest(WebViewwebView){Intrinsics.checkNotNullParameter(webView,"webView");webView.setWebViewClient(newWebViewClient(){// from class: org.owasp.mastestapp.MastgTestWebView$mastgTest$1$1@Override// android.webkit.WebViewClientpublicvoidonReceivedSslError(WebViewview,SslErrorHandlerhandler,SslErrorerror){Intrinsics.checkNotNullParameter(view,"view");Intrinsics.checkNotNullParameter(handler,"handler");Intrinsics.checkNotNullParameter(error,"error");Stringmessage=this.this$0.getSslErrorMessage(error);Log.e("MastgTestWebView","SSL errors onReceivedSslError: "+message);Log.e("MastgTestWebView",error.toString());handler.proceed();}});webView.loadUrl("https://tlsexpired.no");}/* JADX INFO: Access modifiers changed from: private */publicfinalStringgetSslErrorMessage(SslErrorerror){switch(error.getPrimaryError()){case0:return"The certificate is not yet valid.";case1:return"The certificate has expired.";case2:return"The certificate Hostname mismatch.";case3:return"The certificate authority is not trusted.";case4:return"The date of the certificate is invalid.";default:return"SSL Certificate error.";}}}
The test fails because the app uses a WebView that calls proceed() in its onReceivedSslError(...) method without validating the TLS error at all. You can manually validate this in the app's reverse-engineered code by inspecting the provided code locations.
By doing this, the app is effectively ignoring every TLS error even though we can see that the expired certificate error is logged (see Monitoring System Logs):