Quick disclaimer: I fully understand that the code I am attempting to write is insecure, and allows for arbitrary users to escalate to root. I am writing a simple C program like this to demonstrate how privileged escalation works to those unfamiliar.

What I have right now is a simple C program:

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

int BUFFERSIZE = 512;

void main(int argc, char** argv) {
  char ipaddr[BUFFERSIZE];
  snprintf(ipaddr, BUFFERSIZE, "ping -c 4 %s", argv[1]);
  if(setuid(0) == -1) printf("setUID ERROR");

I compile this code as root and set the permissions as such:

-rwsr-xr-x 1 root root 16840 Oct 28 14:13 pingSys

As you can see, the setUID bit is flipped. So what should happen, is if I run the program like so:

./pingSys; /bin/sh

It should execute ping -c 4; /bin/sh as the root user and spawn a shell. But instead, I get this:

user@localhost:~/privEsc$ ./pingSys; /bin/sh
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from icmp_seq=2 ttl=64 time=0.089 ms
64 bytes from icmp_seq=3 ttl=64 time=0.118 ms
64 bytes from icmp_seq=4 ttl=64 time=0.089 ms

--- ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 59ms
rtt min/avg/max/mdev = 0.034/0.082/0.118/0.031 ms
$ whoami

What is going wrong here? I have the setUID bit flipped on the executable, and I even tried running the function setuid(0), which doesn't throw an error. I'm very confused as to why I can't spawn a shell as root because everywhere else I've looked this has worked.

Any ideas?

2 Answers 2

./pingSys; /bin/sh

The semicolon will be interpreted as a command delimiter by the current shell. This means it will first execute ./pingSys in the current shell and then /bin/sh in the current shell, i.e. spawning a new shell with the current (non-privileged) permissions.

What you instead need to do is to put quotes around your argument so that it gets passed in full to your pingSys program instead of getting interpreted by the current shell:

 $ ./pingSys '; /bin/sh'
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=0.071 ms
# whoami
  • Slams head on table ...It's always the small things that slip past. Oct 28, 2018 at 21:44

So, because you haven't quoted the parameter, you are passing two separate commands to your non-elevated shell. One of them runs as root, and calls ping. The other runs as user and spawns a sub-shell. Your command is equivalent to this:

$ ./pingSys
$ /bin/sh

The first line runs as root, the second as the current user. Quoting the full parameter should make it work like you expect.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .