CVE-2014-3153
Folders and files
Name | Name | Last commit date | ||
---|---|---|---|---|
parent directory.. | ||||
-----------------------------[CVE-2014-3153]----------------------------------- ------------------------------------------------------------------------------- CVE-2014-3153 is one of the most known CVEs in the Linux kernel. It was exposed in May 2014 . It was extensively used to root Android devices < 2014. Towelroot is an exploit that "works" using this CVE, but it's closed source and yet obfuscated against reverse engineering as it was compiled using llvm-obfuscator. CVE Details Description: The futex_requeue function in kernel/futex.c in the Linux kernel through 3.14.5 does not ensure that calls have two different futex addresses, which allows local users to gain privileges via a crafted FUTEX_REQUEUE command that facilitates unsafe waiter modification. From the description above we can tell that this CVE is about: 1 - Futexes - futex system call. 2 - FUTEX_REQUEUE is the vulnerable command. 3 - waiter modifications is our target. First futex() is a system of synchoronization between threads or processes kind of mutexes but here the majority of the synchronization operations are perform- ed in user-space. We need the help of the kernel only in one case when the thr- ead is believed to hang for a very long time that userspace can't handle it, so it wait in the kernel. futex() is a system call without a wrappers (cs it's rarely used I guess only pthread use it internaly). The bug: Vulnerability researchers found that if you execute these sequence of steps one after the other a kernel crash will occur: 1 - FUTEX_LOCK_PI 2 - FUTEX_WAIT_REQUEUE_PI 3 - FUTEX_CMP_REQUEUE_PI 4 - "Make PI futex = 0" 5 - FUTEX_CMP_REQUEUE_PI I tested it and it crashed my kernel, and I knew this bug is exploitable so I wanted to see why it crashed. The vulnerability: The vulnerability is that you can create a thread waiting on a futex, requeue it to another one (using the 5 steps above) like that you will be having its waiter (struct rt_mutex_waiter rt_waiter) linked but out of scope (it can be changed in the stack). The interesting struct here is this (we can corrupt it): futex_wait_requeue_pi() will let this important struct in the stack but still linked. struct rt_mutex_waiter { struct plist_node list_entry; struct plist_node pi_list_entry; struct task_struct *task; struct rt_mutex *lock; #ifdef CONFIG_DEBUG_RT_MUTEXES unsigned long ip; struct pid *deadlock_task_pid; struct rt_mutex *deadlock_lock; #endif }; The first two elements are interesting pointers that we can use to achieve (Write kernel pointer Where) and that would result in an exploitable condition. Everytime we lock the PI futex a new waiter will be added to the doubly linked list, and with corrupted pointers we can put kernel pointers in critical places that can lead to LPE. If you can corrupt the rt_mutex->list_entry->node_list->next and then add another waiter, it will be interpreted like this : *(rt_mutex->list_entry->node_list->next) = waiter <- kernel address The rt_waiter is in the stack, so what syscall should we use to corrupt it with the data we want? We will be using this script that comes with the linux source tree. $ objdump -d vmlinux | ./scripts/checkstack.pl i386 | grep -E "(futex_wait_requeue_pi|sys)" 0xc1092524 do_sys_poll [vmlinux]: 928 0xc10925dd do_sys_poll [vmlinux]: 928 0xc10929a8 do_sys_poll [vmlinux]: 928 0xc1091fc4 core_sys_select [vmlinux]: 288 0xc109209a core_sys_select [vmlinux]: 288 0xc111cc58 ___sys_sendmsg [vmlinux]: 244 0xc111cd88 ___sys_sendmsg [vmlinux]: 244 0xc111d5ea ___sys_recvmsg [vmlinux]: 216 0xc111d722 ___sys_recvmsg [vmlinux]: 216 0xc111e51b __sys_sendmmsg [vmlinux]: 184 0xc111e5c9 __sys_sendmmsg [vmlinux]: 184 0xc111e5e4 __sys_sendmmsg [vmlinux]: 184 0xc104d474 futex_wait_requeue_pi.constprop.27 [vmlinux]:180 0xc104d5a8 futex_wait_requeue_pi.constprop.27 [vmlinux]:180 0xc10096b1 syscall_trace_leave [vmlinux]: 128 0xc1009705 syscall_trace_leave [vmlinux]: 128 From the output we know that we can use __sys_sendmmsg and __sys_recvmsg All the exploits that I've seen are using __sys_sendmmsg and I tried it at first but it didn't work for me for some reason that I don't know. I was 0x30 away from the struct. __sys_recvmsg did the trick for me. So now we know that we can write a kernel address where. What to do with this primitive. First we need the leaks, to get the leaks all you have to do is corrupt the next pointer with a userland address and link a waiter and you will be having a kernel stack address in a userland address (we can do it because SMAP isn't present). Now we have a kernel stack address what to do with it? We can reveal thread_info which is in the stack, and from that we know the address of addr_limit. Now all left to do is corrupt addr_limit (write kernel address where) and now we're in the situation of addr_limit > &addr_limit. Now we can read and write to and from the kernel. We will be reading pointers like this: thread_info -> task_struct -> group_leader -> cred And because we can write to kernel addresses we will patch *ID to 0 and pop a shell. This was a really short wu, I can't even call it a wu, but I'm not leaving you here, here are some of the interesting wus I found, especially the one from elongl, I liked it a lot. Links: https://elongl.github.io/exploitation/2021/01/08/cve-2014-3153.html https://tinyhack.com/2014/07/07/exploiting-the-futex-bug-and-uncovering-towelroot/ https://www.programmersought.com/article/95265451595/ https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part4.html https://elixir.bootlin.com/linux/v3.11.4/source/kernel/futex.c#L2643