Edit, I did learn cool new stuff tho, thanks.
Edit, I did learn cool new stuff tho, thanks.
I walk through the process of developing the exploit and primitives, and was upfront that I ran into a mitigation which thwarted my exploit strategy. Similar to other exploit writeups I've done, I try to focus on the big picture and illustrate the idea (through writing and diagrams) while still being technically rigorous. Exploit development is much more reading code than it is writing it.
If you have any suggestions for improvement, or want to tell me which sections felt like handwaving to you, please let me know! Better yet, if you have an idea on how to defeat the mitigation so I can complete the exploit, I would love to discuss it.
BTW: Failing to produce an exploit for a very powerful bug like this, despite my best efforts, was considered a giant win for the security review of Firecracker.
>If you have any suggestions for improvement
Not GP, but I struggled to follow some parts due to passive voice.[0] There were a lot of sentences that omit the actor of the sentence, so I had a hard time understanding which component performed which action.
For example:
>If specified in flags, descriptors can be chained together with next containing the descriptor table index of the chained descriptor. virtio-vsock, buffers in a descriptor chain are used to construct a vsock packet. Something to note at this point: the buffer information in the descriptor comes from the guest, and it should be treated as untrusted.
So when I read that, I have to mentally walk back and figure out:
* can be chained together -> Who chains descriptors together?
* are used to construct a vsock packet -> Who constructs the packet?
* should be treated as untrusted -> Who should treat it as untrusted?
From context, I can figure these things out, but the Firecracker/kernel concepts you're explaining are occupying most of my mental bandwidth. Any bandwidth you can free up with simpler sentences makes it easier for me to focus on the main subject of the blog.
[0] https://writing.wisc.edu/handbook/style/ccs_activevoice/
I've read over this paragraph a few times now and I'm really struggling to see how their protections don't defend against the described issues -
"There are two problems that could occur; the base and result address may belong to two different regions, and the base address may not even exist in a valid region."
"the base and result address may belong to two different regions"
if addr >= region.guest_base && addr < region_end(region)
Surely region_end(region) stops it belonging to two different regions, as you're using one region in the for loop? I'm probably being thick!
"the base address may not even exist in a valid region."
Again surely if the addr < region_end(region) this would ensure it's within a valid region?
Is there any other info you can provide so that my simple brain can understand?
The key here wasn't to produce an exploit. That would have been interesting, but ultimately not the entire goal. The key was to understand "how do we use Firecracker in the safest possible way for our use case?". To do that we picked one of the CVEs that looked like it could be exploitable and dug into it.
We learned a ton about Firecracker and KVM and walked away with some mitigations we can implement such that even if the bug had been exploitable the attacker would have more hurdles to jump through. Specifically, we'll be working to harden the guest operating system such that the untrusted code will have a difficult time escalating to root/kernel, which is a prerequisite for this sort of attack.