Authors: | Hector Marco & Ismael Ripoll |
CVE: | CVE-2013-6876 |
BUG: | Lack of checking setuid() return code |
Dates: | 10 December 2013 - Discovered the bug |
25 March 2014 - Public disclosure |
The drop privileges in s3dvt has the purpose to prevent to execute the bash with root privileges. In the cases where the application is installed with set bit setuid a non-privileged user could obtain a root shell.
Because the bash setuid() bug this bug can be exploited successfully. See discussion section.
s3dvt package 0.2.2 is vulnerable. From the first commit on January 2006 to the current 0.2.2 (released May 2011) are also affected. Commit 0ad732f00b411b092c66a04c359da0f16ec3b387 fix the vulnerability is . After some discussion, the author decided to fix it but forgot to credit our contribution.
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. In this case it is possible to obtain a root shell.
The bug is still present and exploitable. A different CVE number has been assigned. See CVE-2014-1226 - s3dvt_0.2.2 root shell.
The bug appears in apps/s3dvt/main.c file, on lines 169, 170, 231 and 232:
static int pty_init_terminal(void) { char tmpstr[1024]; int curtty; int uid = 0, gid = 0; char exe[] = "/bin/bash"; uid = getuid(); gid = getgid(); ... setuid(uid); setgid(gid); ... execl(exe, exe, NULL); ... } static int pipe_init_terminal(void) { int uid = 0, gid = 0; const char *exe = "/bin/bash"; const char *args = "-i"; ... uid = getuid(); gid = getgid(); pid = fork(); if (pid == 0) { /* the child */ char tmpstr[1024]; setuid(uid); setgid(gid); ... execl(exe, exe, args, NULL); ... } }
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.
diff --git apps/s3dvt/main.c apps/s3dvt/main.c index 0842e22..9fd6d8e 100644 --- apps/s3dvt/main.c +++ apps/s3dvt/main.c @@ -166,8 +166,10 @@ static int pty_init_terminal(void) printf("Error opening tty\n"); return 0; } - setuid(uid); - setgid(gid); + if ( (setgid(getgid()) != 0) || (setuid(getuid()) != 0) ){ + printf(stderr, "Failed to drop privileges\n"); + exit(-1); + } if (setsid() < 0) printf("ERROR (setsid)\n"); /* tcflush(curpty, TCIOFLUSH); */ @@ -228,8 +230,10 @@ static int pipe_init_terminal(void) pid = fork(); if (pid == 0) { /* the child */ char tmpstr[1024]; - setuid(uid); - setgid(gid); + if ( (setgid(getgid()) != 0) || (setuid(getuid()) != 0) ){ + printf(stderr, "Failed to drop privileges\n"); + exit(-1); + } if (setsid() < 0) printf("ERROR (setsid)\n"); /* tcflush(curpty, TCIOFLUSH); */[ s3dvt-fix-setuid.patch ]
$ wget http://hmarco.org/bugs/patches/s3dvt-fix-setuid.patch $ cd s3dvt-0.2.2 $ patch -p0 < ../s3dvt-fix-setuid.patch
This bug can be exploited because the there is a similar bug in the code of the bash. And so, an attacker can bypass/exploit both bugs to raise privileges.
As soon as we discovered the bug we tried our best to explain to s3dvt developers the problem and the way to fix it.
After a long discussion, they managed to realise the issue
and fixed one of the affected functions, the one that focused
the discussion.
But unfortunately:
We strongly believe that such kind of contribution (finding a bug, and explain/teach how it can be fixed) shall be properly recognised.
An advice for smart developers:If someone reports a bug of your software. At least say "Thanks".
- Everybody (including us) make mistakes.
- Genius learn from mistakes.
- Idiots try to hide them.