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.

2 comentarios :

Anónimo dijo...

Hola, de casualidad sabe alguien como solucionar este problema que me aparece en SSLstrip

ImportError: No module named StrippingProxy


Gracias de antemano

Jose Selvi dijo...

Hola @Anónimo, StrippingProxy es uno de los módulos propios que tiene SSLSTRIP, se encuentra dentro del directorio sslstrip-0.x/sslstrip.

Si te da ese error probablemente es porque has sacado sslstrip.py de su directorio original y por eso ahora no encuentra las librerías, o quizá porque lo estás llamando con su path absoluto desde otro lado.

Si lo haces así tendrás que añadir el contenido de sslstrip-0.x/sslstrip al directorio de sistema donde se encuentran las librerías de python.

Suerte con el problemas, y gracias por tu comentario ;)