# ImageMagick: From Arbitrary File Read to RCE In Every Policy

ImageMagick format-detection and policy gaps let a single .jpg/.pdf reach GhostScript, achieving arbitrary file read/write and RCE under open, limited, and secure policies.

- Payout: Research
- Severity: critical
- Program: ImageMagick
- Credited: PWNAI Research
- Disclosed: 2026-03-30
- Write-up quality: 8/10
- Original: https://pwn.ai/blog/imagemagick-from-arbitrary-file-read-to-rce-in-every-policy-zeroday
- Library page: https://bugbountylibrary.com/r/blog%3Apwn-ai-blog-imagemagick-from-arbitrary-file-read-to-rce-in-every-policy-zeroday
- Tags: domain:web impact:data-leak impact:rce kind:research platform:research sev:critical tech:linux tech:php technique:chained technique:source-review vuln:file-upload vuln:misconfiguration vuln:path-traversal vuln:rce

**Target:** ImageMagick convert pipeline, SVG/MSVG renderer, EPSI/EPT/PDF coders, GhostScript delegate
**Root cause:** Format detection is content/magic-byte based and coder modules (EPSI, EPT, PDF) invoke the same GhostScript delegate as blocked PS; policy blocklists omit these modules, and gslib in-process invocation skips the delegate policy check entirely.
**Steps:**
1. File read: `printf '<?xml ...><svg ...><image xlink:href="text:/etc/passwd" .../></svg>' > read.jpg; convert read.jpg output.png` renders /etc/passwd into output
2. PS detection bypass: prefix payload with `\n` so IM's `%!PS` offset-0 check fails while GhostScript still executes
3. PDF bypass: `printf '\n%%!PS-Adobe-3.0 ...\n/f (/tmp/PWNED) (w) file def\nf (HI) writestring\nf closefile\nshowpage\n' > evil.pdf; convert evil.pdf out.png` writes /tmp/PWNED on limited/secure(gslib) policies
4. EPT bypass: file starting with magic `C5 D0 D3 C6` then PostScript body saved as evil.jpg; `convert evil.jpg out.png` writes file despite .jpg extension and limited policy
5. RCE: GhostScript writes PHP/JPEG polyglot + MSL script to /tmp; MSL coder copies polyglot to webroot as .php; PHP executes embedded `<?php system(...) ?>`
6. WordPress: unauthenticated Gravity Forms Post Image field or Author-level XML-RPC `mw_newMediaObject` uploads EPT .jpg through wp_generate_attachment_metadata() to trigger Imagick
**How found:** Agent downloaded ImageMagick into a sandbox and systematically audited format detection, coder selection, delegate invocation, and policy enforcement. Observed that `<?xml` content overrides .jpg extension; traced SVG xlink:href into ReadImage() coder prefixes; enumerated PostScript coders to find EPSI/EPI/EPSF missing from Ubuntu blocklist; tested byte-offset detection to find \n prefix bypass; then enumerated modules absent from limited/secure policy blocklists (PDF, EPT) and checked gslib linkage on Amazon Linux.
**Exploitation:** Attacker uploads a single crafted image (SVG for file read, or \n-prefixed PostScript in .pdf/.jpg/EPT wrapper) to any app passing uploads to ImageMagick. GhostScript delegate executes PostScript under -dSAFER, which still permits file writes to /tmp. A second MSL payload processed by ImageMagick's own unrestricted MSL coder copies a PHP/JPEG polyglot from /tmp into the web root, yielding a webshell (uid=33 www-data confirmed on wordpress:latest Docker and Ubuntu 22.04).
**Escalation:** Chained file read → file write → RCE via MSL coder escaping GhostScript sandbox; extended to pre-auth WordPress (Gravity Forms) and post-auth Author via XML-RPC; /tmp write enables tmpfs OOM DoS, PHP session poisoning, and symlink-following file inclusion.
**Insight:** When a policy blocks a coder by module name, enumerate every other module that reaches the same delegate binary (PDF, EPSI, EPT all hit GhostScript) and check whether the delegate is invoked in-process (gslib) where delegate policy checks never fire. Also test single-byte prefixes against magic-byte offset-0 detection.
