Algunas herramientas de “auditoría” de passwords (hash MD5) Hoy por hoy, casi todos nosotros estamos registrados en algún foro: fútbol, fórmula 1, seguridad informática (no, éste no es un buen ejemplo)... Todos tenemos nuestro par (user, password), tan apreciado por la gente malvada ansiosa de saber. Pues bien, como el user es trivial conocerlo, basta con leer los post del foro(...), “sólo” nos queda como elemento súperprivado el password, y he aquí el uso de las funciones hash. Sin querer ser nada exhaustivo, una función hash, asigna a un determinado conjunto de bytes, el mensaje, su huella. Existen multitud de funciones hash: md4, md5, SHA­1, SHA­256, SHA­512, ¿SHA­3? (Es broma, se espera que para el 2012). Normalmente lo que se hace es hashear el password y guardar este hash en la BD del servidor. Así, cuando te conectas, lo que envías a través de la red es el hash del password que has tecleado, si no coinciden no hay duda de que no eres quien dices ser, y si coinciden, pues estás autentificado, todo esto suponiendo que el concepto de colisión, aunque muy importante y principal motivo de ir jubilando viejas funciones hash es bastante muy pero que requetemuy improbable, casi casi rozando lo imposible, aunque sí, que aunque casi nadie las ha visto, las hay, como las meigas poco más o menos (“Non existen, pero habelas hainas”). Como ejemplo de colisiones podemos ver http://es.wikipedia.org/wiki/Secure_Hash_Algorithm donde observamos que la complejidad de SHA­1 ha sido disminuida, que se sepa, a 2⁶³, siendo 2¹²⁸ la esperada, porque 128 son el nº de bits del mensaje resumen. Este tipo de logros se basan en un principio en el llamado “ataque de cumpleaños”, que es un ataque estadístico (sí, vale para algo) sobre la paradoja del cumpleaños “en una habitación con 23 personas, ¿cuál es la probabilidad de que 2 de ellas cumplan el mismo día? (50'7%)” Esto se parece a lo que entendemos por colisión, 2 mensajes distintos que tienen la misma huella, y por ahí viene todo este rollo que se escapa un poco de nuestras pretensiones pero que está bien saber de qué va. Por otra banda, la función hash seguramente más conocida sea md5, 128 bits, igual que SHA­1, pero más antigua, y por lo tanto, más quemada. Pero a lo que vamos, a “probar la fortaleza de nuestras passwords”. Existen muchas formas, y entre las informáticas seguramente las más conocidas son las RainbowTables, sin mayor complicación, y las herramientas de propósito específicico como son Caín, LHC, md5crack, BarsWF... con un funcionamiento particular cada una de ellas. Nosotros vamos a ver unas comparativas entre 2 de estas herramientas, intentando analizar en lo posible su funcionamiento. •Caín y Abel v4.9.35 : Si bien es verdad que la utilidad que vamos a usar es una entre las muchas que tiene: sniffing, spoofing, “auditoría” de passwords... •BarsWF v0.8 (existen versiones de 32 y 64 bits para SSE2, versiones de 32 y 64 bits para uso en GPUs, librería CUDA sobre Nvidia, librería­lenguaje Brook+ sobre ATI ) ( http:// 3.14.by/en/md5 ). Máquina de prueba: Pentium 4 Ubuntu 9.04 Windows XP 3.0 Ghz 512MB RAM (Anfitrión) (Virtualizado sobre VirtualBox) 1MB caché Efectuaremos un ataque tipo “pseudo­fuerza bruta”, porque “sabemos” el alfabeto posible, con 36 posibles caracteres [a­z0­9]+, frente a los 95 imprimibles. Es por esto que el nº de posibilidades a tener en cuenta es : longitud 1 : 36 longitud 2 : 36*36 longitud 3 : 36*36*36 . . . . . . Pues bien, como se puede observar, el nº de posibilidades a comprobar empezando por las de menor longitud e incrementando, corresponde a una serie geométrica, y, recordando aquellos tiempos pretéritos de ESO, el nº total de elementos a comprobar hasta longitud n será: (36^(n+1) ­ 36) / (36­1) con lo que se puede apreciar que para llegar a comprobar todos los posibles pass hasta longitud 5, 62193780 ~ 62 millones longitud 10, 3760620109779060 ~ 3760 billones longitud 15, 227390317427040025268340 ~ 227390 trillones todo esto, teniendo en cuenta nuestro alfabeto, bastante limitado, pero que sigue siendo el más usado por usuarios convencionales (seamos realistas, ningún amigo nuestro que use su PC para 4 tonterías tiene un pass en su e­mail de 10 o 12 caracteres mezclando mayúsculas, minúsculas, números y símbolos “raros”). Porque si nos vamos a un alfabeto menos convencional [A­Za­z0­9¿? ¡!%{}] (los corchetes no los tenemos en cuenta en este caso) nos iríamos a: longitud 5, 1587031809 ~ 1587 millones longitud 10, 2482167502723212150 ~ 2 trillones longitud 15, 3882187787728146674164722159 ~ 3882 cuatrillones y esto sin tener en cuenta todos los posibles caracteres imprimibles, con lo que un password de este tipo se vuelve prácticamente impracticable, salvo que nos podamos montar en una nave abandonada un súper­mega­clúster, ¡y aún así! Es cuestión de echar cuentas. Con la última cantidad calculada, supongamos que disponemos de ese clúster de 1000000 de procesadores de 8 núcleos funcionando al 100% siempre (el más potente de España, MareNostrum, cuenta con 10240 procesadores, si bien no del mismo tipo, pero para esta explicación se capta la idea de sobra). Suponiendo que cada núcleo fuese capaz de calcular 1 billón de posibilidades por segundo (deberían ir a cientos de TeraHz/seg) se tardaría unos 15 años y casi 5 meses en recorrer todo ese espacio de búsqueda, y todo esto para que al final el pass buscado fuese a tener 20 caracteres, con lo cual no habríamos conseguido absolutamente nada salvo gastar mucho dinero en electricidad, lugar, mantenimiento a supervelocidad... y, sobre todo, nuestro tiempo. E incluso podemos ponernos en un caso aún peor. Supongamos que sí hemos sido capaces de descubrir el pass. Vamos, lo probamos, y resulta que no funciona, ¡todas las organizaciones y personas medio serias cambian sus pass medianamente importantes cada cierto periodo de tiempo! Pero bueno, nosotros, como curiosos que somos, hemos de suponer que la gente es idiota (como diría House), y por lo tanto se ha realizado una breve comparativa, de juguete, intentando ver como funcionan las susodichas herramientas. Algunos resultados obtenidos: ( alfabeto de prueba :[a­z0­9]+ ) Caín BarsWF_SSE2 32 bits Password : Hash md5 Tiempo CPU Velocidad media Tiempo CPU Velocidad media hh:mm:ss (millones/segundo) hh:mm:ss (millones/segundo) jfcmq : f8e628c8a390e752819c96399e73d74c 00:00:05 00:00:05 5'83 5'84 00:00:04 00:00:04 11'22 11'37 pepito : 32164702f8ffd2b418d780ff02371e4c 00:02:41 00:02:40 5'84 5'88 00:01:57 00:01:57 13'81 13'89 qwerty : d8578edf8458ce06fbc5bb76a58c5ca4 00:04:31 00:04:27 5'70 5'79 00:01:10 00:01:11 13'99 13'86 5kfh7qm : cfd88d7572d7cdf929937c251aeaa8c6 01:23:59 01:24:20 5'83 5'80 00:42:30 00:42:17 14'09 14'17 2010psi : 479b6ea311be3376929d5dd1f9f712df 00:59:10 00:59:19 5'85 5'83 00:05:17 00:05:17 14'15 14'12 a3zza7a : 36c8cefe5a9e2550abf4f82c6fa77ae6 00:11:58 00:12:00 5'90 5'88 01:35:23 01:35:39 14'08 14'03 Sabiendo que con un código del algoritmo MD5 implementado en C, público, de John Walker, versión 2.0 del 15­04­2003, http://www.fourmilab.ch/md5/, en el link versión del 2008, funcionando sobre una sencilla interfaz también en C en la misma máquina de las pruebas anteriores, se consigue una velocidad media de aproximadamente 350000 hashes/seg, y a la vista de estos resultados, podemos sacar varias conclusiones: 1.BarsWF ofrece una velocidad media claramente superior, casi 14 millones/seg. Mientras que Caín anda cerca de los 6 millones/seg. Lo que significa que BarsWF es un 233% más rápido en término medio. Ahora bien, ¿por qué? ¿Cómo funciona? Bien, a partir de aquí entran las conjeturas, pero una cosa está clara, el uso de las instrucciones vectoriales SSE2, que actúan a su vez sobre registros de 128 bits (¡qué casualidad! Como los hashes a comparar) proporcionan una ventaja ante cualquier problema, y habrá que esperar a los ordenadores cuánticos (esperemos que para antes del 2050) para darle la vuelta a la tortilla. 2.Reutilización de parámetros. Esto ya es más difícil de intuir. Fijándonos los pasos del algoritmo del md5: 1. Adición de bits 2. Longitud del mensaje 3. Inicializar el búffer MD 4. Procesado del mensaje en bloques de 16 palabras (aquí está la chicha) 5. Salida (Bien detallado en http://es.wikipedia.org/wiki/MD5 ) En un primer vistazo, se ve que aunque el paso 1, el de adición de bits no es siempre igual, digamos que tiende a repetirse primero 36 veces, luego 36*36, después 36*36*36, y así... Entonces, estaría bien tener esto en cuenta a la hora de añadir los bits, porque digamos que podría ser bueno tener un mensaje inicial ya extendido y después sólo modificar los pocos bits que han cambiado, al ser ataques exhaustivos por fuerza bruta, como veremos más adelante. Con este mismo razonamiento podemos concluir que en el paso 2 pasa más de lo mismo, por lo que no nos vamos a repetir. El paso 3 es siempre el mismo, con lo que sería bueno tener esos datos en registros antes de cada ejecución, simplemente ocuparían 4 registros en un procesador de 32 bits, y después sería un copiar a otro. También se observa que lo último del paso 4 son 4 operaciones con los valores que tenían inicialmente los elementos del paso 3, con lo que el razonamiento podría ser análogo al anterior. Pero a partir de ahí, empieza la verdadera magia, es decir, intentar encontrar algo que se repita en el algoritmo y que se pueda reutilizar. Esto escapa de las pretensiones de este articulillo, así que se deja a libertad del lector el profundizar en el algoritmo, aunque es cierto que su uso es cada vez menor y así seguirá la tendencia. 3.Van más rápido en Windows. Esta es posiblemente la más llamativa, por lo menos, al autor se lo parece, y eso quiere decir que o bien la implementación de John Walker no es todo lo correcta que debería, cosa poco probable, basta con buscar un poco en la red sobre este personaje, o bien las implementaciones de los programillas anteriores se aprovechan de alguna clase de “bug” del algoritmo a la hora de probar muchas combinaciones, como son algunas de las explicadas, o bien alguna otra que se ha escapado... 4.Y por último, pero posiblemente la más importante, la velocidad media del BarsWF dista en mucho de lo anunciado por su creador (más información en http://3.14.by/en/read/md5_benchmark ), con lo que probaremos este programa en otra máquina más potente, incluida la versión sobre GPU, que es posiblemente la más prometedora. Como curiosidad, fijémonos en las 2 últimas pruebas, donde se ve que las velocidades medias son las esperadas, y en cambio los resultados son completamente inesperados (en la 1ª BarsWF es 11'2 veces más rápido encontrando la solución y en la 2ª Caín es 8 veces más lento). Esto ocurre por lo que llamaremos estrategia de pivotación, es decir, el orden a la hora de probar las posibilidades, que es determinístico, no aleatorio o pseudoaleatorio como sería otra opción: La forma intuitiva de probar posibilidades sería “pepe”, “pepf”, “pepg”, “peph”... En Caín es justamente al revés, “pepe”, “qepe”, “repe”, “sepe”... Y en BarsWF es algo especial, “aazysss”, “abzysss”, “aazyssz”, “aazza2a”, “bbzza2a”, “a2zza7a”, “a3zza7a”, es decir, 1º cambia la parte izquierda, después la derecha y por último la central, algo así como una mezcla de las 2 estrategias anteriores, tal y como se puede observar en las siguientes imágenes de muestra, tomados en instantes de tiempo consecutivos, como se puede comprobar tanto en la hora del S.O. como en el porcentaje de prueba con esa longitud de palabra del BarsWF (para mejores vistas, probar uno mismo): Esta estrategia de pivotación tan “rebuscada” no tiene en principio ventaja práctica a la hora de utilizar el algoritmo, pero en cambio se puede intuir que sí tiene ventaja heurística, pues en los passwords habituales los caracteres centrales no suelen ser escogidos para evitar este tipo de ataques, sí siendo habitual hacerlo con los caracteres extremos. Otra curiosidad es que en BarsWF en la parte de introducción del alfabeto es lo mismo meterle “­c 0a” que “­c a0”, así que se supone que hace un análisis exaustivo del parametro, probando como se ve en las pruebas primero los números y después las letras, parece ser que en orden ASCII. En Cain en cambio no es lo mismo el alfabeto abc..xyz01..89 que el 01..89ab..xyz, es decir, no lo ordena conforme a un método, sino que acepta el orden que le metes (para nuestras pruebas hemos utilizado el predefinido de [a­z0­9]+), así que con otro orden obviamente los resultados habrían cambiado. Algunas pruebas sobre otra máquina: Intel Core 2 Dúo P7350 2GHz 4 GB RAM, con gráfica Nvidia GeForce G 105M, de 8 unidades de procesamiento, con Windows 7 32 bits BarsWF_SSE2 32 bits Password : Hash md5 2010psi : 479b6ea311be3376929d5dd1f9f712df Tiempo CPU hh:mm:ss 00:01:10 00:01:11 Velocidad media (millones/segundo) 65'13 63'59 que como se puede observar comparando con la tabla inicial, ofrece una aceleración 4X. Algo por otra parte esperado, debido al uso de los 4 threads de esta máquina, así que otra ventaja clave es que ha paralelizado la ejecución del algoritmo, ventaja que junto el ya mencionado uso de registros vectoriales es casi definitiva. Algunas imágenes de muestra de otras pruebas son: Por último, se ha realizado una breve prueba para probar la versión CUDA, cuyas muestras son: donde se puede observar que el uso de GPUs + CPUs produce lo que sí es hoy por hoy la ventaja definitiva, recordándo que la GPU de las pruebas dista en mucho de las actuales comerciales, que son usadas para ataques de este tipo, con más de 100 unidades de procesamiento. Como sugerencia, dejo a gusto del lector el hacer sus propias pruebas, con éstas y otras muchas herramientas como algunas mencionadas al comienzo, e intentar sacar sus propias conclusiones y ver cuál le va mejor.