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!

Getting root on Ubuntu through wishful thinking- 740

Kevin BackhousePosted 4 Years Ago
  • This is a story of how the author successfully exploited CVE-2021-3939 in Ubuntu’s accountsservice, then spent the next two weeks trying to figure out how my own exploit worked. It seemed like magic, even to him! The original bug was accidentally discovered while writing an exploit for another vulnerability.
  • There is a static variable (shared between threads) that is allocated once. In the function user_get_fallback_value, a pointer to this static variable is returned. However, in some code paths, this variable can be freed. Since this variable is only crated the one time, this results in a double free vulnerability on the string, which can be triggered an infinite amount of times.
  • When exploiting a double free vulnerability, the basic idea is to turn this into a use after free. The idea is to free the object once, get something useful allocated into this location, use the bug to free it again to create the UAF. Once it is in this state, it is MUCH easier to exploit, even if the original bug was a double free. Most of the time, we want multiple “owners” to both believe that they own the same chunk of memory.
  • When searching for primitives with this bug, the author came across many issues. The freed chunk is only 0x20 bytes in size, which means the stability of the exploit goes way down since it will be reused frequently. To make the stability worse, the author also noticed this vulnerability could be used as an information disclosure by using the user_new functionality. However, this only worked if the address from a valid UTF-8 string.
  • To successfully exploit this vulnerability, the author needed a 0x20 sized memory allocation or get it to consolidate into a larger chunk. After hitting several deadends (such as rewriting bus names), with no good targets in the 0x20 size, the author ran into some magic once they stepped away from their seat!
  • After attempting one exploit strategy with a wrong sized chunk, their exploit magically worked after several hours of a script running. After spending weeks trying to figure it out, they came to a crazy conclusion: two different threads were overwriting a function pointer! This happens because of the double free bug on an object with a function pointer inside of it.
  • When SetEmail or any call is made to Polkit, a struct called CheckAuthData is used. This struct has a function pointer that determines what call to make during a callback. This struct is also 0x20 in size.
  • As a result, if we trigger the double free vulnerability on the 0x20 sized chunk, it MAY be the CheckAuthData struct getting freed. Then, another request, such as SetPassword, would be made, creating the CheckAuthData in this chunks place. When the original requests uses the callback (and it's authorized to), it will be on the wrong callback, resulting in SetPassword being called instead. Wow, that is wild!
  • The author really leaned into the madness on this one. Most of the time, exploits do not fall out of a tree like this. However, it is interesting to see how a simple double free, with no other primitives, leads to the ability to change a password. These data-driven attacks are incredibly hard to stop.