Bash 4.3 setuid() BUG
Authors: | Hector Marco & Ismael Ripoll |
BUG: | Lack of checking setuid() return code |
Dates: | 10 December 2013 - Discovered the bug |
| 25 March 2014 - Public disclosure |
Description
A bug in bash for versions prior to 4.3 has been found. The bug is
caused by not checking the return values of setuid() and
getuid() calls. The process shall not continue its normal
execution when any of these calls fail (returns an error) to
drop privileges.
Impact
The bash shell contains the drop privileges code
as a way to improve the security of the applications that use
it. It is not advisable to execute bash with a modified
effective uid or gid. This way, a careless privileged
application or a root shell would not be able to damage the
system.
The drop privileges error is not actually a security issue
to the bash because bash is not installed with the bit setuid,
but this code was added to help to protected the system.
Vulnerable packages
Bash package 4.3 is vulnerable,
version from 3.0 (released on August 2004) to the current 4.3
(last git commit on 26 February 2014) is also affected.
The bug
The bug appears because the return value of the
setuid() call is not checked. When
the setuid() fails, the application continue its normal
execution (does not terminate) and the remaining code is
executed with the original privileges.
The bug appears in shell.c file, on lines 1229 and 1230:
void
disable_priv_mode ()
{
setuid (current_user.uid);
setgid (current_user.gid);
current_user.euid = current_user.uid;
current_user.egid = current_user.gid;
}
Exploit
The strategy to exploit this kind of bugs
consists in creating as many processes as the target user is
allowed to make (which is given by RLIMIT_NPROC), and then the
next attempt to drop privileges will fail, letting the process
alive and with the original privileges.
FIX
We have created a non official patch for bash-4.3:
diff --git shell.c shell.c
index bbc8a66..5bfd466 100644
--- shell.c
+++ shell.c
@@ -1226,8 +1226,12 @@ uidget ()
void
disable_priv_mode ()
{
- setuid (current_user.uid);
- setgid (current_user.gid);
+
+ if( (setgid (current_user.gid) !=0) || (setuid (current_user.uid) != 0) ){
+ report_error("Drop privileges failed!!\n");
+ exit(-1);
+ }
+
current_user.euid = current_user.uid;
current_user.egid = current_user.gid;
}
[ bash_4.3-fix-setuid.patch ]
Patching bash-4.3:
$ wget http://hmarco.org/bugs/patches/bash_4.3-fix-setuid.patch
$ cd bash.4.3
$ patch -p0 < ../bash_4.3-fix-setuid.patch
Discussion
There has been some discussions whether this is a security issue
or not. This is a bash security feature to help other
applications with the setuid bit to prevents to execute bash
with root privileges. If bash drop privileges fails then other
applications, as for example
the s3dvt setuid
vulnerability, could obtain a root shell.
We think that this is a security issue because in some
circumstances the bash security feature could be bypassed
allowing the bash to be a valid target shell in an attack.
Hector Marco - http://hmarco.org