Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kernelCTF: Add CVE-2024-41010 LTS #128

Merged
merged 12 commits into from
Dec 10, 2024
Merged

Conversation

0xTen
Copy link
Contributor

@0xTen 0xTen commented Aug 21, 2024

No description provided.

Copy link

google-cla bot commented Aug 21, 2024

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@0xTen 0xTen changed the title CVE-2024-41010 kernelCTF: Add CVE-2024-41010 LTS Aug 21, 2024
@koczkatamas koczkatamas force-pushed the master branch 2 times, most recently from b2e2b9f to 43a5a81 Compare September 27, 2024 21:30
@th3lsh3ll
Copy link

Hello @0xTen Thanks for your submission. May I ask a few questions?

Under the section "kmalloc-cg-512 -> kmalloc-cg-1k"

"We can now overlap a msg_msg with our skbuf->data object."
So the skbuf->data that msgmsg_seg/alt_ifname(from what I understand they are overlapped?) points to is made to overlap with a different msg_msg? This is done by adding another msg_msg to the queue with the overwritten msgmsg_seg?

Is it that you add another msg_msg to the same queue(which overwrites skb->data) then read until the end of msg linked list to leak pointers from kmalloc-cg-1k?

Then after leaking you write to skb->data since the msg_msg overlaps in order to free a msg_msg in another queue with the current one to end up at a double free in kmalloc-cg-1k?

@0xTen
Copy link
Contributor Author

0xTen commented Nov 7, 2024

Your understanding is generally correct except for:

This is done by adding another msg_msg to the queue with the overwritten msgmsg_seg?

Here is very detailed explanation that hopefully will give you a very deep understanding of what is going on:

For context, msg_msg and msg_msgseg are allocated when sending ipc messages and are deallocated by receiving ipc messages. Also, skbuf->data is allocated by sending data on one end of a unix socket pair and is deallocated by receiving the data on the other end of the socket pair.

Getting to kmalloc-cg-512 in the first place

Basically, at that stage I receive from the mqueue that contains the overwritten msg_msgseg (let's call it mqueue A) only to free the skbuf->data object (residing in kmalloc-cg-512) whose pointer I discovered in the previous step (using if_inaddr). After that, you can forget about the previous steps and the corrupted msg_msgseg, because what follows is bug agnostic:
The heap chunk containing that skbuf->data will be put on top of the cg-512 freelist because I freed it by receiving the corrupted msg_msgseg (from mqueue A), and I can now reclaim that chunk by allocating msg_msg using a different mqueue (let's call it mqueue B). At this point we will have a skbuf->data object and msg_msg object overlapping with each other on kmalloc-cg-512. Keep in mind that by receiving that skbuf->data from the socket I will be:

  1. reading the msg_msg struct and leaking it's contents
  2. deallocating the chunk and putting it back on top of the freelist
    After that, if I send data on the socket again I will reclaim the same chunk again and overlap the msg_msg struct, so I can effectively view and edit the msg_msg object as I like.

Getting from kmalloc-512 to kmalloc-cg-1k

Now that we have a fully controllable msg_msg object (which belongs to mqueue B) in kmalloc-cg-512, in order to go from that to kmalloc-cg-1k I do the following things:

  1. send another msg on mqueue B with a size such that it gets allocated in kmalloc-cg-1k, (this will populate the controllable msg_msg with a pointer) to this second msg, which lives in kmalloc-cg-1k.
  2. spray some messages on different mqueues (let's all them mqueue N) such that their msg_msg objects also get allocated in kmalloc-cg1k. This allows us to get a layout such that (in kmalloc-cg-1k) there will be the 2nd msg_msg of mqueue B followed by the 1st msg_msg of some mqueue N.
  3. I read the unix socket to read the 1st msg of mqueue B, which contains the pointer of the 2nd msg of mqueue B. I know for a fact that the next object following that pointer is a msg_msg belonging to a different mqueue N, so I add sizeof(kmalloc-cg-1k object) to the pointer that I just leaked, which should let me know the address of some msg_msg belonging to some mqueue N.
  4. I edit the 1st msg_msg of mqueue B by writing to the unix socket, such that it now no longer points to the 2nd msg of mqueue B and now points to the 1st msg_msg of some mqueue N. The keypoint that you should have in mind here is that some msg_msg that belongs to mqueue N is now not only linked in the list of mqueue N but ALSO in the list of mqueue B and it's accessible from both queues (let's called that msg_msg X).
  5. I free msg_msg X by receiving everything from mqueue B, but msg_msg X is still reacheable from mqueue N, so mqueue N references a heap chunk that is in the freelist of cg-1k.
  6. I send some skbuf->data with a size such that it gets allocated on kmalloc-cg-1k, reclaiming the slot of msg_msg X from the freelist. So now mqueue N has a reference to that skbuf->data.
  7. I free the same chunk again by receiveing from mqueue N, which will free the skbuf->data while it is still reacheable from the unix socket.

Going from that to root

At this point I have a similar scenario as I had on kmalloc-cg-512, which is a dangling skbuf->data object that can be overlapped with any struct I want and I will be able to edit that struct. I overlap it with pipe_buffer to control the pipe_buffer->page pointer and get arb r/w on kernel memory.

@th3lsh3ll
Copy link

thanks

@koczkatamas
Copy link
Collaborator

Hey 0xTen!

Thank you for your submission!

It looks well documented and easy to read.

One question: why did you choose to scan the kernel memory to leak kASLR & find the modprobe address instead of using a ROP chain with target-specific symbol addresses? Was this scanning technique stable as well?

@koczkatamas koczkatamas merged commit 0509ad4 into google:master Dec 10, 2024
5 checks passed
@koczkatamas koczkatamas added the recheck Triggers kernelCTF PR verification again label Dec 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
recheck Triggers kernelCTF PR verification again
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants