We finally have some answers about the Windows IPv6 vulnerability — and a Proof of Concept! The patch was a single change in the Windows TCP/IP driver’s Ipv6pProcessOptions()
, now calling IppSendError()
instead of IppSendErrorList()
. That’s not very helpful on its own, which is why [Marcus Hutchins]’s analysis is so helpful here. And it’s not an easy task, since decompiling source code like this doesn’t give us variable names.
The first question that needs answered is what is the list in question? This code is handling the option field in incoming IPv6 packets. The object being manipulated is a linked list of packet structs. And that linked list is almost always a single member list. When calling IppSendErrorList()
on a list with a single member, it’s functionally equivalent to the IppSendError()
in the fixed code. The flaw must be in the handling of this list with multiple members. The only way to achieve that criteria is to send a lot of traffic at the machine in question, so it can’t quite keep up with processing packets one at a time. To handle the high throughput, Windows will assemble incoming packets into a linked list and process them in batch.
So what’s next? IppSendErrorList()
, takes a boolean and passes it on to each call of IppSendError()
. We don’t know what Microsoft’s variable name is, but [Marcus] is calling it always_send_icmp
, because setting it to true means that each packet processed will generate an ICMP packet. The important detail is that IppSendError()
can have side effects. There is a codepath where the packet gets reverted, and the processing pointer is set back to the beginning of the packet. That’s fine for the first packet in the list, but because the function processes errors on the entire list of packets, the state of the rest of those packets is now much different from what is expected.
This unexpected but of weirdness can be further abused through IPv6 packet fragmentation. With a bit of careful setup, the reversion can cause a length counter to underflow, resulting in data structure corruption, and finally jumping code execution into the packet data. That’s the Remote Code Execution (RCE). And the good news, beyond the IPv6-only nature of the flaw, is that so far it’s been difficult to actually pull the attack off, as it relies on this somewhat non-deterministic “packet coalescing” technique to trigger the flaw.