Skip to content

Files

Failed to load latest commit information.

Latest commit

 Cannot retrieve latest commit at this time.

History

History

CVE-2019-2215_BinderThreadUaf

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

This folder contains an exploit for CVE-2019-2215, exploiting a bug in Binder (RIP BeOS)

The quest linux kernel code can be pulled from https://github.com/facebookincubator/oculus-linux-kernel.

The Oculus Quest is vulnerable up to version 3965200061700000. This and other vulnerabilites were patched by https://github.com/facebookincubator/oculus-linux-kernel/commit/84f9a63a81a226cc5e8c7c071a5cd077ef6445a3

Although this tree is based on MSM 4.4, it is not current and contained this vulnerability among others. The MSM 4.4 tree brought in the fix in early/mid 2018 from upstream. The bug was found by syzkaller in early 2018. The P0 post linked to below covers how the fix was not included in Wahoo since it did not get a CVE at the time. It's suspected that this was being exploited in the wild by the NSO group. Facebook is coincidentally suing NSO right now regarding that matter.

The binder bug is a fairly trivial UAF. In the vulnerable versions of the driver, it's possible to use epoll() to wait on events from a binder client, but the driver also allows clients to release the underlying data structure that epoll is waiting from/to. When releaing the epoll it will mangle the lock in the released buffer.

For exploitation, the P0 PoC uses a method that exploits in-flight IOVEC structures (see https://bugs.chromium.org/p/project-zero/issues/detail?id=1942).

This method was previously published by Di Shen at KeenLab (https://www.blackhat.com/docs/eu-16/materials/eu-16-Shen-Rooting-Every-Android-From-Extension-To-Exploitation-wp.pdf)

This exploit applies the same method. The in-flight iovecs are flexible -- they can be allocated at variable lengths for matching the size of any Use-After-Free.

It's also possible to use blocking and other features on pipes and sockets to modify state in a controlled manner. Smashing data in the iovec can be used for arbitrary reads as well as arbitrary writes.

In the P0 PoC, a pointer to the current task's 'task_struct' happens to lie at the end of the binder_thread, and that exploit reads it out before writing to it. For the Oculus tree, the binder code is much older and doesn't contain that member variable.

The way the UAF corruption works with epoll also lends well for exploitation. When epoll's reference to the thread is released, the spinlock routines will leave behind a self-referential pointer. This can be used to create a write into the iovec to update the in-flight structure with arbitrary values.

For this exploit the flow for the corruption is to:

  • Create the UAF condition
  • Trigger the corruption, leaving behind the self referencing pointer in the IOVEC
  • Write an arbitrary destination (in this case the TTBR1 page table entry)
  • Write an 8-byte value to that destination (rwx/rwx permissions to kernel physical memory)

This lets every linux process have rwx/rwx memory access to kernel memory.

The version of the binder driver in the quest kernel had a further complication as well. Without a transaction ready to read, the poll will happen on a 'binder_proc' structure, and not a 'binder_thread'. Theres no BINDER_PROC_EXIT, as there is with BINDER_THREAD_EXIT. The exploit runs some code in force_thread() to set up the binder thread to poll on the correct data structure.

====

Compile this with an aarch64 android toolkit, and run it from /data/local/tmp/;

while true; do /data/local/tmp/exploit; done