thechico
thechico

Reputation: 21

Code vulnerability

As a learning exercise, I am trying to find a weakness in the following code snippet to gain access as the owner of the executable.

setresuid(geteuid(), geteuid(), geteuid());
system("/usr/bin/id");

FWIW, I can't see any. I know setresuid will set the uid to the owner of the file, but I can't change the owner to anyone but myself. I thought about trying to redirect the id command by altering the PATH, but since it uses an absolute path, that trick doesn't work. Hints?

Upvotes: 0

Views: 2264

Answers (2)

John Bollinger
John Bollinger

Reputation: 181149

The system() function executes the command given as its argument by passing it to /bin/sh -c. I think the /usr/bin/id program is not particularly relevant; it is the shell's behavior that is key. In particular, note that the shell's startup behavior is different when the real and effective UIDs differ:

If the shell is started with the effective user (group) id not equal to the real user (group) id [...] no startup files are read, shell functions are not inherited from the environment, the SHELLOPTS, BASHOPTS, CDPATH, and GLOBIGNORE variables, if they appear in the environment, are ignored, and the effective user id is set to the real user id.

-- BASH 4.1 manual

In the event that a program containing the code you presented is installed suid, the code prevents the condition given in that paragraph from applying by setting real, effective, and saved UIDs all equal to the effective UID (which will be the UID of the owner of the executable).

Exploits typically revolve around unsafe use of untrustworthy data, with environment variables being a frequent offender. The ENV environment variable in particular names a file that under some circumstances the shell will execute at startup. bash will not run it when the real and effective UIDs differ, as documented in the excerpt above, but otherwise will do so when invoked interactively in POSIX compatibility mode or as sh.

That doesn't help for non-interactive invocation, as applies here, so now I have to go speculative. I suspect, but cannot currently document, that some other past -- and maybe even present -- versions of the shell do read and execute commands from the file named by ENV when invoked non-interactively. That would provide a vector for executing arbitrary commands as the owner of the setuid program.

In weak support of that speculation I direct your attention to the BASH_ENV variable, which is analogous to ENV, but is used when bash is invoked noninteractively, as bash. I am supposing that once these two variables were more parallel, applicable to both interactive and non-interactive modes, but the non-interactive use of ENV and the interactive use of BASH_ENV were removed at different times. for different reasons. Quite possibly the non-interactive use of ENV was removed to plug exactly the hole that you are looking for.

Upvotes: 1

user149341
user149341

Reputation:

It is possible to exploit an obscure (and now patched) issue involving the unchecked usage of setresuid():

  1. Under Linux 2.6 and later, setresuid() can fail if the process is running with an RLIMIT_NPROC (that is, a limit on the number of processes as set by ulimit -n) such that the target UID would have too many processes if the setresuid() succeeded.

    However, under Linux 3.1 and later, failing a setresuid() sets a flag on a process such that any subsequent execve() calls will fail. This would prevent the system() from running on any modern Linux if the setresuid() failed.

  2. Unless there is some larger context which has been omitted, it may be possible to set environment variables (e.g, LD_PRELOAD) which cause code to be injected into /usr/bin/id. These variables are ignored for setuid executables, but will not be ignored for executables launched by a setuid executable, as is occurring here.

If you are on a vulnerable system (Linux 2.6 through 3.0), you may be able to exploit this vulnerability by setting environment variables and causing the setresuid() to fail, so that /usr/bin/id runs user-specified code as root.

Upvotes: 1

Related Questions