El nivel 2 del HackIt! tiene como título «Nivel Cromado». Nos indican que es un nivel sólo compatible con Google Chrome (o Chromium). También hay un enlace a un fichero hackit.crx (una extensión para Chrome). Para instalarla en Chrome lo tuvimos que hacer descomprimiéndola y cargándola desde el botón «Cargar extensión descomprimida» del menú chrome://extensions/ .
Así es como luce en Chrome:
Podemos dedicarle un rato a jugar con la extensión desde el propio navegador, pero poco podremos avanzar. La idea es ir al código fuente de la misma a investigar. Si accedemos a la carpeta descomprimida de la extensión, veremos un fichero ek.js. Si lo abrimos, encontraremos la siguiente monstruosidad:
var _0x5544="click;val;#password;https://hackit2014.marcansoft.com/crx;get;text;show;#mal;#bien;NETWORK ERROR!;ajax;bind;#sendButton;ready".split(";");$(document)[_0x5544[13]](function(){$(_0x5544[12])[_0x5544[11]](_0x5544[0],function(){var a={password:$(_0x5544[2])[_0x5544[1]]()};$[_0x5544[10]]({url:_0x5544[3],type:_0x5544[4],async:!1,data:a,dataType:_0x5544[5],success:function(a){Boolean(parseInt(a))?$(_0x5544[7])[_0x5544[6]]():$(_0x5544[8])[_0x5544[6]]()},error:function(){alert(_0x5544[9])}})})}); |
Bien, habrá que limpiarlo un poco con el mismo beautifier que el level anterior…
var _0x5544 = "click;val;#password;https://hackit2014.marcansoft.com/crx;get;text;show;#mal;#bien;NETWORK ERROR!;ajax;bind;#sendButton;ready".split(";"); $(document)[_0x5544[13]](function() { $(_0x5544[12])[_0x5544[11]](_0x5544[0], function() { var a = { password: $(_0x5544[2])[_0x5544[1]]() }; $[_0x5544[10]]({ url: _0x5544[3], type: _0x5544[4], async: !1, data: a, dataType: _0x5544[5], success: function(a) { Boolean(parseInt(a)) ? $(_0x5544[7])[_0x5544[6]]() : $(_0x5544[8])[_0x5544[6]](); }, error: function() { alert(_0x5544[9]); } }); }); }); |
Vaya… código algo ofuscado. Realmente se puede entender que está lanzando peticiones AJAX a https://hackit2014.marcansoft.com/crx (con el payload: { password : xxxxx }. El resultado veremos que es un número (realmente un string de dígitos). Ese número interpretado como boolean debe dar 0 para que el resultado sea «#bien». Aquí hicimos unas cuantas pruebas y no dimos con el algoritmo interno de la parte servidor (si es que lo hay). Lo que vimos es que podíamos ir generando 0’s dependiendo de las letras con las que comenzara nuestro pass, así que lanzamos un script para probar todas las posibilidades hasta obtener una ristra de todo 0’s O:-) La longitud del pass asumimos que era el tamaño máximo del campo input de la extensión (24 caracteres). Y éste es el script que obtiene la clave (cortesía de @ochoto). Ojo, debe ejecutarse desde la consola Chrome abierta en la propia página del Hackit:
var datos = "click;val;#password;https://hackit2014.marcansoft.com/crx;get;text;show;#mal;#bien;NETWORK ERROR!;ajax;bind;#sendButton;ready".split(";"); function enviar(pass) { resultado = "" $[datos[10]]({ url: datos[3], type: datos[4], async: !1, data: {password: pass}, dataType: datos[5], success: function(a) { resultado = a }, error: function(e) { resultado = "error: " + e } }) return resultado }; String.prototype.replaceAt=function(index, character) { return this.substr(0, index) + character + this.substr(index+character.length); } var lastLength=100 var pass=Array(24).join("a") for(var p=0;p<24;p++) { for(var i=32;i<127;i++){ var caracter = String.fromCharCode(i) pass = pass.replaceAt(p, caracter) var res = enviar(pass) if( res.charAt(p)==0) { console.log(res + ": Encontrada posicion:" + p + ", caracter:" + caracter + ", codigo:" + i) break } } } |
Estoy seguro de que el mismo algoritmo lo hemos visto en alguna prueba de hackits pasados, pero ahora no caigo (estoy mayor :-P).
Como curiosidad, si haces la petición con 24 caracteres nulos, te devuelven directamente la clave en ascii:
https://hackit2014.marcansoft.com/hackit/2/check?password=%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00
72979910710110095671041144810951959510188116101110115105111110
Decodificando en plan guarro:
http://codepad.org/6k5Ezf3V
La extensión se puede instalar de forma «normal» sin descomprimirla. Lo que pasa es que Chrome te lo pone difícil aposta (porque las extensiones pueden contener malware) y no vale con hacer clic al descargarla. Hay que abrir el paner de extensiones, abrir un navegador de archivos (por ejemplo Dolphin en Linux), y con drag&drop soltar la extensión sobre el panel de extensiones. Esta es la forma «oficial» de instalar una extensión que no esté en la Chrome Web Store.
El servidor lo único que hace es paddear la cadena con ‘=’, hacer XOR con la password real, y concatenar el resultado (en decimal). No es necesario hacer fuera bruta, puedes calcular la diferencia de cada carácter. Hace falta un poquito de heurística porque los caracteres no están delimitados, así que a priori no sabes si el número es de un, dos, o tres dígitos (así que puedes probar las tres opciones). También se puede resolver a mano.