HackIt!2013: Level 2 (y II)

Según esta web, la contraseña para acceder a un repo Maven puede ser generada a partir de una contraseña maestra así:

$ mvn --encrypt-master-password Oone3vei
{wsJL3n5FpasHjLctHj2HuHIoc8DBGtpIWp2bc40vkBU=}
$ mvn --encrypt-password Thu8luuV
{uD995k4e9YEHeRC0LWz4jIEv/kAt5Mt/up3X62RoJIs=}

Es decir, si la contraseña maestra fuera Oone3vei, se generaría esto: {wsJL3n5FpasHjLctHj2HuHIoc8DBGtpIWp2bc40vkBU=}, lo que deberíamos guardar en el fichero settings-security.xml. A partir de esa contraseña maestra, podremos generar otras (¿para distintos repos Maven?¿para distintos usuarios del mismo repo?). En el ejemplo, tomando el password Thu8luuV, y a partir de la contraseña maestra, se generará el pass
{uD995k4e9YEHeRC0LWz4jIEv/kAt5Mt/up3X62RoJIs=}, que se guardará en setttings.xml.

Teniendo ambos ficheros, ¿es posible obtener el string que se usó como password y que generó el pass cifrado de settings.xml? Sí, usando el siguiente código Java:

import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
import org.sonatype.plexus.components.cipher.PlexusCipher;
import org.sonatype.plexus.components.cipher.PlexusCipherException;
 
public class Prueba {
 
	public static void main(String[] args) {
		PlexusCipher cipher;
		try {
			cipher = new DefaultPlexusCipher();
			String masterPw = cipher.decrypt("CO0lvhBKZAMHPlguhfnJAWS6zgpLe5BoQO/AwhVwJX/4UEPxkeqBjVKAq+yK37ft", "settings.security");
		String appPw = cipher.decrypt("9FANUCx4GboHlC12nghO/i+oVV4RRSw1grsm6or+KiYJ2tSEAG5BSWAgq1QCmejj9Q4kpppWwU8caX2PioJD1w==", masterPw);
		System.out.println(appPw);
 
	} catch (PlexusCipherException e) {
		e.printStackTrace();
	} 
	}
 
}

Por cierto, necesitarás instalar los paquetes .jar de Plexus Cipher para poder compilar ese código:

$ sudo apt-get install libplexus-cipher-java

HackIt! 2013

Selection_421HackIt! es el concurso de seguridad informática de la Euskal Encounter en el que compiten más de 80 equipos y gana w0per 😉 El resto de los equipos jugamos en otra liga por intentar quedar en segundo o tercer puesto. Este año en DL conseguimos el objetivo, tras andar como el gato y el ratón con Navarparty. Grandes estos navarros!

Realmente el HackIt! consta de 2 secciones, el propiamente llamado HackIt, +-10 retos donde en general se requieren amplios conocimientos técnicos/ informáticos para pasar más allá de la prueba 4)  y SolveIt, +-8 retos, donde se plantean pruebas con menor componente técnico y más ingredientes de ingenio.

Esta edición del HackIt, como las últimas (2012, 2011, 2010) ha sido organizada por @marcan y está desde hace unos días online. Siempre estaré agradecido a su labor (este año. ademaś, le ha dedicado un toque especial generando banners de «patrocinadores», que servían como ayuda/pista en algún  nivel :-P)  De hecho, es la prueba que me sigue haciendo perder el sueño y dedicar 3 días a «jugar».

Como cada año, al terminar el HackIt! me gusta retomar algunas de las pruebas, para comentarlas con el resto de compañeros, y aprender de los demás. Nuestra forma de solucionar puede no ser la óptima, ni siquiera la forma más ortodoxa. Incluso en una de las pruebas (Trollencio!) fue pura chiripa, como veréis. Por ello, me gustaría que los grupos o individuos que se pasaron dichas pruebas (antes o ahora, post-mortem) comentaran sus impresiones en este post.

Selection_423Comencemos con la primera. Hack It 1: WTF!»#$%&()~ . Analizando el código vemos que se carga un fichero Javascript desde la ruta /hackit/1/static/checkpw.js . ¿Y qué tenemos ahí? Un monstruo como el de la figura de la izquierda. Fíjense en el scroll vertical 🙂 Se trata de código Javascript codificado en un alfabeto con sólo 8 caracteres : ()[]{}!+  Una especie de codificación BrainFuck, pero en Javascript. Útil para intentar saltarse detectores de intrusión, reglas de firewall, etc… porque a ver quién es el majo que interpreta eso 😛

En fin, si abrimos una consola Javascript en Chrome y seguimos el artículo del autor de esta monstruosidad (o belleza, según cómo se mire), empezaremos a entenderlo. La idea es conseguir interpretar cualquier instrucción Javascript usando sólo ()[]{}+-  . Lo primero será saber cómo obtener los caracteres alfanuméricos: a-z0-9, pues con ellos ya tendremos un buen camino recorrido.

Selection_424Si ejecutamos +[] , obtendremos un 0 (casting de un array vacío a integer). Con ![] un false (casting a boolean de un array vacío). Si negamos ese valor !![] obtendremos un true, y al convertirlo a entero +!![], un 1. Con estos 2 números y el operador de suma, podremos obtener cualquier otro dígito (con algunos trucos que muestra el autor, esto se puede simplificar, para no tener ristras enormes cuando necesitamos un numero como 128). ¿Y las letras?  Bueno, empecemos con algo más sencillo. Si esto es un array [] (vacío), y esto devuelve un 0 +[], entonces, ¿qué ocurrirá si intentamos acceder a la primera posición (0) de un array vacío? [][+[]] . Que obtendremos la cadena «undefined». ¿Y si hacemos un casting de un objeto a número? +{}  . Javascript nos dirá que eso no es posible con la cadena «NaN» (not a number).  Accediendo a los caracteres de esas cadenas (indexándolas como arrays de caracteres), tendremos ya unas cuantas letras (u, n, d, e, f, i , a) . Siguiendo este mismo truco el autor explica cómo conseguir todo el alfabeto. Ahora nos hace falta una función que, dado como parámetro un string, evalúe dicho string como si el nombre de una función se tratara. Este trabalenguas no es sino para introducir la función «Function», que hace precisamente eso:

Function(«alert(1)»)()

construirá la función alert() a partir de la cadena pasada como parámetro (en concreto, construirá alert(1) y la ejecutará, mostrando ese 1 en pantalla). Este post en castellano nos ayudó a terminar de entender cómo funcionaba todo, os lo recomiendo. En definitiva, es posible ejecutar en el navegador cualquier función a partir de un churro de caracteres ()[]{}+ .  En su día, el maligno ya nos habló de este experimento, pero no le hice demasiado caso, hasta hoy 🙂

Bien, ¿y cómo pasarnos entonces este primer nivel? Realmente no hace falta entender nada de lo que he explicado hasta ahora 😛 , porque se puede resolver «de chiripa». La cuestión es que si conseguimos ejecutar checkpw.js  en un navegador nos saltará un alert con el password. Ojo! Para que el brainfuck funcione, necesita acceder a la letra «p» de alguna forma, y el artículo indica que ésto es posible si el script se carga desde una localización http://loquesea.com  (la p la sacará del nombre del protocolo, httP ) . Así que no vale con cargar el script con protocolo file:// o directamente desde la consola del navegador, como intentamos mil veces 🙂

Crazy Geek Puzzle

Los retos que plantean en Geek Puzzle son demasiado adictivos para alguien con pasión por la informática. Hay que contenerse durante el día para no sucumbir a intentar conquistar la solución. Ser disciplinado y aguantar hasta la noche. Ahí ya eres libre para coger tu taza de café, tu papel y boli, y comenzar a pensar en qué escurridizo, enfermizo, demencial algoritmo has de seguir para alcanzar el objetivo que el Puzzle plantea. El puzzle #4, ha estado robándome horas de sueño desde el domingo a la noche. Encontrar la vía de penetración en un sistema del que lo desconoces todo y sabes que salvo el puerto de referencia todo lo demás está cerrado a cal y canto es demasiado atractivo como para dejarlo pasar si una de tus aficiones, o hobby, o trabajo, es la seguridad informática. No hay nada tan bueno ni tan malo como que tu trabajo sea además tu hobby. Nunca desconectarás… Y si una vez superado ese reto, consigues entrar, comunicarte con esa máquina como el autor del puzzle pretendía, obtienes como respuesta otro reto aún si cabe más complejo, ya no puedes parar. Has pasado la mitad del puente, la segunda mitad no puede ser tan compleja como para darte la vuelta ahora… hay que seguir. Hasta que consigues llegar casi hasta el otro lado… y te das cuenta de que la mente del creador del reto 4 de Geek Puzzle debe de ser parecida a la de éste otro amante de los puzzles 😉 Sí, una última prueba, un último esfuerzo… es lo que te pide para poder dormir tranquilo esta noche. Y por supuesto, mientras haya café, lo seguiremos intentando 😉

Proyecto Euler: reto a tus conocimientos de programación

El Proyecto Euler publica una serie de problemas de programación en los que es necesario tener algo más que conocimientos matemáticos básicos para resolverlos. Aunque las matemáticas ayudarán a encontrar soluciones elegantes y eficientes, el uso de un ordenador y buenos conocimientos de programación serán más que necesarios para resolver la mayoría de los problemas.

La motivación por la que comenzó el Proyecto Euler es la de ofrecer una plataforma para la mente inquieta que quiera adentrarse en nuevas áreas y aprender nuevos conceptos de una forma divertida e interesante.

¿Quieres saber en qué nivel están tus conocimientos de programación? Prepara tu cafetera, coge papel y lápiz, y entra en el Proyecto Euler…

Hackit! Nivel 4: ingeniería inversa

Al igual que en el nivel 3, un pequeño formulario con login y password ocupa la pantalla. A diferencia del nivel 3, donde tuvimos que romper un applet Java, en esta ocasión se nos plantea romper un componente Flash. Es decir, podemos asumir que la lógica que valida un login y un password está en el propio componente Flash, y que por tanto, se intenta garantizar la seguridad por ocultación… lo cual no suele funcionar (como acabamos de comprobar). Bien, hay que averiguar cuál es el algoritmo de validación que oculta el fichero binario .swf (Flash). El procedimiento: igual que en 3, obtener un buen descompilador de Flash, estudiar el código que genere y averiguar el camino a seguir, es decir, un poquito de ingeniería inversa sobre .swf. Esta prueba no fue tan fácil como la anterior; a pesar de ello, la clave cayó bastante rápido gracias a que uno de los miembros del equipo se llevó la artillería preparada en una máquina Windows… Desvelaré el secreto más adelante, dejo el fin de semana para que os divirtáis y cojáis fuerza para el nivel 5, que se nos atragantó a unos cuantos grupos… pero eso… es otra historia que contaré la semana que viene 😉