Nebula covers a variety of simple and intermediate challenges that cover Linux privilege escalation, common scripting
language issues, and file system race conditions.Nebula is an ideal place to get started for people new to Linux
exploitation.Hints will be provided in this walkthrough to give a chance for your wheels to spin.
Try your best to solve each level on your own before looking at the solution. Goodluck!!!
Username : level01
Password : level01
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.
Files for this level can be found in /home/flag00.
You are looking for commands that can search for files based on its permissions and user.
Use the find command.
We can use the find command to search for this file.
find / -perm -u=s -user "flag00" 2> /dev/null
/bin/.../flag00
Username : level01
Password : level01
There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?
Files for this level can be found in /home/flag01.
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid();
setresgid(gid, gid, gid);
setresuid(uid, uid, uid);
system("/usr/bin/env echo and now what?");
}
char *buffer;
The group id , user id of the current user is copied into the gid and uid using the getegid() and geteuid() functions. (Get Effective group id and Get Effective User id functions)
gid = getegid();
uid = geteuid();gid = getegid();
Then the setresgid, setresuid functions are used to set gid and uid of the current user. setresgid - set real, effective and saved user or group ID setresuid - set real, effective and saved user or user ID
uid = geteuid();system("/usr/bin/env echo and now what?");
Echo command is used to print "and now what?"
We here can make use of shell functions.
Find out how to export shell funtions. Which command here can be changed into a shell function that is called by the program itself ?
You may need to use bash to solve this level.
Create a shell function called /usr/bin/env(). Use the function to run the getflag command.
We can either change the environment variables or use shell funtions for this level. We will be using shell functions.
Create the function using
function /usr/bin/env() { getflag; }
Now we will have to export the function and execute the program usingexport -f /usr/bin/env
./flag01
Username : level02
Password : level02
There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?
Files for this level can be found in /home/flag02.
#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);
}
char *buffer;
A character pointer is declared. (Can be used to store strings.) The group id , user id of the current user is copied into the gid and uid using the getegid() and geteuid() functions. (Get Effective group id and Get Effective User id functions)
gid = getegid();
uid = geteuid();setresgid(gid, gid, gid);
Then the setresgid, setresuid functions are used to set gid and uid of the current user. setresgid - set real, effective and saved user or group ID setresuid - set real, effective and saved user or user ID
setresuid(uid, uid, uid);buffer = NULL; asprintf(&buffer, "/bin/echo %s is cool", getenv("USER")); printf("about to call system(\"%s\")\n", buffer);
The character string is set to null and the string "USER is cool" is copied into the "buffer" string which is print out in the next command using the printf() function. Where "USER" is substituted by the environment variable USER. To see the USER environment variable, just runenv | grep USER
Then, the system() function is used to execute the "buffer" string.system(buffer);
i.e In this case it will execute "echo level02 is cool".![]()
Manipulate an environment variable
The program is executing a line of command for us. Think what all to add to the environment variable so that we can execute what we want.
Change the environment varibale to include multiple commands.
We will be changing the environment variable USER which is used by the program .
Multiple commands can be executed in one line using " ; ".
Change the USER environment variable and execute the program by :
USER=hello\;getflag\;echo
echo hello ;getflag ;echo is cool
Username : level03
Password : level03
Check the home directory of flag03 and take note of the files there. There is a crontab that is called every couple of minutes.
Files for this level can be found in /home/flag03.
The writable.sh is executed every couple of minutes.
writable.sh
Every file in /home/flag03/writable.d, is executed and then removed.
ulimit -t : ulimit limits the resource usage of a process. The -t 5 sets the time limit to 5 seconds.
bash -x: Prints the command before executing it. This mode is very useful when debuggging code.
You just need to add a file to the writable.d folder
You need to add a file into writable.d directory that executes the getflag for us. And as proof that it was executed, redirect the output into the out.txt file in the parent directory.
A file called code.sh is created and "getflag > out.txt" is written into it.
When executed, the the ouput of the getflag is redirected to out.txt
Username : level04
Password : level04
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 :)
Files for this level can be found in /home/flag04.
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
int main(int argc, char **argv, char **envp)
{
char buf[1024];
int fd, rc;
if(argc == 1) {
printf("%s [file to read]\n", argv[0]);
exit(EXIT_FAILURE);
}
if(strstr(argv[1], "token") != NULL) {
printf("You may not access '%s'\n", argv[1]);
exit(EXIT_FAILURE);
}
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);
}
if(argc == 1) { printf("%s [file to read]\n", argv[0]); exit(EXIT_FAILURE); }
Argc is the number of command line arguments used while executing the program including the name of the c program . So if there are no command line arguments, argc = 1.
The above condition checks whether there were any command line arguments while executing the program and if there are none, prints the correct way to use this executable.
if(strstr(argv[1], "token") != NULL) { printf("You may not access '%s'\n", argv[1]); exit(EXIT_FAILURE); }
argv is the list of command line arguments including the name of the program where argv[0] is the name of the program and the rest are the command line arguments.
Strstr() function checks for the occurance of a string within another string.
If the command line argument specified (which is the file to be read according to this program) contains the string "token" in it, it denies access to the file as shown above.
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); }
The file specified is opened and any error in opening or reading the file is checked for and results in program temination.
write(1, buf, rc);
If no error are encountered, the file read is printed.
Think of other ways to point to a file. You know about it if you know linux basics.
We will be using links to refer to the token file.
To execute getflag, we need to switch to the flag04 account. So we can switch to flag04 using the content of the token file as password and execute getflag.
Username : level05
Password : level05
Check the flag05 home directory. You are looking for weak directory permissions. To do this level, log in as the level05 account with the password level05. Files for this level can be found in /home/flag05.
Use the ssh key to login to the appropriate account.
Use the ssh -i command.
Extract the file found in the .backup file using the tar command.
-C option of the tar command lets you extract the file to a specific directory.
The ssh key (id_rsa) can be used to login to the flag05 account after which the getflag command can be executed.
I couldn't ssh to flag05 account so i had to use another machine to ssh into the account.
Username : level06
Password : level06
The flag06 account credentials came from a legacy unix system. To do this level, log in as the level06 account with the password level06. Files for this level can be found in /home/flag06.
Traditionally, the /etc/passwd file is used to keep track of every registered user that has access to a system. The passwd file contains the information of every users including the username,encrypted password, user id, group id etc. But the passwd file is readable by everyone which means the encrypted password was up for grabs making it an easy attack vector.
Crack the password. You can use johnny the ripper.
Since the credentials are from legacy unix system, the /etc/passwd contains the encrypted password of the flga06 user. So we copy the password of the flag06 user and store it in pass.tx using grep and tee commands.
tee command splits the output into two and reditects one into the file pass.txt and the other to stdout.
The tee command is not at all a necessity, I just used it to show you its usage.
Then, we use john (johnny the ripper) to crack the password.
Just to be clear, the password is "hello". The password is used to login to flag06 and execute the getflag.
Username : level07
Password : level07
The flag07 user was writing their very first perl program that allowed them to ping hosts to see if they were reachable from the web server. To do this level, log in as the level07 account with the password level06. Files for this level can be found in /home/flag07.
#!/usr/bin/perl
use CGI qw{param};
print "Content-type: text/html\n\n";
sub ping {
$host = $_[0];
print("<html><head><title>Ping results</title></head><body><pre>");
@output = `ping -c 3 $host 2>&1`;
foreach $line (@output) { print "$line"; }
print("</pre></body></html>");
}
# check if Host set. if not, display normal page, etc
ping(param("Host"));
This program takes the first argument it receives, pings it and prints the output. From the config file thttpd.conf, we can find out the port number used by the scipt. We can see the output by visiting the page using curl .
curl http://<ip addr of machine>:7000/index.cgi?Host=127.0.0.1
In the program the value of Host is passed on to the ping funciton. Here the passed value is stored into a 'host' variable ($_[0] means the first argument passed into the function).
That value is later used in the ping command to ping the specified host and the output is printed out.
Reading this may help you: How can i call shell command in my perl scirpt
If executing system commands from a program doesnt ring any bells i dont know what does. You can manipulate the input to chain commands.
You may need to use URL encoding.
The command we can try to execute is
ping -c 3 127.0.0.1;getflag
I first tied to use the query string (the whole request is in quotes or else our system splits the command into two)
?Host=127.0.0.1;getflagSo i url encoded ';' which is %3B.
curl http://<ip addr of machine>:7000/index.cgi?Host=127.0.0.1%3Bgetflag
Username : level08
Password : level08
World readable files strike again. Check what that user was up to, and use it to log into flag08 account.To do this level, log in as the level08 account with the password level08. Files for this level can be found in /home/flag08.
There is a .pcap file in the home dir of flag08. We can use wireshark to open the file and read it.
level08@nebula:~$ cd /home/flag08 level08@nebula:/home/flag08$ ls capture.pcap
We can copy this file to our machine using scp (secure copy). Just like cp command, the scp requires a souce and destinaiton
scp level08@192.168.196.149:/home/flag08/capture.pcap .
Use wireshark to analyse the file
wireshark capture.pcap
We can see that a login was attempted and we even have the credentials. Right click on a packet and select TCP Stream in the Follow option.We can see the username and password. But, there is a catch.
The non printable characters are represented with '.'. Find out what they actually represent. You may want to see the data as hex instead of ascii.
The non printable characters were hex values '7f' and '0d'. 7f represents backspace and 0d represents Carriage Return. So the password is not backdoor...00Rm8.ate but insteas is 'backd00Rmate'.
You can now switch user to flag08 and execute the getflag.