Objective : Run a program as root (C++ binary).
The same as : SetUID bit not working in Ubuntu?
And : Why setuid does not work on executable?
./a.out output:
E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)
E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?
psurana //output for "whoami" Look below for the code.
ls -l output:
-rwsrwxr-x 1 root root 46136 Jun 7 20:13 a.out
The Code :
#include <string>
#include <stdlib.h>
int main(int argc, char *argv[]){
std::string input = "apt-get install " + std::string(argv[1]);
system(input.c_str());
system("whoami");
return 0;
}
Details: : compiled the program and then did chown root:root a.out && chmod u+s a.out
. Please look above for ls -l output.
I still do not get the root privileges and the output for system("whoami") in the code is my own username on the machine.
Reading the two linked questions did not yield me anywhere. :(.
both the creator and the owner of the file are root. The setuid bit is set, so it should work. The filesystem is not external either, it is my own machine. How can I make this work?
Best Answer
If you change the code like this you can see the effective and real UIDs:
On my system this returns these two lines (I've used ... to skip irrelevant groups):
As you can see, the raw call to
id
returns an Effective UID of 0 (root), but the Real UID is still my own. This is what you would expect.However, you can see that the
bash -c id
call has stripped the Effective UID away so it is no longer running as root. This is documented underman bash
as follows:So the solution here should be to include the
-p
flag.(You can find out about the process by which
bash
resets its UID at Setuid bit seems to have no effect on bash.)However, the story's not finished here because I know you're going to say you didn't invoke
bash
. Unfortunately for you, that's pretty much whatsystem()
does on your behalf, and it doesn't allow you to specify-p
.strace
discards the root privileges, but here's enough of thestrace -f ./a.out
output for you to see what's going on:At this point the child process kicks off, ready to run our
id
Now we have a shell running, and it will have discarded our Effective UID. Next you'll see it starting the
id
command and writing its output to stdout for you:The solution for you here will be either to use one of the
exec*()
family directly, or to include a call tosetuid(0)
, or to configure a tool such assudo
to allow you to call your target program directly and (presumably) without a password.Of these options I'd personally go with the
sudo
solution. The authors of that spent a long time ensuring the code was safe against (un)intended escalation of privilege attacks.