Irssi 0.8.16-rc1 setuid() BUG
Authors: | Hector Marco & Ismael Ripoll |
BUG: | Lack of checking setuid() return code |
Dates: | 10 December 2013 - Discovered the bug |
| 10 December 2013 - Contacted affected vendor |
| 13 December 2014 - Fixed |
| 25 March 2014 - Public disclosure |
Description
A bug in irssi for versions prior to
0.8.16-rc1 have been found. The bug is caused by not checking the
return values of setuid() and getuid()
calls. The process must not continue its normal execution
when any of these calls fail (return an error) to drop
privileges.
Impact
The drop privileges in irssi has the purpose
to prevent careless users to unconsciously damage the
system. In the irssi application, the drop privileges is not
actually a security issue, but this code was added as a
generic defensive programming technique. It is not necessary
(and not advisable) to execute irssi by root or with the bit
setuid activated. See discussion section.
Vulnerable packages
Irssi package 0.8.16-rc1 is
vulnerable, versions from 8.10 (released on May-2008)
to the current 0.8.16-rc1 (released Dec-2013) are 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 executing (does not terminate) and
the following code is executed with the original privileges.
The bug appears in fe-common/core/fe-exec.c file, on
line 325:
...
setuid(getuid());
setgid(getgid());
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_DFL);
...
if (rec->shell) {
execvp(shell_args[0], (char **) shell_args);
fprintf(stderr, "Exec: /bin/sh: %s\n", g_strerror(errno));
} else {
args = g_strsplit(cmd, " ", -1);
execvp(args[0], args);
fprintf(stderr, "Exec: %s: %s\n", args[0], g_strerror(errno));
}
...
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 irssi-0.8.15:
--- irssi-0.8.15/src/fe-common/core/fe-exec.c 2010-04-03 18:19:24.000000000 +0200
+++ irssi-0.8.15-patched/src/fe-common/core/fe-exec.c 2013-12-10 16:40:15.015052397 +0100
@@ -317,8 +317,10 @@ static void process_exec(PROCESS_REC *re
/* child process, try to clean up everything */
setsid();
- setuid(getuid());
- setgid(getgid());
+ if ( (setgid(getgid()) != 0) || (setuid(getuid()) != 0) ){
+ printf(stderr, "Failed to drop privileges\n");
+ exit(-1);
+ }
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_DFL);
[ irssi-0.8.15-fix-setuid.patch ]
Patching irssi-0.8.15:
$ wget http://hmarco.org/bugs/patches/irssi-0.8.15-fix-setuid.patch
$ cd irssi-0.8.15
$ patch -p1 < ../irssi-0.8.15-fix-setuid.patch
Discussion
A official path have been released. According to irssi staff, the
privileges are droped to help careless users that executes irssi with root permissions. For
example by invoking irssi with the sudo command.
A careless user using irssi root privileges would have to
reach the maximum number of processes (RLIMIT_NPROC) before
attempting to do any accidental damage, which is a very
unlikely scenario.
Hector Marco - http://hmarco.org