Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -388,12 +388,46 @@ Broadcasts can be either **asynchronous**, reaching all receivers without order,

To understand a receiver's functionality, look for the **`onReceive`** method within its class. This method's code can manipulate the received Intent, highlighting the need for data validation by receivers, especially in **Ordered Broadcasts**, which can modify or drop the Intent.

#### Weak receiver challenge-response and crash-to-restart primitives

Some OEM apps try to protect an exported receiver with a broadcasted challenge-response, but the challenge is generated from a **static `Random`** seeded once at process start (`new Random(System.currentTimeMillis())`). If you can force a restart or approximate the launch time, the receiver secret becomes brute-forceable within a very small seed window.

What to look for:
- exported receivers/services expecting a `VERIFY_*` / `AUTH_*` value back through another broadcast
- static or global `Random` instances seeded from wall-clock time
- 30-60 second verification windows
- other exported components that crash on `intent.getData()`, missing extras, or bad casts, giving you a **restart primitive**

In exploit chains, a null-deref or similar DoS in another exported component can reset the process and make the receiver-side RNG state predictable.

### Content Provider

**Content Providers** are essential for **sharing structured data** between apps, emphasizing the importance of implementing **permissions** to ensure data security. They allow apps to access data from various sources, including databases, filesystems, or the web. Specific permissions, like **`readPermission`** and **`writePermission`**, are crucial for controlling access. Additionally, temporary access can be granted through **`grantUriPermission`** settings in the app's manifest, leveraging attributes such as `path`, `pathPrefix`, and `pathPattern` for detailed access control.

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.

#### DocumentProvider restore/import path traversal

When an exported receiver or service accepts **`DocumentProvider` / tree URIs** and then copies them into a local folder, the bug may live in the **consumer** rather than in the provider. A common anti-pattern is deriving the destination path from `DocumentsContract.getDocumentId(srcUri)` with string operations and passing the result directly into `new File(...)`.

```java
File dstFile = new File(
DocumentsContract.getDocumentId(srcUri)
.replaceFirst(rootDocumentId, tempFolderPath) // no canonicalization
);
try (InputStream in = resolver.openInputStream(srcUri);
OutputStream out = new FileOutputStream(dstFile)) {
// copy attacker-controlled bytes
}
```

If the attacker controls the provider, encoded traversal such as `data%2F..%2Fpayload.apk` becomes `data/../payload.apk` after decoding and can escape the intended directory. This yields an **arbitrary file write inside the victim app sandbox**, often enough to overwrite cached plugins, downloaded APKs, or restore targets.

Audit checklist:
- restore/import/migration actions receiving arrays of URIs (`SAVE_URI_PATHS`, `EXTRA_STREAM`, `ClipData`)
- calls to `DocumentsContract.getDocumentId`, `Uri.getPath`, `mkdirs`, `openInputStream`, `FileOutputStream`
- missing `getCanonicalPath()` + `startsWith(<allowed_dir>)` validation on the final destination

### 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.
Expand Down Expand Up @@ -454,6 +488,41 @@ To control file access:

- **Digital signing** is a must for Android apps, ensuring they're **authentically authored** before installation. This process uses a certificate for app identification and must be verified by the device's package manager upon installation. Apps can be **self-signed or certified by an external CA**, safeguarding against unauthorized access and ensuring the app remains untampered during its delivery to the device.

#### Deterministic installer cache / artifact substitution

If a store, updater, or helper component downloads an installable artifact to a **deterministic path**, check how it decides the file is "already downloaded". A dangerous pattern is a cache hit based only on **existence + size** (for example `file.length() >= expectedSize`) before a later install stage.

If you can write attacker-controlled bytes to that exact path, the install flow may reuse the substituted artifact on the next deep link / broadcast / API trigger. This becomes especially useful when the app auto-installs helper APKs, plugins, or "shell" launchers without user confirmation.

#### Custom APK verifier confusion / mixed-scheme abuse

Some stores and updaters perform their own APK signature verification before handing the file to Android's Package Installer. Audit whether that logic matches the platform rules.

Red flags:
- a present **v3** signing block fails signer validation but the custom verifier **falls back to v2** instead of rejecting
- v2 verification checks only the signature over the embedded digest, but **does not recompute the digest from the APK contents**
- package-name or metadata checks exist, but signer validation is not bound to the actual file body

This can enable a **dual-signed APK**:
1. Build the payload with the expected package name.
2. Sign it with an attacker-controlled **v3** signature only.
3. Transplant a trusted APK's **v2** signing block into the payload.
4. The custom verifier accepts the trusted v2 block, while Android installs the same APK using the valid attacker v3 block.

```bash
apksigner sign \
--ks key.jks \
--out payload-v3.apk \
--v1-signing-enabled false \
--v2-signing-enabled false \
--v3-signing-enabled true \
payload.apk

apksigner verify --verbose --print-certs payload-v3.apk
```

This pattern is relevant in OEM app stores, plugin managers, enterprise installers, or any code path that tries to enforce a custom signer allowlist outside the normal Android verifier.

### **App Verification for Enhanced Security**

- Starting from **Android 4.2**, a feature called **Verify Apps** allows users to have apps checked for safety before installation. This **verification process** can warn users against potentially harmful apps, or even prevent the installation of particularly malicious ones, enhancing user security.
Expand Down Expand Up @@ -583,11 +652,15 @@ Tools / scripts that speed-up Binder reconnaissance:
- [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[]))
- [Android Open Source Project - APK signature scheme v3](https://source.android.com/docs/security/features/apksigning/v3)
- [Android Developers - apksigner](https://developer.android.com/tools/apksigner)
- [Deep-C – Android deep link exploitation framework](https://github.com/KishorBal/deep-C)
- [Unsafe use of deep links - Android Developers](https://developer.android.com/privacy-and-security/risks/unsafe-use-of-deeplinks)
- [Create deep links - Android Developers](https://developer.android.com/training/app-links/deep-linking)
- [Samsung Developer - Shell APK](https://developer.samsung.com/instant-plays/shell-apk.html)
- [Bugscale - Here We Go Again: A Five-Bug Chain to Arbitrary APK Install on Samsung S25](https://bugscale.ch/blog/here-we-go-again-a-five-bug-chain-to-arbitrary-apk-install-on-samsung-s25/)
- [bugscale/samsung-s25-research - graft_sig.py](https://github.com/bugscale/samsung-s25-research/blob/main/local-apk-install/graft_sig.py)
- [Microsoft Authenticator’s Unclaimed Deep Link: A Full Account Takeover Story (CVE-2026-26123)](https://khaledsec.medium.com/microsoft-authenticators-unclaimed-deep-link-a-full-account-takeover-story-cve-2026-26123-e0409a920a02)

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