-
Notifications
You must be signed in to change notification settings - Fork 12
/
README
83 lines (74 loc) · 3.18 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
The vulnerability was a UAF for this specific challenge (kmalloc-4k).
There are not much structs to target, I used packet_fanout when opening and AF_PACKET socket like this :
send_fd = socket(AF_PACKET, SOCK_RAW, PF_PACKET);
I will have a struct packet_fanout on my UAF struct, which I can modify:
struct packet_fanout {
possible_net_t net;
unsigned int num_members;
u32 max_num_members;
u16 id;
u8 type;
u8 flags;
union {
atomic_t rr_cur;
struct bpf_prog __rcu *bpf_prog;
};
struct list_head list;
spinlock_t lock;
refcount_t sk_ref;
struct packet_type prot_hook ____cacheline_aligned_in_smp;
struct sock __rcu *arr[];
};
num_members interest me more, it gave me a primitive to put a heap pointer (of type struct sock*) past
arr member.
When adding a new socket of the same type this will execute:
static void __fanout_link(struct sock *sk, struct packet_sock *po)
{
struct packet_fanout *f = po->fanout;
spin_lock(&f->lock);
f->arr[f->num_members] = sk;
smp_wmb();
f->num_members++;
if (f->num_members == 1)
dev_add_pack(&f->prot_hook);
spin_unlock(&f->lock);
}
Notice that there is no checks on f->num_members and we can control it.
With that oob heap write, I overwrote next field of msg_msg struct:
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 */
};
And I got kernel leaks.
Using the same bug (heap oob) I sprayed like 0x100 opened /dev/firewall and
changed firewall_fops to a heap pointer (of type struct sock *) for one of
them that IDK, free that socket, and get it back using setxattr now we can
control RIP, I found mov qword ptr [rdx], rsi; ret; gadget which gave me
arbitrary write in the kernel using ioctl(), I didn't notice that
modprobe_path was hardened so I guess I can be able to solve it other way.
Now when finshed my exploit in root user I switched to normal user, the
exploit didn't work because I wans't able to create the socket, it returned -1
I need cap_net_admin to open an AF_PACKET socket lol.
This exploit may work on older kernel versions but now let's focus on the one
we have, so I started another exploit, exploiting only msg_msg struct.
We can control msg_msg struct, first I sprayed shm_file_data, to bypass
fg-kaslr, then I corrupted m_ts field to a bigger size, and I got some kernel
leaks, now I can calculate the base address.
Now that I have kernel leak I can turn that into arbitrary read, and because
it has a race condition (TOCTOU) when allocating the next chunk, and when
writing to it (we can use userfaultfd to make the exploit reliable).
Note that you will get next field when your actual message size is bigger than
0x1000.
We can turn that into arb write (I used that only once to not make a lot of
noise).
Now I have arb read and arb write, I started at init_task go prev 1 time, and
we will have out task_struct, read the cred struct and patch *ID to 0 using
the arb write.
A lot of protection mechanisms were enabled to harden the heap and everything,
idk if this much protections should be used in a production system as it will
slow down the machine.
That was a very good challenge, from FizzBuzz101 and d3v17.