Exploit.education - Nebula

Exploit.education is an awesome CTF type of challenges which are fun and interesting to solve. Nebula is the first machine which mostly deals with privilege escalation and exploiting common misconfigurations on *unix.

I will keep updating this post.


This level requires you to find a Set User ID program that will run as the “flag00” account. You could also find this by carefully looking in top level directories in / for suspicious looking directories.

find / -user flag00 -perm /u+s 2>/dev/null



There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?

a bit trickier for me.
first, we check the flag01 binary in flag01 directory.

image.png alright, it has SUID just like the last one. now, if we look at source code, one particular line is interesting:

system("/usr/bin/env echo and now what?");

/usr/bin/env is called as absolute path while echo is called without whole path. so how will the system know where is echo ?
by looking at the PATH variable. what does it look like right now?

image.png and where is echo ?

Screenshot from 2024-05-01 15-39-30.png so, the system will look at the PATH variable and figure out where is echo. what if we change the echo to be a different binary, like the getflag binary? and then when we run flag01, we get this kind of flow:

system("/usr/bin/env /bin/getflag and now what?");

so, our current user is level01 but when we run this, the /bin/getflag will run as flag01 user (because of SUID)!

cd /home/level01
echo "/bin/getflag" > echo
chmod +x echo

Screenshot from 2024-05-01 15-52-07.png


There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?

this one was quite easy

image.png same as the last one, it has SUID as flag02 . so, we have some interesting C code below:

asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
printf("about to call system(\"%s\")\n", buffer);


let’s execute it


it echos whatever is set to the USER environment variable. by changing it to getflag and also doing some command injection, we can easily pass this level

export USER="&& getflag"


we used && to run another command along with echo.


Check the home directory of flag03 and take note of the files there. There is a crontab that is called every couple of minutes.

same as last one, difficulty is easy
we’ve got two files here:


writable.d and writable.sh
looking at contents of writable.sh :


for i in /home/flag03/writable.d/* ; do
	(ulimit -t 5; bash -x "$i")
	rm -f "$i"

it’s running everything inside the writable.d directory. the script is running as cronjob which is described at the challenge page

There is a crontab that is called every couple of minutes.

make a script inside the directory and call getflag. this is way too easy

getflag > /home/flag03/flag

wait for a few minutes and then you will get flag file.



This level requires you to read the token file, but the code restricts the files that can be read. Find a way to bypass it :)

we have to open a token file using flag04 . it has the password for flag04 user.

  if(argc == 1) {
      printf("%s [file to read]\n", argv[0]);

  if(strstr(argv[1], "token") != NULL) {
      printf("You may not access '%s'\n", argv[1]);

  fd = open(argv[1], O_RDONLY);
  if(fd == -1) {
      err(EXIT_FAILURE, "Unable to open %s", argv[1]);

  rc = read(fd, buf, sizeof(buf));

  if(rc == -1) {
      err(EXIT_FAILURE, "Unable to read fd %d", fd);

  write(1, buf, rc);

there is strstr comparision for the second argument. it checks for token string and denies if it finds it.
we have to change file name, but how? we can’t copy or move it because of no permissions.
instead, we can create a symlink to it and rename it to something else (provide full path or else symlink will be broken)

ln -s /home/flag04/token /home/level04/tk



this one was fun

Check the flag05 home directory. You are looking for weak directory permissions


.ssh looks interesting. can we go there?


nope. another interesting directory is backup . what’s in there?

sh-4.2$ ls .backup/

let’s untar it to /tmp (because remember, /tmp can be accessed by any user). create a directory backup.

mkdir /tmp/backup
tar -xvf backup-19072011.tgz -C /tmp/backup


this has to be the ssh key for flag05 user! let’s use it (replace IP with your server IP)

ssh -i /tmp/backup/.ssh/id_rsa



easy difficulty.

The flag06 account credentials came from a legacy unix system.

what comes to mind when we talk about unix or linux password management?

fortunately, we do have read access to the file.

Screenshot from 2024-05-02 15-01-40.png

we’ve got a hashed password. it’s a DES-based crypt hash. we can crack it with john the ripper although I should warn you, the password is very easy to guess

create a file with this format username:hash and save it. we will use rockyou wordlist

john --worldlist=/usr/share/wordlists/rockyou.txt file_name


now login in to flag06 and complete the challenge



World readable files strike again. Check what that user was up to

we have a pcap file, which we can analyze with wireshark.
scrolling through the packets, we find this one:


backdoor…00Rm8.ate doesn’t seem like the correct password. this is in the ASCII format. the dots could have some different meaning which we are not able to see.
changing the format to hex dump in wireshark


the three dots and the one after that are 7f in hex. the last one is 0d . if we look up at an ASCII table, we can figure out what it stands for
Screenshot from 2024-05-06 18-16-30.png


There’s a C setuid wrapper for some vulnerable PHP code.

this is rather very short and quite easy for anyone who has worked with 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;


this php file is provided for the challenge and a flag09 binary and has SUID bit set


we get some weird error, but notice how it’s displaying an error just like the php cli. running -h confirms the suspicion:


we can run the -a and get an interactive console, which can execute shell commands. voila!



The setuid binary at /home/flag10/flag10 binary will upload any file given, as long as it meets the requirements of the access() system call.

easy difficulty.
there’s some C which is used to send a file to remote host. one part which is helpful is this one:

printf("Connecting to %s:18211 .. ", host); fflush(stdout);
fd = socket(AF_INET, SOCK_STREAM, 0);
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(host);
sin.sin_port = htons(18211);

it connects to port 18211 of the remote host, so we just have to open that port and send the token file which is in /home/flag10 .
use netcat for opening the port and receive any file:

nc -lvnp 18211


one weird thing I found was that the password was already there in /home/level10