I write a simple program named suid.c
:
int main(int argc, char* argv[]) {
system(argv[1]);
}
Compile it with gcc then set suid permission (root user now):
# gcc suid.c -o suid
# chmod +s suid
I tried to run ./suid id
with the www-data user on different virtual machines, but the output is different.
id=33(www-data) gid=33(www-data) groups=33(www-data)
uid=33(www-data) gid=33(www-data) euid=0(root) egid=0(root) groups=0(root),33(www-data)
Why is that? Has anything changed in Linux?
It depends whether /bin/sh
is bash or dash on your distribution. Bash always drops setuid/setgid privileges unless invoked with the option -p
. Dash doesn't do anything special about privileges.
On Ubuntu, the system
function invokes sh
, which is /bin/sh
, which is dash, which doesn't drop privileges. On Kali, the system
function invokes sh
, which is /bin/sh
, which is bash, which drops privileges. It's a matter of which shell the distribution installs as sh
, not of how recent the distribution is.
Bash's behavior can be a security countermeasure, but it isn't a very effective one. It's a second line of defense against misguided configurations or badly written programs that run with privileges that they shouldn't have, and allow untrusted input to functions such as system
. However, such programs usually have other holes that allow the potential attacker to attack anyway, such as the ability to write to files.