Introduction
A couple of weeks ago a heap overflow vulnerability in the TIPC subsystem of theLinux kernel was disclosed by Max van Amerongen (.
It’s a pretty clear cut heap buffer overflow where we control the size and data of the overflow.I decided I wanted to embark on a small exploit development adventure to see how hard it would be to exploit this bugon a kernel with common mitigations in place (SMEP/SMAP/KASLR/KPTI).
If you came here to find novel new kernel exploitation strategies, you picked thewrong blogpost, sorry!
TIPC?
To quote the on the TIPC webpage that detailseverything about transport, addressing schemes, fragmentation and so on.
That’s a lot of really dry stuff though. I made some PCAPs of a tipc-over-udpsession setup and with some hand-waving and reading the kernel source narrowedit down to a few packets we need to emit before we can start sending the messageswe are interested in.
In short, a typical TIPC datagram starts with a header, that consist out of at leastsix 32bit words in big endian byte order. Those are typically referred to as w0 through w5.This header is (optionally) followed by a payload. w0 encodes the TIPC version,header size, payload size, the message ‘protocol’. There’s also a flag whichindicates whether this is a sequential message or not.
w1 encodes (among other things) a protocol message type specific to the protocol.
The header also specifies a node_id in w3 which is a unique identifier a nodeincludes in every packet. Typically, nodes encode their IPv4 address to be theirnode_id.
A quick way to learn about the various bit fields of theheader format is by consulting by some Pennsylvania State University students who dubbed objects with such properties “Elastic Objects”.Their research on the subject is quite exhaustive and covers Linux, BSD and XNU.. I definitley recommendchecking it out.
Since we can pick arbitrarily sized allocations, we’re free to target any convenientelastic object. I went with msg_msg, which is :
/* one msg_msg structure for each message */struct msg_msg {struct list_head m_list;long m_type;size_t m_ts;/* message text size */struct msg_msgseg *next;void *security;/* the actual message follows immediately */};You can easily allocate msg_msg objects using the msgsnd system call. Andthey can be freed again using the msgrcv system call. These system calls arenot to be confused with the sendmsg and recvmsg system calls btw, great naming scheme!
If we corrupt the m_ts field of a msg_msg object we can extend its size and get a relative kernel heap out-of-boundsread back to userland when retrieving the message from the queue again using the msgrcvsystem call.
A small problem with this is that overwriting the m_ts field also requirestrampling over the struct list_head members (a prev/next pointer). When msgrcvis called and a matching message is found, it wants to unlink it from the linked list..but since we’re still in the information leak stage of the exploit, we can’t put any legitimate/meaningfulpointers in there. Luckily, there’s a flag you can pass to msgrcv called MSG_COPY, whichwill make a copy of the message and not unlink the original one, avoiding a bad pointer dereference.
So the basic strategy is to line up three objects like this:
msg_msgmsg_msgsome_interesting_objectand proceed to free the first msg_msg object and allocate the MSG_CRYPTO keybuffer into the hole it left behind. We corrupt the adjacent msg_msg using thebuffer overflow and subsequently leak data from some_interesting_object usingthe msgrcv system call with the MSG_COPY flag set.
I chose to leak the data of tty_struct, which can easily be allocated by open()‘ing/dev/ptmx. This tty_struct holds all kinds of state related to the tty, andstarts off like this:
struct tty_struct { int magic; struct kref kref; struct device *dev; /* class device or NULL (e.g. ptys, serdev) */ struct tty_driver *driver; const struct tty_operations *ops; int index; ...}A nice feature of this structure is the magic at the very start, it allows usto easily confirm the validity of our leak by comparing it against the expectedvalue TTY_MAGIC (0x5401). A few members later we find struct tty_operations *ops whichpoints to a
A succesful run of the exploit should look something like this:

SOCIAL SHARE CARD GENERATOR