Analizando un leak de contraseñas con Pipal

Hace unas semanas se publicó un ‘leak’, otro más, con multitud de contraseñas aparentemente asociadas a un servicio web conocido. Ya nos estamos acostumbrando a este tipo de noticias, y esta vez se ha apuntado con el dedo a la todopoderosa Google como fuente de esta publicación, con nada menos que alrededor de 5 millones de usuarios comprometidos.

Desde Google indican que no se trata de un ataque dirigido ni un compromiso de ninguno de los servidores de la empresa, sino que apuntan a que se puede tratar de una recopilación elaborada con mucha paciencia, y que menos de un 2% de las combinaciones de usuario y contraseña podrían haber funcionado. A pesar de ello nunca está de más echar un pequeño vistazo a las credenciales publicadas y, además de comprobar si nosotros o amigos y familiares están comprometidos, poder realizar un pequeño análisis y comprobar el estado de la concienciación en materia de seguridad de las contraseñas.

Para la primera tarea nos ponemos a buscar por el documento de texto y nos quedamos tranquilos tras comprobar que ni nosotros ni ningún conocido aparecen en esta publicación. Si no has podido obtener este ‘leak’ puedes acceder al proyecto Have I been pwned? del investigador de seguridad Troy Hunt, que recopila cuentas de correo comprometidas en este y otros ‘leaks’ importantes, y comprobar tus cuentas de correo.

Para la segunda tarea, vamos a emplear una utilidad que realiza el análisis de forma automática. La utilidad se llama Pipal y ha sido creada por Robin Wood (@digininja) precisamente para esta tarea: analizar los listados de contraseñas obtenidos, en su caso tras realizar las auditorías de seguridad que Robin lleva a cabo durante su trabajo habitual. Como el propio Robin indica “Antes de continuar debo resaltar que lo único que hace esta aplicación es proporcionar las estadísticas e información necesaria para ayudarte a analizar las contraseñas. El verdadero trabajo lo debes realizar tú interpretando los resultados. Yo te doy los números, tú cuentas la historia”.

Veamos como funciona la aplicación y los resultados que nos puede mostrar. Pipal se puede descargar desde github, y es una aplicación en Ruby autocontenida que podemos ejecutar en cualquier instalación estándar de Ruby, sin ningún otro requisito adicional.

$ ./pipal/pipal.rb -?
pipal 3.1 Robin Wood (robin@digi.ninja) (http://digi.ninja)

Usage: pipal [OPTION] ... FILENAME
     --help, -h, -?: show help
     --top, -t X: show the top X results (default 10)
     --output, -o : output to file
     --gkey : to allow zip code lookups (optional)
     --list-checkers: Show the available checkers and which are enabled
     --verbose, -v: Verbose

     FILENAME: The file to count

El listado contiene direcciones de correo electrónico. Necesitamos convertir el fichero a UTF8 para que pueda ser procesado correctamente, así que ejecutamos las siguientes órdenes para dejarlo preparado:

cat google_5000000_passwords.txt | awk -F":" '{print $2}' > pass.txt

iconv -f 437 -t utf8 pass.txt > pass-utf8.txt

Tras esto, pasamos ya a ejecutar la aplicación con el fichero de contraseñas obtenido:

./pipal/pipal.rb pass-utf8.txt -o salida.txt -v

Empezamos a ver en la consola como la aplicación se pone a realizar su trabajo. Tras unos minutos (u horas, según el equipo utilizado), obtenemos los resultados, que pasamos a analizar.

En primer lugar obtenemos los resultados generales, donde podemos ver las contraseñas más utilizadas, y aquellas “base words” (palabras que forman parte de la contraseña) que aparecen con mayor frecuencia:

Basic Results

Total entries = 4926343
Total unique entries = 3120179

Top 10 passwords
123456 = 48003 (0.97%)
password = 11593 (0.24%)
123456789 = 11162 (0.23%)
12345 = 8119 (0.16%)
qwerty = 5925 (0.12%)
12345678 = 5253 (0.11%)
111111 = 3524 (0.07%)
abc123 = 3016 (0.06%)
123123 = 2990 (0.06%)
1234567 = 2915 (0.06%)

Top 10 base words
password = 17596 (0.36%)
qwerty = 11061 (0.22%)
love = 3424 (0.07%)
monkey = 3213 (0.07%)
dragon = 3043 (0.06%)
hello = 2804 (0.06%)
iloveyou = 2778 (0.06%)
abcd = 2264 (0.05%)
welcome = 2241 (0.05%)
july = 2225 (0.05%)

Aquí podemos ver cómo, a pesar de los múltiples esfuerzos de la comunidad en este aspecto, las contraseñas más utilizadas siguen siendo o siguen teniendo palabras o secuencias de caracteres que consideramos inseguras.

Los conjuntos de dígitos o las sucesiones de caracteres tal y como se encuentran en el teclado, así como palabras comunes, entre las que destaca la propia palabra “password” (contraseña en inglés) copan los primeros lugares.

A continuación aparecen dos listas donde se muestra la longitud de las contraseñas, ordenadas por número de caracteres y por frecuencia de aparición, respectivamente, junto con un pequeño gráfico en ASCII que muestra la distribución de las mismas:

Password length			Password length
(length ordered)		(count ordered)
1 = 853 (0.02%)			8 = 1424125 (28.91%)
2 = 1565 (0.03%)		6 = 926282 (18.8%)
3 = 12721 (0.26%)		10 = 682219 (13.85%)
4 = 45572 (0.93%)		9 = 681330 (13.83%)
5 = 143317 (2.91%)		7 = 663424 (13.47%)
6 = 926282 (18.8%)		11 = 151685 (3.08%)
7 = 663424 (13.47%)		5 = 143317 (2.91%)
8 = 1424125 (28.91%)	        12 = 93010 (1.89%)
9 = 681330 (13.83%)		4 = 45572 (0.93%)
10 = 682219 (13.85%)	        13 = 42293 (0.86%)
11 = 151685 (3.08%)		14 = 24787 (0.5%)
12 = 93010 (1.89%)		15 = 14812 (0.3%)
13 = 42293 (0.86%)		3 = 12721 (0.26%)
14 = 24787 (0.5%)		16 = 7277 (0.15%)
15 = 14812 (0.3%)		17 = 2548 (0.05%)
16 = 7277 (0.15%)		32 = 2512 (0.05%)
17 = 2548 (0.05%)		18 = 1780 (0.04%)
18 = 1780 (0.04%)		2 = 1565 (0.03%)
19 = 1079 (0.02%)		20 = 1169 (0.02%)
20 = 1169 (0.02%)		19 = 1079 (0.02%)
21 = 451 (0.01%)		1 = 853 (0.02%)
22 = 387 (0.01%)		21 = 451 (0.01%)
23 = 288 (0.01%)		22 = 387 (0.01%)
24 = 257 (0.01%)		23 = 288 (0.01%)
25 = 172 (0.0%)			24 = 257 (0.01%)
26 = 118 (0.0%)			25 = 172 (0.0%)
27 = 71 (0.0%)			26 = 118 (0.0%)
28 = 51 (0.0%)			27 = 71 (0.0%)
29 = 31 (0.0%)			28 = 51 (0.0%)
30 = 41 (0.0%)			30 = 41 (0.0%)
31 = 12 (0.0%)			40 = 33 (0.0%)
32 = 2512 (0.05%)		29 = 31 (0.0%)
33 = 6 (0.0%)			31 = 12 (0.0%)
34 = 7 (0.0%)			35 = 11 (0.0%)
35 = 11 (0.0%)			34 = 7 (0.0%)
36 = 4 (0.0%)			33 = 6 (0.0%)
37 = 6 (0.0%)			37 = 6 (0.0%)
38 = 3 (0.0%)			50 = 5 (0.0%)
39 = 1 (0.0%)			36 = 4 (0.0%)
40 = 33 (0.0%)			53 = 4 (0.0%)
41 = 3 (0.0%)			122 = 3 (0.0%)
42 = 2 (0.0%)			41 = 3 (0.0%)
44 = 2 (0.0%)			45 = 3 (0.0%)
45 = 3 (0.0%)			38 = 3 (0.0%)
50 = 5 (0.0%)			44 = 2 (0.0%)
53 = 4 (0.0%)			42 = 2 (0.0%)
54 = 2 (0.0%)			56 = 2 (0.0%)
56 = 2 (0.0%)			64 = 2 (0.0%)
64 = 2 (0.0%)			54 = 2 (0.0%)
65 = 1 (0.0%)			65 = 1 (0.0%)
67 = 1 (0.0%)			67 = 1 (0.0%)
85 = 1 (0.0%)			85 = 1 (0.0%)
91 = 1 (0.0%)			91 = 1 (0.0%)
122 = 3 (0.0%)			39 = 1 (0.0%)
136 = 1 (0.0%)			136 = 1 (0.0%)
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
   ||||                                                                 
   ||||                                                                 
   ||||                                                                 
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
000000000011111111112222222222333333333344444444445555555555666666666677
012345678901234567890123456789012345678901234567890123456789012345678901

Podemos ver como las contraseñas de 8 caracteres son las que más aparecen, y el rango entre 6 y 10 caracteres es en el que se encuentran la mayoría de las contraseñas.

Teniendo en cuenta un equipo potente que utilice la herramienta oclhashcat (del que ya hemos hablado anteriormente en este blog), que las contraseñas únicamente contienen minúsculas y caracteres alfanuméricos, y suponiendo que se obtienen las contraseñas en MD5 (lo que es bastante común), se podría recorrer todo el espacio de contraseñas de 10 caracteres en algo menos de un día, así que, aunque a priori 10 caracteres pueda parecer muy seguro, vemos que no es así.

También cabe destacar la aparición de más de 2500 contraseñas de longitud 32, cuando únicamente aparecen pocas decenas de casos de contraseñas con longitudes vecinas. Revisando las contraseñas vemos que parecen ser hashes MD5, lo que puede significar 2 cosas: o bien no han sido descifradas o bien alguien ha introducido la suma MD5 de algún fichero como contraseña (veo que no soy el único que lo ha hecho alguna vez).

A continuación, aparecen varias estadísticas interesantes relacionadas con la longitud de la contraseña y el conjunto de caracteres utilizado:

One to six characters = 1130310 (22.94%)
One to eight characters = 3217859 (65.32'%)
More than eight characters = 1708484 (34.68%)

Only lowercase alpha = 1972788 (40.05%)
Only uppercase alpha = 0 (0.0%)
Only alpha = 1972788 (40.05%)
Only numeric = 775445 (15.74%)

First capital last symbol = 0 (0.0%)
First capital last number = 0 (0.0%)

Vemos que más del 65% de las contraseñas son de 8 o menos caracteres, alrededor del 40% están formadas únicamente por letras en minúscula, y más de un 15% sólo contienen dígitos. Todas estas prácticas rebajan la seguridad de las contraseñas y deberíamos tratar de evitarlas.

También vemos que no aparecen contraseñas que contengan únicamente mayúsculas o que empiecen con mayúsculas, lo que nos puede hacer sospechar de que realmente no existe ninguna contraseña que utilice mayúsculas, como veremos más adelante.

Acto seguido se muestran estadísticas de las contraseñas con números en su parte final.

Single digit on the end = 396589 (8.05%)
Two digits on the end = 561345 (11.39%)
Three digits on the end = 307392 (6.24%)

Last number
0 = 225978 (4.59%)
1 = 446157 (9.06%)
2 = 249229 (5.06%)
3 = 322395 (6.54%)
4 = 199645 (4.05%)
5 = 198905 (4.04%)
6 = 236076 (4.79%)
7 = 204986 (4.16%)
8 = 190806 (3.87%)
9 = 215301 (4.37%)

 |                                                                      
 |                                                                      
 |                                                                      
 |                                                                      
 | |                                                                    
 | |                                                                    
 | |                                                                    
||||  |                                                                 
|||||||| |                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
0123456789

Last digit
1 = 446157 (9.06%)
3 = 322395 (6.54%)
2 = 249229 (5.06%)
6 = 236076 (4.79%)
0 = 225978 (4.59%)
9 = 215301 (4.37%)
7 = 204986 (4.16%)
4 = 199645 (4.05%)
5 = 198905 (4.04%)
8 = 190806 (3.87%)

Last 2 digits (Top 10)
23 = 139781 (2.84%)
56 = 71742 (1.46%)
12 = 61841 (1.26%)
11 = 59786 (1.21%)
00 = 50068 (1.02%)
01 = 49657 (1.01%)
10 = 41260 (0.84%)
21 = 40985 (0.83%)
34 = 37776 (0.77%)
89 = 37686 (0.76%)

Last 3 digits (Top 10)
123 = 113837 (2.31%)
456 = 60162 (1.22%)
234 = 27651 (0.56%)
345 = 18836 (0.38%)
789 = 16930 (0.34%)
000 = 16916 (0.34%)
007 = 14584 (0.3%)
321 = 13666 (0.28%)
111 = 13478 (0.27%)
010 = 11371 (0.23%)

Last 4 digits (Top 10)
3456 = 55734 (1.13%)
1234 = 25782 (0.52%)
2345 = 17379 (0.35%)
6789 = 13343 (0.27%)
2010 = 8404 (0.17%)
1111 = 7681 (0.16%)
2009 = 7672 (0.16%)
2008 = 6442 (0.13%)
5678 = 6438 (0.13%)
1987 = 6207 (0.13%)

Last 5 digits (Top 10)
23456 = 55364 (1.12%)
12345 = 17006 (0.35%)
56789 = 12977 (0.26%)
45678 = 6056 (0.12%)
11111 = 5821 (0.12%)
54321 = 4407 (0.09%)
34567 = 4166 (0.08%)
23123 = 4064 (0.08%)
00000 = 3499 (0.07%)
67890 = 3089 (0.06%)

Muchos usuarios simplemente añaden algunos dígitos a “su contraseña” si se les obliga a utilizar números. Aquí vemos como muchos usuarios añaden un sólo dígito (siendo el más común el 1), o 2 o más dígitos, ya sea repetidos o formando series. Mención especial al apartado de 4 dígitos, donde podemos ver como aparecen varios números que podríamos identificar con años (2010, 2009, 2008, 1987).

Finalmente, aparecen estadísticas sobre el conjunto de caracteres utilizado y cómo se ordenan los caracteres dentro de la contraseña:

Character sets
loweralphanum: 2096099 (42.55%)
loweralpha: 1972788 (40.05%)
numeric: 775444 (15.74%)
loweralphaspecialnum: 39336 (0.8%)
loweralphaspecial: 25376 (0.52%)
specialnum: 4200 (0.09%)
special: 582 (0.01%)

Character set ordering
allstring: 1972788 (40.05%)
stringdigit: 1544506 (31.35%)
alldigit: 775444 (15.74%)
othermask: 233532 (4.74%)
stringdigitstring: 174893 (3.55%)
digitstring: 144649 (2.94%)
digitstringdigit: 42337 (0.86%)
stringspecialdigit: 15959 (0.32%)
stringspecialstring: 13657 (0.28%)
stringspecial: 4875 (0.1%)
specialstring: 2083 (0.04%)
specialstringspecial: 873 (0.02%)
allspecial: 582 (0.01%)

La tabla de conjuntos de caracteres nos muestra que no hay ninguna letra mayúscula en ninguna de las contraseñas que hemos obtenido, algo que ya habíamos intuido anteriormente. La tabla de ordenación, por su parte, nos muestra que más del 70% de las contraseñas están formadas únicamente por una cadena de texto o una cadena con un número detrás. Si añadimos a esto las contraseñas formadas únicamente por números, estamos hablando de alrededor del 87% de las contraseñas encontradas.

Por si este análisis no os parece suficiente, Pipal tiene dos funcionalidades de análisis más: los Splitters y los Checkers. Ambos son pequeños módulos que otorgan más funcionalidad a la aplicación.

En el caso de los Splitters, éstos dividen cada una de las líneas del fichero de entrada en campos, de forma que si tenemos por ejemplo nombre de usuario y contraseña, podemos indicarlo a la aplicación y puede ser de utilidad en fases posteriores de análisis.

Los Checkers en cambio realizan comprobaciones adicionales sobre el conjunto de contraseñas sirviendo, por ejemplo, para identificar campos de fecha (días, meses, años), como los grupos de 4 dígitos que forman años que hemos visto anteriormente. También hay otros para comprobar colores, estaciones del año, codigos postales, nombres de usuario, etcétera.

Se pueden listar los checkers disponibles con el modificador --list-checkers, y se habilitan al estilo módulos de apache2, creando un enlace simbólico desde la carpeta checkers-available a la carpeta checkers-enabled.

El único problema de los checkers es que la distribución oficial no tiene ninguno localizado en español. Para solucionar este problema David Lladró (@davidlladro), amigo y antiguo compañero, ha creado una versión de Pipal en la que sí aparecen varios checkers localizados en español.

Con esto concluye el análisis de esta herramienta y el último “leak” de contraseñas publicado. Espero que os haya gustado y vuestros comentarios sobre esta estupenda herramienta.