¿Es posible utilizar sólo 6 caracteres para programar en JavaScript?
El lenguaje de programación JavaScript es un lenguaje no tipado, esto significa que se pueden crear variables sin especificar el tipo de dato. Esta característica permite que, al hacer operaciones, el resultado dependa de la operación que se realiza y del tipo de datos de las variables involucradas, por ejemplo: var c = a + b;
Si “a” tiene un valor entero de 1 y “b” tiene un valor entero de 2, el resultado “c” tendría el valor entero de 3. La situación cambia si a “b” se le da como valor el carácter “2”; el resultado de c sería la cadena de texto “12”. Como se puede observar en este ejemplo, la operación “suma” cambió a una operación de “concatenación”, derivando en un resultado distinto. A esto también se le conoce como tipado dinámico, que consiste en que, al no estar directamente asociadas las variables con un tipo de dato, se les permite cambiar de acuerdo con el tipo de operación realizada.
Con base en lo anterior, se puede escribir código JavaScript utilizando sólo los siguientes seis caracteres, y a esto se le conoce como JSFuck: [ ]( ) + !
Esto es posible debido a las partes atómicas del lenguaje JavaScript que van directamente relacionadas con su tipado dinámico, lo cual se traduce en los tipos de conversión de datos, la precedencia y asociatividad de los operadores, la interpretación de los valores falsos y negativos, y el uso de la notación con corchetes. Veamos un ejemplo sencillo con la interpretación de una cadena vacía, la cual se puede considerar como un arreglo de caracteres. Entonces tendríamos algo como lo siguiente: [ ]
Sin embargo, JavaScript podría considerar ese arreglo de datos como cualquier tipo de dato, por lo que se requiere una conversión, y para ello utilizamos el operador “+”: [ ]+[ ]
Lo que está sucediendo es que la operación sobre estos arreglos de datos, de los cuales no se conoce su tipo, dará como resultado una conversión de datos, en este caso una concatenación que resultará en una cadena vacía. Otro ejemplo sería obtener a partir de un arreglo de datos vacío un valor negativo (false), entonces partimos de lo siguiente: [ ]
Nuevamente tenemos un arreglo de datos que no sabemos su tipo, y utilizamos un operador para hacer la conversión de datos, en este caso el signo “!”: ![ ]
Esta operación es booleana y el resultado es false. Esto sucede porque todos los valores no definidos son considerados por el lenguaje como un valor negativo, y al agregar el operador sólo se realiza la conversión del valor no definido al tipo de dato booleano. Entonces si quisiéramos obtener un valor positivo (true), es necesario volver a aplicar el operador “!” para hacer la conversión de false a true: !![ ]
Finalmente, si ese valor booleano lo quiero interpretar como una cadena de caracteres, es decir la palabra “true”, entonces utilizo el operador “+” de la siguiente forma: !![ ]+[ ]
Con lo anterior se vuelve a realizar una conversión de datos de tipo booleano a una cadena de caracteres. Este tipo de técnica es utilizado por muchos ciberdelincuentes para evadir mecanismos de protección contra ataques de tipo Cross-Site Scripting, ya que funciona muy bien cuando un dato de entrada es reflejado sobre la función “eval2” o en los eventos de campos HTML, como son: “onload, onclick, onerror”, etc. A pesar de que la inyección daría como resultado una cadena de texto con una longitud grande, sigue siendo un método de ataque eficiente para evadir mecanismos de protección como Web Application Firewalls.
Scitum recomienda al realizar una validación de datos de entrada en aplicaciones, asegurarse de que cada campo cumpla con un cierto formato y longitud específica. Adicional, como parte fundamental para mitigar ataques tipo “JSFuck”, se sugiere codificar los datos de salida con respecto al contexto en donde serán reflejados o almacenados, es decir, con base al lenguaje donde será reflejado el dato. No es lo mismo utilizar una codificación de caracteres HTML que utilizar una codificación de caracteres JavaScript. Lo ideal es utilizar la codificación para JavaScript.
Referencias:
http://www.jsfuck.com/
https://github.com/aemkei/jsfuck