After some fails, I figured that the ISO given was for Mac OSX 64 bit and I launched to the following interface after booting.
I created an SSH tunnel and is able to connect through my local machine. I ran the getflag command expecting to get the flag, but looks like the challenge starts for 00 already
I ran a strings command on the getflags binary and here is what I get. I dont think this is anything useful.
Ran an strace on the program with no args, still didnt find anything good.
Sudoing wont work either
Looks like the subject states that I need to run the program as flagXX user, which indicates that this might be a privellege escalation problem.
I checked /etc/passwd
for any clues and I see this strange thing on the next user, ill keep note. But others than that, all the passwords seem protected
I tried running a sudo -l
to list all the programs I can run, but looks like I got no luck
In that case, I guess I can find all the files created by me to acheive the same thing using find / -user level00
Thats alot of files, Ill filter out the error texts by redirecting stderr to /dev/null find / -user level00 2>/dev/null
This is what I got. Doesnt seem to have nothing special here, just process files and system files. I will do the same thing for the flag00
user..
… and there are 2 files which can be read by us, intresting.
They are both ASCII files, could they contain the password?
Looks like we might have our password, lets try to login to flag00
Nope, its incorrect. Looks like this is an encrypted password. I went on https://www.dcode.fr/caesar-cipher to hopefully find a decryption and luckily, I managed to extract the plaintext from the caesar cipher
nottoohardhere
is the password. I tried it and I'm in, launched getflag and I got my password x24ti5gi3x0ol2eh4esiuxias
I noticed the weird thing on /etc/passwd
for this user during the last level, and Ill try to login with the weird string 42hDRfypTqqnw
for this one.
Nope, does not work. Ill need to do more research on what this is.
Upon googleing, the string included in /etc/passwd is the encrypted user password, and usually is stored in a more secure form in /etc/shadow following this format:
So our next step is to attempt to decrypt the password using one of the following formats.
It is not MD5 since the password is not 32 Characters long.
I dont think its blowfish because we need to get a seperate key for that (could be the username). It is not the SHA algorithms either because the length of the password does not meet the encryption results. So we are left with yescrypt
I did some google and there are people trying to crack yescrypt with john the ripper, so I gave it a go and installed it
I ran the program and got the plaintext password
The password turns out to be correct, and the flag is obtained f2av5il02puano7naaf6adaaf
Upon logging in, I was greeted by a level02.pcap
in my home directory. Something tells be we need to use wireshark for this..
I loaded the file into wireshark and followed the TCP stream which constructs the TCP message based on the frames and got this.
I tried c/p the string inside the password prompt, but the login failed. Looks like the ...
characters might be something else, I displayed the characters in hex, and got this..
This is what the client typed, and turns out the 7F is a delete character in ASCII, which might indicate a backspace. So the password became from ft_wandr...NDRel.L0L
to ft_waNDReL0L
by replacing the .
with backspaces. I tried against the console and it works.
I got in and obtained the flag kooda2puivaav1idi4f57q8iq
I went in and got greeted by an executable
The strings output are shown as below
Here is the file type
Could /home/user/level03/level03.c
be a source code indicator?
Looks like the setuid and setgid bit is set, which means that we can execute this program as the user who created it, which is our flag03 user.
The possible way forward now is to make this program execute getflag
, so it can return us the flag as said user
To find a way to execute programs inside the executable, i used ltrace
to identify any system calls made by the program.
Looks like it calls system to execute shell command /usr/bin/env echo Exploit me
. Its quite weird that it calls to env
first then echo
So it sets the current environment variables before calling echo. If I change the PATH variable to look for my own directory first, then whatever program that has the name echo
will get executed. So thats what I did here.
and once this is done, I re-executed level03 and got the flag qi0maab88jeaj46qoumi7maus
For level04, I was greeted with a perl script with the following contents
Here is the file type
since the setuid and setgid bits are enabled, means this is another privellege escallation gig, I will need to execute getflag inside this script somehow to get the flag.
Upon doing some research on what the script does, I figured that this script is meant to be run as a back end CGI, where we need to spin up a webserver to accept requests.
The program defines a subroutine 'x' which takes a parameter which needs to be named 'x' and concats it to the echo call. Not much I can elaborate here since I am not good with perl. Need to trial and error this.
Luckily, the ISO already has Apache installed and it is already running on port 4747
I went port-forwarded the traffic and tried to adjust the x query parameter in my browser, and it does show me something as an output
Looks like the print command of the perl script will be run by the server since its surrounded in backticks. In bash, backticks are called command substitution in bash which spawn a subshell and captures the output of the command inside the backtick and returns it to the main shell
If this is the case, I should make the x parameter
To run the getflag program as flag04 user.
To do that, the following query is sent
And I got the following output, the flag is ne2searoevaevoem4ov4ar8ap
Upon reaching level05, there are no programs or files in the home directory, so I ran find / -user flag05 2> /dev/null
to look for any files flag05 owns
And turns out, we got our files
The file contents are as follows
Which scans the /opt/openarenaserver/
directory for files and executes everything that is executable inside with a time limit of 5 seconds for each process. The file is then deleted afterwards.
Gave it a sanity check and it works
I tried to run getflag with it, but I had no luck.
when I tried to ls -lah
the file, I noticed that there is something special in the permission bit:
the + bit at the end of the permission bits means that there are additional permissions set by Access Control Lists (ACL). To get information on those permissions, one can use getfacl command
Nothing useful here it seems, the only implication i get from doing this is that I cant write to that file.
I was curious and also ran getfacl on the /opt/openarenaserver directory, and got something intresting…
I tried changing the permissions of the directory, but it is not permitted
I also tried changing ownership of the script, but it was also not permitted
After a short break and I logged back in, I noticed that I have new mail
and upon reading it, I saw a crontab which runs the openarenaserver script every 2 minutes
This must be a clue, I made a script that echoes to a file and I waited for 2 minutes, eventually the script did get deleted and the contents did appear in the file I specified.
I replaced the contents of the script with getflag, and the file should have the programs output. And once the script runs and gets deleted, the output should have the flag viuaaale9huek52boumoomioc
Upon arriving at level06, I was greeted with 2 files, here are the enumeration results
We have a php script file that supposedly is running on a server, and we have a CGI program which has setuid bit set.
I executed both the script and the program and looks like they have the same output. Could the executable be a compiled version of the php script?
I took a look at the script file, and here is what the formatted version looks like
The script has a function called y
which accepts 1 parameter, where it replaces all the .
with x
and all the @
with y
from the input string and returns the replaced string.
The function x
however takes 2 inputs, but only the first one is used. the first input should be a path to a file and its contents will be read and stored at the variable a
It then finds the pattern [x (anything here)]
and runs y(anything here from earlier)
to get the result which is used as a replacement for the file contents. The reason y
gets executed is becase of the e(execution) flag after the regex. This tells the computer to excecute whatever is in the second parameter as PHP code.
The x
function then replaces braces with parenthesis.
The thing is, the way y
gets executed is by specifying a string in the second parameter. In Javascript, there is a way to inject varaibles straight into strings like so:
We can also run functions in it like so:
We can do the same in PHP like so
This feature is called variable interpolation. And instead of running php functions, php also allows us to run shell commands in variable interpolations using backticks. This feature is called Execution operator
So back to our function, we can use Execution operators and variable interpolation to execute commands in the y(anything here from earlier)
step; which we want to acheive
To do so, we need to change the [x (anything here)]
part so that the second capture group will batch whatever that we want the input to be on the y()
call.
Hence, our input should be
After getting our input, we obtained our flag wiok45aaoguiboiki2tuin6ub
I see a binary in the home folder, below are the enumeration results
I noticed that the program calls getenv on LOGNAME which returns level07
before echoing out the value. In bash, there are a way to execute commands inside the resolution of environment variables by using the same mechanism from level04
I tried doing the following but it looks like it didnt work
I realized something, the program also prints the string into the terminal. If I set the variable to
before the execution, the program will execute on the action of setting of the variable; which will print out the wrong output. However, if I set the variable to
The echo will print the literal with the backticks, which will get executed by the system
syscall which spawns a child shell instead. Take a look at the example.
With the above information, I am able to get the flag fiumuikeil55xe9cu4dood66h
I was greeted by 2 files, here are the enumeration results
Upon running the program with ltrace, here are the results
Im guessing it uses strstr
to check the name of the file if it contains the string token
and if it is, it will just print the error message. Other files are okay as seen below :
My intuition tells me to make a soft link to that file with a different name, and call the program with the soft link. It didnt work however
I also noticed that the program does not do any setuid calls before calling open.
After some searcing, I found out that for sticky world writable directories like /run/shm, symlinks can only be followed by who created it. So I made the symlink in some other location and it worked
The password to flag08
is quif5eloekouj29ke0vouxean
The flag of this level is 25749xKZ8L7DkSCwJkT9dyv6f
Here are the enumeration results
Upon running ltrace
on the executable, it looks like it detects the attempt and warns us to not reverse this using ptrace(PTRACE_TRACEME, 0, 0, 0)
.
So I just executed the executable arguments to test
On the surface, looks like the program iterates through the characters and does an ASCII rotation based on the current index of the iteration
I also saw a token file earlier, maybe if that file was encrypted with this mechanism, and I need to decrpypt the file in the same manner. I used od -t u1
to get the files bytes in decimal so I can construct an array and iterate through it applying the decryption in python. The script can be made like so
With the script created and ran, we are able to login to flag09 and get the flag s5cAJpM8ev6XHw998pRWG728z
Upon enumeration, looks like this has similar mechanism with the last level, with another layer of complexity
I wanted to get to know more about this mechanism so I opened another terminal to act as my server using nc -l 0.0.0.0 6969
In my original terminal, I sent a test file to 127.0.0.1
to see its behaviour
Original terminal:
Other terminal:
Looks like the file gets sent in plaintext, now I gotta find a way to access the file to get it sent through. The ltrace shows this line before the file gets read, so I went to see what it is about in the man page.
as it turns out, there is a warning about a security hole
Warning: Using these calls to check if a user is authorized to,
for example, open a file before actually doing so using open(2)
creates a security hole, because the user might exploit the short
time interval between checking and opening the file to manipulate
it. For this reason, the use of this system call should be
avoided. (In the example just described, a safer alternative
would be to temporarily switch the process's effective user ID to
the real ID and then call open(2).)
This means that we can change the file behaviour after access has been called, and before open has been called. We need to change the file in such a way that it passes the first access
call and opens the token
file on the open
call.
And since we couldnt do anything to stop or pause the execution externally, we will need to do the file operation alot of times in succession, hoping that the timing reaches our favour.
The operations which we will do to the file is to
Hopefully, when we continiously run the application in another thread, the access
will run before step 2, and open will run before step 4.
We made a script to do the linking operations
Also another script to run the program in a loop
The following link will start a local server that listens to a port and restarts everytime a connection closes nc -lk 0.0.0.0 6969
Do the following in order :
You should able to see the value of token sometimes in the server output.
The value of the token is woupa2yuojeeaaed06riuj63c
, which is the password for flag10. The getflag
output for that user is feulo4b72j7edeahuete3no7c
Here are the enumeration results
We are presented with a lua file, here is the code.
Looks like the code is already running in a server of port 5151 on localhost, and it reads data from the body, put it through the hash function and sends a respose.
However, looking at the code, we can deduce that there is no point trying to crack the encryption since we cant inject anything into the response. We can however, use command substitution and output the result in a file, and thats what we did
we got the flag in /dev/shm/flag
fa6v5ateaw21peobuub8ipe6s
Here are the enumeration results
We are presented with a perl file, here is the code.
Much like the last level, it seems like the code is already running in a server of port 4646 on localhost.
There are 2 query parameters, namely "x" and "y", which are passed to the function t. The function uses regex to convert alphabets to uppercase and keeps only the first word.
"x", now formatted, is used to egrep the file "/tmp/xd" and redirects stderr to stdout.
The rest of the code checks if the output matches the param "y" and prints 1 or 2 dots.
Our first instinct is to utilize command substitution, but putting the whole command wouldn't work, as the "x" parameter is trimmed to the first word.
To bypass that, we can run the entire command in a script that has a fully uppercase name, like "FLAGGETTER", and substitute that instead.
/dev/shm/FLAGGETTER
In order to run the script as a command, we have to add the directory that contains the script to the PATH env variable.
Now we can try to pass the command substitution to the server via curl.
curl "127.0.0.1:4646?x=\`flaggetter\`&y=y"
Hmm seems like the flag file wasn't created, what is the error here?
We were stuck here for quite a while, thinking there were problems elsewhere.
We continued to test and in the end, we realized that the updated PATH doesn't carry over to other users.
To resolve the issue, we can use absolute path to run the script.
curl "127.0.0.1:4646?x=\`/*/*/flaggetter\`&y=y"
There we go, the flag file is now created at /dev/shm/flag
and it contains the flag g1qKMiRpXf53AWhDaU7FEkczr
We are greeted by a setuid elf executable, and here are the enumeration results
The executable calls getuid to get the current user id which is the uid of level13
, and it checks the return value and compares it to 4242.
We couldnt really get more out of this by using tracing programs, so we went to try to modify the uid and made a C program that does so
However, our user is not root so this code will fail with error EPERM
. We also tried looking into exploits in the getuid()
function itself and couldnt find any.
Without any other choices, our only option left is to manipulate register values to bypass the check during the programs runtime using gdb.
We launched gdb with the program name gdb ./level13
and it brings us to the gdb shell. On another terminal, we run the command tty
to get the tty device, so that gdb can send the stdout to that device during debugging.
On the gdb shell, we first assign the output tty to the device we see just now by running tty /dev/pts{id}
.
Once its done, we will make a breakpoint at the getuid
function of the code because we want to make changes around that function by using b getuid
.
We then enable register and assembly view by doing layout asm
and layout reg
.
Once we see the layouts, we can type run
to start the debugging.
We will have to step-in until we see the return instruction to change the register values, we use the command stepi
Notice we are at the ret
instruction, which is the assembly instrction for return. It will read the value in eax
and return to the caller. It is at this point we want to change the value of eax
to 4242.
and to continue the program execution till the process ends, use continue
. In the other terminal, you should see the flag 2A31L79asukciNyi8uppkEuSx
This is a mystery, there are no files in the home directory and nothing created by flag14 user in the system that I can see
the output of top -U flag14
did not show any processes either
I think this means we gotta do everything ourselves now..
Since we used gdb in the last round to change the uid to 4242, maybe we can do the same to getflag
, we can change the uid to the uid of flag14, which is according to /etc/passwd
, 3014.
I set the breakpoint at getuid
, but looks like I got caught red handed
So what if i set the breakpoint at ptrace
? Will I be able to bypass this?
Turns out I can, I adjusted the return value to a sucess value in ptrace and I managed to get to getuid
. The rest is the same as the last level, and I managed to get the flag 7QiHafiNa3HVozsaXkawuYrTstxbpABHD8CPnHJ