Analizando un método de bypass de sistemas WAF
Horacio Rivero
Posted on March 26, 2020
El método que se muestra en la imagen es comúnmente utilizado en ofuscación de código javascript malicioso para realizar ataques de XSS, para los que se preguntar para que ofuscar este código?, bueno los Firewalls o los sistemas conocidos como WAF por ejemplo los de Clouflare, Akamai, filtran todo tipo de código malicioso antes de que este llegue a a una servidor/servicio/gateway/proxy reverso de backend, pero gracias algunas técnicas es posible pasar alguno de estos filtros.
El código a continuación es capaz de pasar varios tipos de filtros:
Ahora lo interesante es saber por que este segmento de código es capaz de ejecutarse y saber que esta ocurriendo en el fondo.
Analicemos que esta ocurriendo por partes
// obtiene el valor unicode representado de forma decimal
'('.charCodeAt() // 40
// se pasa de valor unicode decimal a su repretacion hexadecimal base 16
Number(charCode).toString(16) // 28
// se pasa de su valor expresado de forma hexadecimal a su presetacion decimal base 10
Number(0x0028) // 40
// representación de valores unicode hexadecimales a string, siguiendo el ejemplo anterior entoces podemos representar los valores de esta forma reemplazado "0" por "/" y "x" por "u"
'\u0028' // '('
'\u0029' // ')'
// ahora realicemos la representación corta y ocultemos los paréntesis ya que estos van a ser detectados por los filtros
'\x28' // '('
'\x29' // ')'
// gracias a los template string incorporados en ES6, ahora las funciones pueden ser invocadas de esta forma ``, esto es algo que ya muchos saben.
const test = (msg) => alert(msg[0])
test`hello wold`
// como todos saben el constructor de Set y de cualquier funcion es Function, por ende cada función va a heredan el comportamiento de invocación que se muestra en la función test
Set.constructor instanceof Function // true
test.constructor instanceof Function // true
// entonces si creamos una función y luego la invocamos comprenderemos que ocurre cuando se invoca al contructor de esta forma Function``
Function(['console.log("hello")', 'console.log("world")'])() // hello world
// lo que realiza el constructor de la función de arriba es algo muy similar a esto
const fn = (fns) => Function(fns.reduce((c, fn) => c += `${fn};`, ''))
fn(["console.log('hello')", "console.log('world')"])() // hello world
Ahora expresamos la función del principio de otra forma para que se vea todo más claro, creamos una función y pasamos como argumento un bloque de instrucciones y luego invocamos la función resultante.
Bueno como lo ven no es tan complejo, existen algunos métodos que realmente contiene bastante complejidad, pueden ver alguno de ellos en este enlace:
Posted on March 26, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.