ImageMagick安全策略评估工具:提升图像处理库的安全性

本文深入探讨ImageMagick安全策略配置文件(policy.xml)的重要性,分析常见配置错误,介绍策略评估工具的使用,并提供严格的策略模板以防范资源耗尽、格式滥用等安全风险,帮助开发者加固应用安全。

ImageMagick安全策略评估工具

在我们的审计过程中,偶尔会遇到ImageMagick安全策略配置文件(policy.xml),这些文件用于限制库的默认行为和资源消耗。在实际环境中,这些文件通常包含大量从互联网上复制粘贴的建议。这通常由两个原因造成:

其选项仅在库的在线文档页面上一般性描述,没有明确说明策略允许的每个安全指令所规范的内容。虽然架构复杂性和策略可定义的选项粒度是新手的最大障碍,但相应的知识库可能更受欢迎。默认情况下,ImageMagick带有无限制的策略,必须由开发人员根据其用途进行调整。根据文档,“这为在沙盒环境中运行的ImageMagick安装提供了最大的实用性,可能在Docker实例中,或在防火墙后面,与公共网站相比,安全风险大大降低。”还提供了一个安全严格的策略,但正如过去所指出的,并不总是配置良好。

ImageMagick支持超过100种主要文件格式(不包括子格式)类型的图像格式。多年来影响该库的臭名昭著的漏洞产生了一些紧急安全修复和变通方法,涉及添加策略项以排除受影响的格式和功能(2016年的ImageTragick,2018年@taviso通过GhostScript的RCE,2020年@insertScript通过PDF密码的shell注入,2021年@alexisdanizan的漏洞)。

实现更安全的策略

考虑到这一点,我们决定研究ImageMagick安全策略解析器接受的所有选项的效果,并编写一个工具来协助开发人员和安全团队设计和审计这些文件。由于可用选项的数量和需要明确拒绝所有不安全设置,这通常是一项手动任务,可能无法识别破坏策略强度的细微绕过。设置看似有效但提供无实际安全益处的策略也很容易。该工具的检查基于我们的研究,旨在帮助开发人员加强其策略并提高应用程序的安全性,确保策略提供有意义的安全益处,并且不能被攻击者颠覆。

该工具可在imagemagick-secevaluator.doyensec.com/找到。

允许列表与拒绝列表方法

可以在网上找到许多看似安全的策略,指定了一个不安全的编码器列表,类似于:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
...
<policy domain="coder" rights="none" pattern="EPHEMERAL" />
<policy domain="coder" rights="none" pattern="EPI" />
<policy domain="coder" rights="none" pattern="EPS" />
<policy domain="coder" rights="none" pattern="MSL" />
<policy domain="coder" rights="none" pattern="MVG" />
<policy domain="coder" rights="none" pattern="PDF" />
<policy domain="coder" rights="none" pattern="PLT" />
<policy domain="coder" rights="none" pattern="PS" />
<policy domain="coder" rights="none" pattern="PS2" />
<policy domain="coder" rights="none" pattern="PS3" />
<policy domain="coder" rights="none" pattern="SHOW" />
<policy domain="coder" rights="none" pattern="TEXT" />
<policy domain="coder" rights="none" pattern="WIN" />
<policy domain="coder" rights="none" pattern="XPS" />
...

在ImageMagick 6.9.7-7中,推送了一个未列出的更改。策略解析器的行为从如果策略中至少有一个无权限规则则不允许使用编码器,变为尊重策略中编码器的最后一个匹配规则。这意味着在现代策略中可以采用允许列表方法,首先拒绝所有编码器权限并启用经过审查的编码器。更安全的策略将指定:

1
2
3
4
5
...
<policy domain="delegate" rights="none" pattern="*" />
<policy domain="coder" rights="none" pattern="*" />
<policy domain="coder" rights="read | write" pattern="{GIF,JPEG,PNG,WEBP}" />
...

大小写敏感性

考虑以下指令:

1
2
3
...
<policy domain="coder" rights="none" pattern="ephemeral,epi,eps,msl,mvg,pdf,plt,ps,ps2,ps3,show,text,win,xps" />
...

使用此指令,转换仍将被允许,因为策略模式是大小写敏感的。编码器和模块在策略中必须始终为大写(例如“EPS”而不是“eps”)。

资源限制

在ImageMagick中实现拒绝服务相当容易。要获取一组新的有效负载,可以方便地在库的Github存储库上报告的最新问题中搜索“oom”或类似关键词。这是一个问题,因为接受潜在恶意输入的ImageMagick实例(通常如此)总是容易受到攻击。因此,该工具还会报告策略是否未明确设置合理的限制。

策略碎片化

一旦定义了策略,重要的是确保策略文件生效。与发行版捆绑或通过多个包管理器安装为依赖项的ImageMagick包可能指定相互干扰的不同策略。在本地机器上快速查找将识别多个policy.xml文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$ find / -iname policy.xml

# macOS上的示例输出
/usr/local/etc/ImageMagick-7/policy.xml
/usr/local/Cellar/imagemagick@6/6.9.12-60/etc/ImageMagick-6/policy.xml
/usr/local/Cellar/imagemagick@6/6.9.12-60/share/doc/ImageMagick-6/www/source/policy.xml
/usr/local/Cellar/imagemagick/7.1.0-45/etc/ImageMagick-7/policy.xml
/usr/local/Cellar/imagemagick/7.1.0-45/share/doc/ImageMagick-7/www/source/policy.xml

# Ubuntu上的示例输出
/usr/local/etc/ImageMagick-7/policy.xml
/usr/local/share/doc/ImageMagick-7/www/source/policy.xml
/opt/ImageMagick-7.0.11-5/config/policy.xml
/opt/ImageMagick-7.0.11-5/www/source/policy.xml

策略也可以使用-limit CLI参数、MagickCore API方法或环境变量进行配置。

入门级严格策略

从官方文档中描述的最严格策略开始,我们设计了一个收集我们所有观察结果的严格策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<policymap xmlns="">
  <policy domain="resource" name="temporary-path" value="/mnt/magick-conversions-with-restrictive-permissions"/> <!-- 该位置应仅对运行ImageMagick的低权限用户可访问 -->
  <policy domain="resource" name="memory" value="256MiB"/>
  <policy domain="resource" name="list-length" value="32"/>
  <policy domain="resource" name="width" value="8KP"/>
  <policy domain="resource" name="height" value="8KP"/>
  <policy domain="resource" name="map" value="512MiB"/>
  <policy domain="resource" name="area" value="16KP"/>
  <policy domain="resource" name="disk" value="1GiB"/>
  <policy domain="resource" name="file" value="768"/>
  <policy domain="resource" name="thread" value="2"/>
  <policy domain="resource" name="time" value="10"/>
  <policy domain="module" rights="none" pattern="*" /> 
  <policy domain="delegate" rights="none" pattern="*" />
  <policy domain="coder" rights="none" pattern="*" /> 
  <policy domain="coder" rights="write" pattern="{PNG,JPG,JPEG}" /> <!-- 您可接受的受限格式集,根据您的权限需求设置 -->
  <policy domain="filter" rights="none" pattern="*" />
  <policy domain="path" rights="none" pattern="@*"/>
  <policy domain="cache" name="memory-map" value="anonymous"/>
  <policy domain="cache" name="synchronize" value="true"/>
  <!-- <policy domain="cache" name="shared-secret" value="my-secret-passphrase" stealth="True"/> 仅适用于跨多个服务器的分布式像素缓存 -->
  <policy domain="system" name="shred" value="2"/>
  <policy domain="system" name="max-memory-request" value="256MiB"/>
  <policy domain="resource" name="throttle" value="1"/> <!-- 定期让出CPU至少指定的时间(毫秒) -->
  <policy xmlns="" domain="system" name="precision" value="6"/>
</policymap>

您可以使用identify命令验证安全策略是否激活:

1
2
3
identify -list policy
Path: ImageMagick/policy.xml
...

在开发定制策略时,您也可以使用我们的评估工具试验上述策略。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计