SSD Advisory – Linux Kernel AF_PACKET Use-After-Free

Credit to Author: SSD / Maor Schwartz| Date: Tue, 17 Oct 2017 11:42:53 +0000

Want to get paid for a vulnerability similar to this one?
Contact us at: sxsxdx@xbxexyxoxnxdxsxexcxuxrxixtxy.xcom

Vulnerabilities summary
The following advisory describes a use-after-free vulnerability found in Linux Kernel’s implementation of AF_PACKET that can lead to privilege escalation.

AF_PACKET sockets “allow users to send or receive packets on the device driver level. This for example lets them to implement their own protocol on top of the physical layer or to sniff packets including Ethernet and higher levels protocol headers”

Credit
The vulnerability was discovered by an independent security researcher which reported this vulnerabilities to Beyond Security’s SecuriTeam Secure Disclosure program.

Vendor response
“It is quite likely that this is already fixed by:
packet: hold bind lock when rebinding to fanout hook – http://patchwork.ozlabs.org/patch/813945/

Also relevant, but not yet merged is
packet: in packet_do_bind, test fanout with bind_lock held – http://patchwork.ozlabs.org/patch/818726/

We verified that this does not trigger on v4.14-rc2, but does trigger when reverting that first mentioned commit (008ba2a13f2d).”

Vulnerabilities details

This use-after-free is due to a race condition between fanout_add (from setsockopt) and bind on a AF_PACKET socket.

The race will cause __unregister_prot_hook() from packet_do_bind() to set po->running to 0 even though a packet_fanout has been created from fanout_add().

This allows us to bypass the check in unregister_prot_hook() from packet_release() effectively causing the packet_fanout to be released and still being referenced from the packet_type linked list.

Crash Proof of Concept

Crash report

We know that the freed object is a kmalloc-4096 object:

and that its prot_hook member is the one being referenced in the packet handler when registered via dev_add_pack() from register_prot_hook() inside af_packet.c:

The function pointers inside of struct packet_type, and the fact it is in a big slab (kmalloc-4096) makes heap spraying easier and more reliable as bigger slabs are less often used by the kernel.

We can use usual kernel heap spraying to replace the content of the freed packet_fanout object by using for example sendmmsg() or any other mean.

Even if the allocation is not permanent, it will still replace the targeted content in packet_fanout (ie. the function pointers) and due to the fact that kmalloc-4096 is very stable, it is very less likely that another allocation will corrupt our payload.

id_match() will be called when sending a skb via dev_queue_xmit() which can be reached via a sendmsg on a AF_PACKET socket. It will loop through the list of packet handler calling id_match() if not NULL. Thus, we have a PC control situation.

Once we know where the code section of the kernel is, we can pivot the kernel stack into our fake packet_fanout object and ROP. The first argument ptype contains the address of the prot_hook member of our fake object, which allows us to know where to pivot.

Once into ROP, we can jump into native_write_c4(x) to disable SMEP/SMAP, and then we could think about jumping back into a userland mmaped executable payload that would call commit_creds(prepare_kernel_cred(0)) to elevate our user process privilege to root.

Print Friendly, PDF & Email

https://blogs.securiteam.com/index.php/feed