Bash – From which version does Bash drop privileges

bashprivilegesshellsystem-callsversion

I've been trying to do some buffer overflow attack, and I thought I could use system("/bin/bash") in order to obtain a root shell.

Then I read the documentation for system().

It says:

system() will not, in fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2 drops privileges on startup.

The system I am attacking has a bash version 4.3, and when I use a system("/bin/bash"), I don't get root privileges (of course the initial program I am attacking starts with root privileges). My question is: will system drop privileges only on bash version 2, or will it drop them for any bash that has a version > 2?

EDIT: /bin/bash just drops privileges, while /bin/dash or /bin/sh don't.

After reading comments from @StéphaneChazelas, EDIT2:

  • check this link for more explanation and accuracy about bash dropping privileges.
  • -p option can be used to be sure to keep privileges when the bash spawns.

Best Answer

Current version

Recent versions of bash will drop privileges, unless it was started with -p. From the section of bash(1) describing the privileged mode:

If the shell is started with the effective user (group) id not equal to the real user (group) id, and the -p option is not supplied, [...] the effective user id is set to the real user id. If the -p option is supplied at startup, the effective user id is not reset. Turning this option off causes the effective user and group ids to be set to the real user and group ids.

Historical versions

You asked "From which version...?". The part of system() that you quote has been unchanged since the earliest revision available in the active git repository (version 1.70). That was checked in in 2004, and the comments indicate it was last modified in 2001.

Bash version 3 was released in 2004. That means that bash 2 would have been the current/latest version at the time. So effectively, it's saying "...bash version 2 or higher/newer", ie. this has been the case since version 2.

To confirm for yourself, you could try to build some intermediate versions and test them, or consult the bash git repository. The lines responsible are:

  if (running_setuid && privileged_mode == 0)
    disable_priv_mode ();

Those have been there since version 2.0. Looking back to version 1.14.7, bash would only drop privileges when privileged mode was explicitly disabled with +p:

    case 'p':
      if (on_or_off == '+')
      {
        setuid (current_user.uid);
        setgid (current_user.gid);
        current_user.euid = current_user.uid;
        current_user.egid = current_user.gid;
      }