daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

imagemagick-security.md (7947B)


      1 ---
      2 title: "ImageMagick Security"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-web/imagemagick-security.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/imagemagick-security.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # ImageMagick Security
     14 
     15 Check further details in [**https://blog.doyensec.com/2023/01/10/imagemagick-security-policy-evaluator.html**](https://blog.doyensec.com/2023/01/10/imagemagick-security-policy-evaluator.html)<sup>[[1]](#references)</sup>
     16 
     17 ImageMagick is commonly used behind upload, thumbnailing, document-conversion, and CI/CD pipelines. That makes it a high-value target whenever untrusted images, SVGs, EPS, PS, or PDFs reach `magick` / `convert`.
     18 
     19 Classic **ImageTragick**-style payloads are only part of the story. A modern chain can start from a **single SVG** and end in **arbitrary file write** by abusing how ImageMagick generates MVG plus how it delegates EPS/PS parsing to Ghostscript.
     20 
     21 ## SVG -> MVG injection -> `msl:` execution
     22 
     23 When ImageMagick rasterizes SVG, it first emits an intermediate **MVG** script. If attacker-controlled SVG data reaches that generated MVG without normalizing both LF and CR, an XML-encoded carriage return (`&#13;`) can become a **new MVG line**.<sup>[[2]](#references)</sup>
     24 
     25 A practical injection point is the `<polyline points="...">` attribute because the points string is copied into MVG almost verbatim. A payload like:<sup>[[2]](#references)</sup>
     26 
     27 ```xml
     28 <polyline points="0,0 50,50&#13;image Over 0,0 1,1 'msl:/tmp/payload.msl'&#13;100,0"/>
     29 ```
     30 
     31 can turn one SVG attribute into attacker-controlled MVG commands.<sup>[[2]](#references)</sup>
     32 
     33 The most useful primitive is:<sup>[[2]](#references)</sup>
     34 
     35 ```text
     36 image Over X,Y W,H 'URL'
     37 ```
     38 
     39 This does **not** only load remote HTTP resources. It can also trigger internal coders / protocol handlers such as `data:` and `msl:`.<sup>[[2]](#references)</sup>
     40 
     41 If `msl:` is reachable, an attacker can execute **Magick Scripting Language** from disk and turn the bug into **arbitrary file write**:<sup>[[2]](#references)</sup>
     42 
     43 ```xml
     44 <image>
     45   <read filename="xc:red[10x10]"/>
     46   <write filename="png:/var/www/html/poc.png"/>
     47 </image>
     48 ```
     49 
     50 This is different from older ImageTragick payloads: instead of directly trying to get shell metacharacters into a delegate command, the chain abuses **MVG line injection** and then pivots into a **second-stage MSL script**.<sup>[[2]](#references)</sup>
     51 
     52 ## Ghostscript delegate as the file dropper
     53 
     54 ImageMagick usually sends **EPS/PS/PDF** work to a **Ghostscript delegate**. That matters even for an SVG upload, because injected MVG can load an embedded:
     55 
     56 ```text
     57 data:image/x-eps;base64,...
     58 ```
     59 
     60 payload.<sup>[[2]](#references)</sup>
     61 
     62 In the published **ImagePanick** repro, Ghostscript `10.06.0` running under SAFER can be abused as a file dropper:<sup>[[2]](#references)</sup><sup>[[3]](#references)</sup>
     63 
     64 - `.tempfile` creates a writable temp file and also extends the read/write/control permit lists for that temp path.
     65 - `writestring` stores attacker-controlled MSL bytes.
     66 - `renamefile` moves the random temp name to a predictable filename such as `/tmp/payload.msl`.
     67 
     68 Then a second injected MVG line loads:<sup>[[2]](#references)</sup>
     69 
     70 ```text
     71 msl:/tmp/payload.msl
     72 ```
     73 
     74 and ImageMagick executes the MSL, producing **arbitrary file write**. From there, writing into a web root, cron path, shell init file, or `authorized_keys` is usually enough for practical RCE or persistence.<sup>[[2]](#references)</sup>
     75 
     76 For more Ghostscript-centric notes, see [Ghostscript Injection](/hacktricks/pentesting-web/formula-csv-doc-latex-ghostscript-injection).
     77 
     78 ## Quick triage
     79 
     80 If a target processes untrusted images, first check which dangerous coders and delegates are still available:
     81 
     82 ```bash
     83 magick -list policy
     84 identify -list format | grep -E 'SVG|MSL|PS|EPS|PDF'
     85 convert -list delegate | grep -iE 'gs|ghostscript'
     86 find / -iname policy.xml 2>/dev/null
     87 ```
     88 
     89 If the application accepts SVG and the backend simply does:
     90 
     91 ```bash
     92 magick input.svg output.png
     93 ```
     94 
     95 that alone may be enough to trigger the chain when weak policies and a Ghostscript delegate are present.
     96 
     97 ## Towards Safer Policies
     98 
     99 To address these challenges, a [tool has been developed](https://imagemagick-secevaluator.doyensec.com/) to aid in designing and auditing ImageMagick's security policies. This tool is rooted in extensive research and aims to ensure policies are not only robust but also free from loopholes that could be exploited.<sup>[[1]](#references)</sup>
    100 
    101 ## Allowlist vs Denylist Approach
    102 
    103 Historically, ImageMagick policies relied on a denylist approach, where specific coders were denied access. However, changes in ImageMagick 6.9.7-7 shifted this paradigm, enabling an allowlist approach. This approach first denies all coders and then selectively grants access to trusted ones, enhancing the security posture.<sup>[[1]](#references)</sup>
    104 
    105 ```xml
    106   ...
    107   <policy domain="coder" rights="none" pattern="*" />
    108   <policy domain="coder" rights="read | write" pattern="{GIF,JPEG,PNG,WEBP}" />
    109   ...
    110 ```
    111 
    112 ## Case Sensitivity in Policies
    113 
    114 It's crucial to note that policy patterns in ImageMagick are case sensitive. As such, ensuring that coders and modules are correctly upper-cased in policies is vital to prevent unintended permissions.<sup>[[1]](#references)</sup>
    115 
    116 ## Resource Limits
    117 
    118 ImageMagick is prone to denial of service attacks if not properly configured. Setting explicit resource limits in the policy is essential to prevent such vulnerabilities.<sup>[[1]](#references)</sup>
    119 
    120 ## Policy Fragmentation
    121 
    122 Policies may be fragmented across different ImageMagick installations, leading to potential conflicts or overrides. It's recommended to locate and verify the active policy files using commands like:<sup>[[1]](#references)</sup>
    123 
    124 ```bash
    125 $ find / -iname policy.xml
    126 ```
    127 
    128 ## A Starter, Restrictive Policy
    129 
    130 A restrictive policy template has been proposed, focusing on stringent resource limitations and access controls. This template serves as a baseline for developing tailored policies that align with specific application requirements.<sup>[[1]](#references)</sup>
    131 
    132 The effectiveness of a security policy can be confirmed using the `identify -list policy` command in ImageMagick. Additionally, the [evaluator tool](https://imagemagick-secevaluator.doyensec.com/) mentioned earlier can be used to refine the policy based on individual needs.<sup>[[1]](#references)</sup>
    133 
    134 For **untrusted uploads**, prefer an **allowlist**.<sup>[[1]](#references)</sup> If SVG / EPS / PS are not required, explicitly block the dangerous coders instead of trying to blacklist individual bad payloads:<sup>[[2]](#references)</sup>
    135 
    136 ```xml
    137 <policy domain="coder" rights="none" pattern="{SVG,EPS,PS,MSL}" />
    138 ```
    139 
    140 Additional hardening:
    141 
    142 - Disable the Ghostscript delegate in `delegates.xml` if EPS / PS support is not needed.<sup>[[2]](#references)</sup>
    143 - Keep coder names upper-cased because policy patterns are **case sensitive**.<sup>[[1]](#references)</sup>
    144 - Prefer a dedicated SVG rasterizer such as `librsvg` for untrusted SVG instead of full ImageMagick + Ghostscript.<sup>[[2]](#references)</sup>
    145 - Run conversions in a sandbox (`nsjail`, `firejail`, container, read-only filesystem, restricted tmpdir).<sup>[[2]](#references)</sup>
    146 
    147 ## References
    148 
    149 - [1] [ImageMagick Security Policy Evaluator](https://blog.doyensec.com/2023/01/10/imagemagick-security-policy-evaluator.html)
    150 - [2] [ImagePanick: From SVG to RCE Chaining Weak Policies and Bugs in ImageMagick and Ghostscript](https://blog.deephacking.tech/en/posts/imagepanick-from-svg-to-rce-imagemagick-ghostscript/)
    151 - [3] [ImagePanick PoC / Docker lab](https://github.com/e1abrador/ImagePanick/)