1 00:00:00,480 --> 00:00:02,580 - Welcome to the 12 o'clock talk, 2 00:00:02,580 --> 00:00:05,820 on All Roads Lead to JKE. 3 00:00:05,820 --> 00:00:07,800 Without any ado, Billy, are you starting off? 4 00:00:07,800 --> 00:00:08,800 - Yes. - All right. 5 00:00:10,341 --> 00:00:13,341 (audience applauds) 6 00:00:14,550 --> 00:00:18,750 - Hi, I'm Billy, and thanks for coming. 7 00:00:18,750 --> 00:00:23,070 Here is our title, "All Roads Leads to GKE" 8 00:00:23,070 --> 00:00:25,470 Google, Google net engine host. 9 00:00:25,470 --> 00:00:28,740 Hosts refer to the Google GKE node. 10 00:00:28,740 --> 00:00:30,360 Forward to escape. 11 00:00:30,360 --> 00:00:33,600 We will use four different Linux kernel vulnerability, 12 00:00:33,600 --> 00:00:36,300 including one day and zero day we found, 13 00:00:36,300 --> 00:00:38,220 to escape from the container, 14 00:00:38,220 --> 00:00:41,310 to take over the node in GKE. 15 00:00:41,310 --> 00:00:44,610 Today's presentation will be presented by me, Billy, 16 00:00:44,610 --> 00:00:46,173 and my partner Ramdhan. 17 00:00:50,340 --> 00:00:54,240 Before going to the topic, let's introduce ourself. 18 00:00:54,240 --> 00:00:58,440 My name is Billy, a security researcher in the STAR lab. 19 00:00:58,440 --> 00:01:02,133 My partner Ramdhan, also works in the STAR lab. 20 00:01:03,000 --> 00:01:05,820 We usually work together to do research 21 00:01:05,820 --> 00:01:08,490 on the Linux kernel and Hypervisor. 22 00:01:08,490 --> 00:01:12,240 Like Virtualbox parallels for bug hunting 23 00:01:12,240 --> 00:01:13,890 and exploitation. 24 00:01:13,890 --> 00:01:18,547 We successfully Pwned Ubuntu, in Pwn2own 2021 and 2022. 25 00:01:20,046 --> 00:01:23,160 And Virtualbox in Pwn2own 2022. 26 00:01:23,160 --> 00:01:28,160 We also identified various vulnerability in Linux, 27 00:01:28,380 --> 00:01:31,470 like CVE-2021-3491 28 00:01:31,470 --> 00:01:35,761 It is a Linux kernel privilege escalation vulnerability 29 00:01:35,761 --> 00:01:38,610 in the io_uring subsystem. 30 00:01:38,610 --> 00:01:42,510 We also combined with CVE-2021-2221 31 00:01:42,510 --> 00:01:46,620 with CVE-2021-2250, 32 00:01:46,620 --> 00:01:50,370 We achieved via escape, from the Virtualbox. 33 00:01:50,370 --> 00:01:53,490 We also achieved the parallel loss via escape, 34 00:01:53,490 --> 00:01:57,753 from the CVE-2021-34854. 35 00:01:57,753 --> 00:02:00,150 This CVE shows we have some bug 36 00:02:00,150 --> 00:02:02,943 in Linux kernel and Hypervisor. 37 00:02:05,130 --> 00:02:07,260 Let's start today's outline. 38 00:02:07,260 --> 00:02:10,080 We will give you some background information, 39 00:02:10,080 --> 00:02:15,080 introduce a bit about what is Google Container-Optimize OS 40 00:02:15,690 --> 00:02:18,810 And explain kCTF VRP Challenge, 41 00:02:18,810 --> 00:02:21,120 a Google bug hunting program, 42 00:02:21,120 --> 00:02:26,040 programming focused on the container escaping exploitation. 43 00:02:26,040 --> 00:02:29,040 And then we will start showing our details 44 00:02:29,040 --> 00:02:34,040 on our first submission and it's exploitation 45 00:02:34,350 --> 00:02:37,740 we used to transform a limited primitive 46 00:02:37,740 --> 00:02:40,140 to escape from the container. 47 00:02:40,140 --> 00:02:42,663 And finally, through the conclusion. 48 00:02:45,300 --> 00:02:49,353 Google Container-Optimized OS base is a Linux OS base 49 00:02:50,227 --> 00:02:53,340 optimized for running Docker containers. 50 00:02:53,340 --> 00:02:57,810 Which is default node always in Google Kubernetes Engine. 51 00:02:57,810 --> 00:02:59,580 No packaging manager, 52 00:02:59,580 --> 00:03:02,970 unable to install third-party kernel nodules. 53 00:03:02,970 --> 00:03:05,130 Read-only root file system. 54 00:03:05,130 --> 00:03:08,190 Every time when you put, 55 00:03:08,190 --> 00:03:10,740 you always verify the file system tracer 56 00:03:10,740 --> 00:03:14,640 to measure the file system is not malformed or backdoor. 57 00:03:14,640 --> 00:03:16,860 Usually the Linux kernel configure 58 00:03:16,860 --> 00:03:19,440 are stored in the etc folder. 59 00:03:19,440 --> 00:03:22,450 In the Google Container-Optimized OS, 60 00:03:22,450 --> 00:03:25,521 this folder is writeable but stateless. 61 00:03:25,521 --> 00:03:27,892 Which means, every time it put, 62 00:03:27,892 --> 00:03:30,664 it will start from a clear slate. 63 00:03:30,664 --> 00:03:33,720 And configure is set up at run time. 64 00:03:33,720 --> 00:03:38,073 For attack install, a persistent backdoor is hard. 65 00:03:41,160 --> 00:03:43,920 If we want to escape from a container, 66 00:03:43,920 --> 00:03:45,510 there are some limits here. 67 00:03:45,510 --> 00:03:49,710 There are some obstacles when we exploit attack surface 68 00:03:49,710 --> 00:03:54,540 it uses some common exploit technique in the container. 69 00:03:54,540 --> 00:03:59,370 It disallowed unprivileged user to use eBPF, 70 00:03:59,370 --> 00:04:04,370 and that includes the userfaultfd system call. 71 00:04:04,860 --> 00:04:08,280 It disallowed to access internal networking. 72 00:04:08,280 --> 00:04:12,510 So we are unable to access Kubernetes API server. 73 00:04:12,510 --> 00:04:15,330 Also limit on device node access. 74 00:04:15,330 --> 00:04:19,443 Unable to spray tty_structure and unable to use fuse. 75 00:04:23,370 --> 00:04:26,700 Okay, there are some attack surface 76 00:04:26,700 --> 00:04:28,680 we can use in a container. 77 00:04:28,680 --> 00:04:32,010 First, we can create a new user namespace 78 00:04:32,010 --> 00:04:34,770 to explore more attack surface. 79 00:04:34,770 --> 00:04:39,090 Like Cgroup, a Linux kernel feature limited account 80 00:04:39,090 --> 00:04:41,883 for an isolate the resource usage. 81 00:04:43,050 --> 00:04:46,590 Or the Filesystem context functionality, 82 00:04:46,590 --> 00:04:48,390 or packet circuit, 83 00:04:48,390 --> 00:04:51,513 or traffic control configuration. 84 00:04:54,360 --> 00:04:58,320 In io_uring, is a Linux kernel system code, 85 00:04:58,320 --> 00:05:01,680 interface code for asynchronous IO operation. 86 00:05:01,680 --> 00:05:04,620 And there were some CVEs in this subsystem before. 87 00:05:04,620 --> 00:05:07,380 And it is reachable in our container. 88 00:05:07,380 --> 00:05:12,380 We think this is great attack surface. 89 00:05:12,792 --> 00:05:14,850 Let's see what our kCTF VRP 90 00:05:14,850 --> 00:05:18,330 environment architecture looks like. 91 00:05:18,330 --> 00:05:22,800 Basically it is a GKE cluster, has multiple nodes. 92 00:05:22,800 --> 00:05:26,130 The node you can see it is a vn 93 00:05:26,130 --> 00:05:28,710 and each node has multiple parts. 94 00:05:28,710 --> 00:05:31,440 A part you can see is a container, 95 00:05:31,440 --> 00:05:35,640 in a part you will launch a kCTF challenge. 96 00:05:35,640 --> 00:05:38,040 kCTF has two challenges. 97 00:05:38,040 --> 00:05:39,930 They are in different parts. 98 00:05:39,930 --> 00:05:42,549 Your goal is to get two flags. 99 00:05:42,549 --> 00:05:44,849 One flag is called KCTF flag 100 00:05:44,849 --> 00:05:46,680 It's place in the same part 101 00:05:46,680 --> 00:05:48,864 when you're connecting to the challenge 102 00:05:48,864 --> 00:05:52,991 and this challenge will give you nsjail bash shell. 103 00:05:52,991 --> 00:05:55,546 And another flag is called Full-Chain flag. 104 00:05:55,546 --> 00:05:58,046 It's placed on the other part. 105 00:05:59,460 --> 00:06:01,830 The node OS and the Kubernetes version 106 00:06:01,830 --> 00:06:03,840 are upgraded automatically, 107 00:06:03,840 --> 00:06:07,530 but there is a time gap between the bug build interface 108 00:06:07,530 --> 00:06:08,790 and upgrade. 109 00:06:08,790 --> 00:06:13,790 So it is allowed to use one day vulnerability, 110 00:06:13,800 --> 00:06:15,540 and we introduce before. 111 00:06:15,540 --> 00:06:19,770 All nodes are running on the Container-Optimized OS, 112 00:06:19,770 --> 00:06:21,660 Pod egress access only. 113 00:06:21,660 --> 00:06:25,530 So you can download the exploit from the internet 114 00:06:25,530 --> 00:06:26,373 and launch. 115 00:06:29,066 --> 00:06:31,323 There are two attack scenarios. 116 00:06:32,820 --> 00:06:36,210 One is breaking out of the nsjail sandbox 117 00:06:36,210 --> 00:06:37,910 and get the flag on the same part. 118 00:06:42,660 --> 00:06:46,650 Another attack scenario is to break the isolation 119 00:06:46,650 --> 00:06:48,390 that Kubernetes provides 120 00:06:48,390 --> 00:06:51,570 and access the flag from other challenge. 121 00:06:51,570 --> 00:06:53,730 But with the kernel vulnerability, 122 00:06:53,730 --> 00:06:56,910 we can literally escape privileges 123 00:06:56,910 --> 00:06:59,070 and take over the whole node. 124 00:06:59,070 --> 00:07:00,780 So you can get a whole frame 125 00:07:00,780 --> 00:07:02,943 from a single kernel vulnerability. 126 00:07:04,530 --> 00:07:08,850 And next let's show our first submission. 127 00:07:08,850 --> 00:07:13,713 And let Ramdhan to show the first two submissions. 128 00:07:19,511 --> 00:07:22,513 - Hello everyone, I'm Ramdhan. 129 00:07:22,513 --> 00:07:25,023 I will talk about our first submission. 130 00:07:25,920 --> 00:07:28,110 Our first submission is using using 131 00:07:28,110 --> 00:07:33,110 CVE-2021-4154. 132 00:07:33,810 --> 00:07:37,263 This bug is, we used to exploit kCTF container. 133 00:07:38,580 --> 00:07:40,290 This bug is use-after-free bug 134 00:07:40,290 --> 00:07:44,973 in cgroup1_parse_param function in cgroup kernel subsystem. 135 00:07:47,580 --> 00:07:52,440 So basically this bug is caused by lack of check 136 00:07:53,850 --> 00:07:55,710 in this function. 137 00:07:55,710 --> 00:07:59,250 There are source key that always need value, 138 00:07:59,250 --> 00:08:01,080 that has string type, 139 00:08:01,080 --> 00:08:03,690 but before dispatch file, 140 00:08:03,690 --> 00:08:07,020 there's no check if the value is string or not. 141 00:08:07,020 --> 00:08:11,493 So we can pass a value with another type. 142 00:08:12,930 --> 00:08:17,930 So using the fs config sys call, 143 00:08:18,120 --> 00:08:21,780 we passed our value with the file type. 144 00:08:21,780 --> 00:08:24,123 So we pass a file descriptor as a value. 145 00:08:24,123 --> 00:08:29,123 Then param string will contain file strap address. 146 00:08:29,790 --> 00:08:33,003 Then it will start in fc source. 147 00:08:36,570 --> 00:08:41,240 We can reach this bug by calling a fsconfig sys call, 148 00:08:41,240 --> 00:08:45,150 but value set the key as source, 149 00:08:45,150 --> 00:08:50,130 and we set the value with the file descriptor 150 00:08:50,130 --> 00:08:53,520 using fsconfig set after. 151 00:08:53,520 --> 00:08:54,740 So... 152 00:08:57,240 --> 00:09:00,720 the put fscontext will- 153 00:09:00,720 --> 00:09:02,250 if it calls the file descriptor, 154 00:09:02,250 --> 00:09:07,250 the put fscontext will call and it will free the fc->source 155 00:09:08,790 --> 00:09:10,533 that contain the file struct. 156 00:09:11,430 --> 00:09:14,070 But the file descriptor that associated 157 00:09:14,070 --> 00:09:17,070 with the freed file struct, still exists in the process. 158 00:09:17,070 --> 00:09:21,063 So we have use-after-free in file struct object. 159 00:09:26,280 --> 00:09:27,500 And... 160 00:09:31,470 --> 00:09:33,783 So using this bug, 161 00:09:35,303 --> 00:09:38,847 we can we can create a bunch of fc_context 162 00:09:39,780 --> 00:09:42,303 pointing to the same struct file. 163 00:09:45,282 --> 00:09:48,630 So there are multiple fc->source 164 00:09:48,630 --> 00:09:50,070 pointing to the same struct file. 165 00:09:50,070 --> 00:09:53,793 So if we close one of them, 166 00:09:57,794 --> 00:09:58,770 we have use-after-free 167 00:09:58,770 --> 00:10:03,770 and we can close another to have double free. 168 00:10:10,110 --> 00:10:10,943 Okay. 169 00:10:12,210 --> 00:10:13,527 So.. 170 00:10:16,980 --> 00:10:18,330 To.. 171 00:10:18,330 --> 00:10:19,440 Yes. 172 00:10:19,440 --> 00:10:24,440 We can free another fc_context that associated with it. 173 00:10:28,459 --> 00:10:29,292 Okay. 174 00:10:30,170 --> 00:10:35,170 We can perform double free because we have the fc_context 175 00:10:37,440 --> 00:10:39,663 still pointed to the freed struct file. 176 00:10:46,965 --> 00:10:47,798 To... 177 00:10:50,520 --> 00:10:52,650 So how to exploit this bug? 178 00:10:52,650 --> 00:10:56,010 We need to build our exploit strategy. 179 00:10:56,010 --> 00:10:57,780 In use-after-free scenario 180 00:10:57,780 --> 00:11:00,060 usually we overwrite some object 181 00:11:00,060 --> 00:11:02,850 with another type of object, 182 00:11:02,850 --> 00:11:06,993 but we have another problem, 183 00:11:09,330 --> 00:11:10,420 exploiting this bug 184 00:11:11,310 --> 00:11:13,440 because the file struct is- 185 00:11:13,440 --> 00:11:14,940 first problem is the file struct 186 00:11:14,940 --> 00:11:17,550 is allocated in their own slab cache. 187 00:11:17,550 --> 00:11:22,550 So we cannot override with another type of object 188 00:11:23,040 --> 00:11:24,480 in a common way. 189 00:11:24,480 --> 00:11:27,630 And the second problem, 190 00:11:27,630 --> 00:11:30,390 what type of object 191 00:11:30,390 --> 00:11:34,140 that we can use to extend the limit 192 00:11:34,140 --> 00:11:35,797 primitive of this bug. 193 00:11:39,870 --> 00:11:40,803 So, 194 00:11:42,390 --> 00:11:45,423 I'll present you the solution of the first problem. 195 00:11:55,050 --> 00:11:59,430 To overwrite some object with another type of object, 196 00:11:59,430 --> 00:12:01,800 that reside in different slab cache, 197 00:12:01,800 --> 00:12:06,390 we used the technique, that's called cross cache technique. 198 00:12:06,390 --> 00:12:09,250 This is the common technique 199 00:12:11,610 --> 00:12:14,910 to exploit use-after-free in Linux kernel. 200 00:12:14,910 --> 00:12:18,990 So there's two type of cross cache techniques. 201 00:12:18,990 --> 00:12:23,214 The first is cross cache use-after-free. 202 00:12:23,214 --> 00:12:26,673 And the second one is cross cache heap overflow. 203 00:12:32,670 --> 00:12:36,273 So in cross cache use-after-free, 204 00:12:38,927 --> 00:12:42,643 first we slap page freed to buddy allocator. 205 00:12:45,510 --> 00:12:48,940 So first we fill the whole slab page 206 00:12:52,507 --> 00:12:54,090 with some object. 207 00:12:54,090 --> 00:12:57,270 So for example, there's slab of object a, 208 00:12:57,270 --> 00:13:02,223 so we allocate all of object a to fill the whole slab page. 209 00:13:05,490 --> 00:13:07,353 Then we free them all. 210 00:13:09,279 --> 00:13:13,167 So the slab page will go to the buddy or page allocator. 211 00:13:14,700 --> 00:13:18,630 Then we spray another type of object 212 00:13:18,630 --> 00:13:22,920 and it will coming from the page allocator, 213 00:13:22,920 --> 00:13:26,940 and now the old freed slab cache of object a 214 00:13:26,940 --> 00:13:29,370 owned by object x slab cache. 215 00:13:29,370 --> 00:13:32,903 So using this technique 216 00:13:32,903 --> 00:13:35,670 we can solve the first problem. 217 00:13:35,670 --> 00:13:40,290 But I will present to you the another cross cache 218 00:13:40,290 --> 00:13:43,233 that's called the cross cache heap overflow. 219 00:13:44,940 --> 00:13:47,790 In cross cache heap upper flow, 220 00:13:47,790 --> 00:13:50,610 We make the target slab cache adjacent, 221 00:13:50,610 --> 00:13:52,623 next to another slab cache, 222 00:13:53,550 --> 00:13:55,380 the object that we want. 223 00:13:55,380 --> 00:14:00,047 So for example, in the right side image that we made, 224 00:14:00,047 --> 00:14:04,260 we can override the object a from the object x, 225 00:14:04,260 --> 00:14:08,760 but they are in two different slab cache. 226 00:14:08,760 --> 00:14:11,500 But it requires the sprayable object 227 00:14:12,720 --> 00:14:14,810 for both object x and object a. 228 00:14:15,900 --> 00:14:20,900 But don't expect it will be reliable most of the time 229 00:14:23,100 --> 00:14:24,393 because, 230 00:14:26,271 --> 00:14:28,930 we also need to trigger 231 00:14:30,555 --> 00:14:33,510 the heap overflow bound multiple times. 232 00:14:33,510 --> 00:14:35,910 And we can also make it more reliable 233 00:14:35,910 --> 00:14:40,230 if we have the capability to gain some information, 234 00:14:40,230 --> 00:14:43,713 if we already provided the object or not. 235 00:14:46,590 --> 00:14:50,430 So I already present you the first problem 236 00:14:50,430 --> 00:14:53,100 is that we can actually to 237 00:14:53,100 --> 00:14:56,670 override the file struct 238 00:14:56,670 --> 00:14:59,130 in our slab cache with another of object 239 00:14:59,130 --> 00:15:00,600 using the cross cache. 240 00:15:00,600 --> 00:15:03,180 And for the second problem, 241 00:15:03,180 --> 00:15:05,160 what type of object that we can use 242 00:15:05,160 --> 00:15:06,903 to extend the limited primitive. 243 00:15:09,540 --> 00:15:10,653 So, 244 00:15:11,546 --> 00:15:13,470 for the second problem I- 245 00:15:13,470 --> 00:15:15,422 as some of you already know- 246 00:15:15,422 --> 00:15:19,200 this is the msg_msg object 247 00:15:19,200 --> 00:15:21,093 and msg_msg_seg. 248 00:15:22,440 --> 00:15:23,730 This is the kernel object 249 00:15:23,730 --> 00:15:26,700 for exploiting Linux kernel bugs. 250 00:15:26,700 --> 00:15:31,620 For the future, I will refer the msg_msg as msg object, 251 00:15:31,620 --> 00:15:36,363 and msg_msgseg as msgseg object. 252 00:15:38,850 --> 00:15:40,350 So, 253 00:15:40,350 --> 00:15:45,180 this is the properties of msg object. 254 00:15:45,180 --> 00:15:47,853 So, this is the object that, 255 00:15:49,800 --> 00:15:52,620 already known for exploiting Linux kernel bug, 256 00:15:52,620 --> 00:15:57,120 because of,. especially the heap bugs, 257 00:15:57,120 --> 00:16:00,330 because of its flexibility of it's size, 258 00:16:00,330 --> 00:16:04,023 and this is the sprayable object. 259 00:16:06,090 --> 00:16:10,230 And there are the second object 260 00:16:10,230 --> 00:16:11,410 called the msgseg 261 00:16:12,330 --> 00:16:14,590 it's used to store extra message 262 00:16:19,110 --> 00:16:21,627 if the total of the message followed by the header 263 00:16:24,660 --> 00:16:27,660 with the size of hex 30. 264 00:16:27,660 --> 00:16:32,660 So if the total of object of the message is more than 4k, 265 00:16:33,453 --> 00:16:37,350 the msgseg object will use 266 00:16:37,350 --> 00:16:41,073 and it pointed by the next pointer of the msg object. 267 00:16:43,830 --> 00:16:48,830 So this is the msg object is a powerful object 268 00:16:49,110 --> 00:16:50,760 that can be used for many things, 269 00:16:50,760 --> 00:16:53,250 for example, arbitrary write 270 00:16:53,250 --> 00:16:55,503 arbitrary free, arbitrary read. 271 00:16:56,730 --> 00:17:00,653 We will go deeper with some of this. 272 00:17:00,653 --> 00:17:05,560 And it's accessible via msg get 273 00:17:06,750 --> 00:17:08,040 for a lot of thing, 274 00:17:08,040 --> 00:17:12,450 msg queue and the msg send function 275 00:17:12,450 --> 00:17:15,000 to insert the message to the queue, 276 00:17:15,000 --> 00:17:18,963 and msg retrieve, to retrieve the message from the queue. 277 00:17:25,590 --> 00:17:27,080 And... 278 00:17:29,430 --> 00:17:31,863 So, there are- 279 00:17:35,617 --> 00:17:39,117 To allocate the msg we can use the msgget. 280 00:17:41,040 --> 00:17:43,350 This is the indirect set image. 281 00:17:43,350 --> 00:17:47,940 There's a definition of some of functions for interface 282 00:17:47,940 --> 00:17:49,620 that we are going to use. 283 00:17:49,620 --> 00:17:53,246 So as you can see, 284 00:17:53,246 --> 00:17:58,246 there are the msgp parameter in the function interface, 285 00:17:58,380 --> 00:18:02,640 but it's actually defined as the msgbuf struct 286 00:18:02,640 --> 00:18:07,640 and the msg type is used for selection process. 287 00:18:09,000 --> 00:18:11,740 When we retrieve a message from the queue 288 00:18:13,170 --> 00:18:16,950 and the msg flag, 289 00:18:16,950 --> 00:18:19,500 there are some useful flag that we can use. 290 00:18:19,500 --> 00:18:22,624 For example, the msg_copy, 291 00:18:22,624 --> 00:18:25,080 this flag is, we can use if we want to 292 00:18:25,080 --> 00:18:27,030 retrieve the messages from the queue 293 00:18:27,030 --> 00:18:31,293 without deleting them from the queue. 294 00:18:35,340 --> 00:18:38,290 So there's the image 295 00:18:41,730 --> 00:18:46,730 that shows how the message links to the queue. 296 00:18:48,390 --> 00:18:51,423 For example, we allocate the message queue, 297 00:18:53,370 --> 00:18:57,580 and then we send the message with the mtype one 298 00:19:00,597 --> 00:19:03,860 and with the 4k bytes of message. 299 00:19:05,580 --> 00:19:07,360 We send to the queue 300 00:19:09,360 --> 00:19:13,980 and we have the first message insert to the msg queue. 301 00:19:13,980 --> 00:19:15,570 And there are the msgseg 302 00:19:15,570 --> 00:19:20,570 because of the total of encountered the size of msg object 303 00:19:24,360 --> 00:19:26,463 with the header is more than 4k. 304 00:19:29,190 --> 00:19:34,190 And if we try to add another msg object with the mtype two, 305 00:19:36,684 --> 00:19:41,460 and with the C of hex 200, it will be linked to the queue. 306 00:19:42,960 --> 00:19:47,610 And if we want to retrieve the second msg, 307 00:19:47,610 --> 00:19:51,990 we can use the msg except with the mtype one. 308 00:19:51,990 --> 00:19:56,990 It will share the message that doesn't have mtype one. 309 00:19:57,030 --> 00:20:02,030 So the second message 310 00:20:02,310 --> 00:20:06,993 will retrieve and print to terminal. 311 00:20:11,370 --> 00:20:15,390 So I'm gonna explain the tricks that we can use, 312 00:20:15,390 --> 00:20:16,803 using the msg object. 313 00:20:17,730 --> 00:20:22,730 So suppose using the double fee bug we have before, 314 00:20:24,332 --> 00:20:28,623 in our first submission CVE, 315 00:20:29,910 --> 00:20:34,777 we can convert this to have use-after-free on msg. 316 00:20:35,760 --> 00:20:39,930 And after we have use-after-free on msg, 317 00:20:39,930 --> 00:20:43,443 we overwrite them using the msgseg object. 318 00:20:47,460 --> 00:20:51,360 So the first trick is, we can use the msg object 319 00:20:51,360 --> 00:20:54,870 if have out of bounds read. 320 00:20:54,870 --> 00:20:59,460 We can override the mts, 321 00:20:59,460 --> 00:21:01,920 mts is message text size. 322 00:21:01,920 --> 00:21:05,010 If we override this large value, 323 00:21:05,010 --> 00:21:09,450 we can get the address leak from the out of bounds buffer 324 00:21:09,450 --> 00:21:11,373 if we have msg retrieve. 325 00:21:16,470 --> 00:21:20,820 For the second tricks, is we can do arbitrary read. 326 00:21:20,820 --> 00:21:25,820 We can do this by controlling the next pointer 327 00:21:26,760 --> 00:21:30,663 to the address that we want to leak. 328 00:21:33,480 --> 00:21:37,800 Because when we retrieve the message 329 00:21:37,800 --> 00:21:41,233 and we set the message text size to the 4K, 330 00:21:43,687 --> 00:21:47,400 it will seg to the next pointer 331 00:21:47,400 --> 00:21:50,790 because the 332 00:21:50,790 --> 00:21:55,790 kernel assumes that these messages has more than 4K size 333 00:21:55,890 --> 00:22:00,890 it will go, it will copy from the next pointer to the user 334 00:22:01,620 --> 00:22:04,263 when we do msg retrieve call. 335 00:22:09,030 --> 00:22:12,300 And so the third trick, 336 00:22:12,300 --> 00:22:17,300 is we can do by using this msg object is arbitrary free. 337 00:22:17,760 --> 00:22:19,740 We can do this if we have 338 00:22:19,740 --> 00:22:21,993 some specific kernel configuration. 339 00:22:24,150 --> 00:22:26,643 To get arbitrary free, 340 00:22:27,480 --> 00:22:32,010 we can see if we retrieve the message, it will call, 341 00:22:32,010 --> 00:22:34,380 do msg function. 342 00:22:34,380 --> 00:22:38,457 And in the end, we have called to a free msg, 343 00:22:38,457 --> 00:22:43,320 and then it will reach the security msg_msg free. 344 00:22:43,320 --> 00:22:48,320 As you see, it will call the kfree on msg security. 345 00:22:48,360 --> 00:22:51,153 And if we can control the security field, 346 00:22:52,185 --> 00:22:53,823 we have arbitrary free. 347 00:22:56,070 --> 00:22:59,712 But before we reach the free msg, 348 00:22:59,712 --> 00:23:04,590 we in control the list del, list del function, 349 00:23:04,590 --> 00:23:07,863 and need to take care of next and previous value. 350 00:23:12,330 --> 00:23:16,447 We actually can control them using the msgseg object, 351 00:23:16,447 --> 00:23:21,447 but the msgseg object cannot control the first 8 bytes, 352 00:23:24,150 --> 00:23:28,970 the first 8 bytes, So... 353 00:23:31,260 --> 00:23:35,193 if we reach the list del using, 354 00:23:38,910 --> 00:23:42,353 the msgseg, the kernel will crash. 355 00:23:44,730 --> 00:23:49,143 Because we cannot control the next pointer in the mlist, 356 00:23:51,030 --> 00:23:56,030 but we can bypass them if the kernel have 357 00:23:56,640 --> 00:23:58,953 the config the back list enabled. 358 00:24:01,140 --> 00:24:02,470 So 359 00:24:04,440 --> 00:24:08,280 If we have this config enabled 360 00:24:08,280 --> 00:24:10,653 it will call the list_del_entry_valid. 361 00:24:14,640 --> 00:24:19,623 We can easily make it return false and skip the list_del, 362 00:24:21,120 --> 00:24:26,120 by set the proof value 363 00:24:26,580 --> 00:24:28,440 with the list poison to. 364 00:24:28,440 --> 00:24:32,313 this is some constant defined in the kernel source. 365 00:24:33,390 --> 00:24:38,390 And fortunately kCTF kernel config has that field enabled. 366 00:24:38,520 --> 00:24:42,330 So we can use the security 367 00:24:42,330 --> 00:24:44,370 and the config_debug_list enabled, 368 00:24:44,370 --> 00:24:47,240 to have arbitrary free using the msg object. 369 00:24:50,790 --> 00:24:55,743 So to re wrap our three tricks, 370 00:24:56,970 --> 00:25:00,810 we can combine this to the kernel RIP control. 371 00:25:00,810 --> 00:25:02,970 So for arbitrary free, 372 00:25:02,970 --> 00:25:07,413 we can free the pipe buffer object in kmalloc 1k cache. 373 00:25:09,870 --> 00:25:13,083 This RIP buffer we can allocate using the pipes. 374 00:25:14,910 --> 00:25:19,910 So we use our first two tricks to do out of bounds read 375 00:25:20,490 --> 00:25:24,900 and arbitrary read to leak the address of pipe buffer 376 00:25:24,900 --> 00:25:25,733 in the heap. 377 00:25:25,733 --> 00:25:30,460 And we read the ops pointer 378 00:25:31,320 --> 00:25:34,773 in the pipe buffer to get the kernel text address. 379 00:25:36,630 --> 00:25:41,630 And by closing pipes and controlling the ops field, 380 00:25:42,690 --> 00:25:47,013 we can control the kernel RIP pointer. 381 00:25:49,650 --> 00:25:52,473 So we go back to our first submission, 382 00:25:53,812 --> 00:25:58,740 when we have use-after-free in struct file, 383 00:25:58,740 --> 00:26:01,233 and we develop our expert strategy. 384 00:26:04,401 --> 00:26:06,480 So with the first problem 385 00:26:06,480 --> 00:26:08,880 and the solution is we can overwrite 386 00:26:08,880 --> 00:26:11,163 the stack file with another type of object. 387 00:26:12,450 --> 00:26:14,880 We overwrite them using the msg object, 388 00:26:14,880 --> 00:26:16,413 using cross cache technique. 389 00:26:17,280 --> 00:26:21,324 And we free one of fc_context 390 00:26:21,324 --> 00:26:24,150 that is still pointed to the msg object. 391 00:26:24,150 --> 00:26:26,930 So we have use-after-free on the msg object, 392 00:26:29,130 --> 00:26:32,691 so we can reallocate them using the msg seg object. 393 00:26:32,691 --> 00:26:37,691 So we can find the msg object using the msg seg object. 394 00:26:38,730 --> 00:26:42,330 Then using this condition, 395 00:26:42,330 --> 00:26:46,687 we can perform, like our tricks before 396 00:26:48,600 --> 00:26:51,243 out-of-bound read and arbitrary read. 397 00:26:53,160 --> 00:26:57,750 So first we need to leak the address of pipe_buffer 398 00:26:57,750 --> 00:27:00,270 in kmalloc 1k. 399 00:27:00,270 --> 00:27:03,490 So we need another of msg object 400 00:27:04,980 --> 00:27:09,980 that's adjacent or near from the msg seg object. 401 00:27:13,054 --> 00:27:17,397 We allocate another msg object in kmalloc 1k 402 00:27:18,390 --> 00:27:20,293 and adjacent msg 403 00:27:22,230 --> 00:27:26,070 will have next pointer pointed to kmalloc 1k. 404 00:27:26,070 --> 00:27:28,890 And we can do out-of-bounds read 405 00:27:28,890 --> 00:27:31,683 and leak the address of kmalloc 1k. 406 00:27:34,890 --> 00:27:38,280 After we have the address of kmalloc 1k, 407 00:27:38,280 --> 00:27:40,117 we free the msg, 408 00:27:43,929 --> 00:27:45,570 msg that we talked before, 409 00:27:45,570 --> 00:27:46,620 the address, 410 00:27:46,620 --> 00:27:50,550 the msg that allocated to the kmalloc 1k. 411 00:27:50,550 --> 00:27:54,423 We allocate the spray the pipe buffer, 412 00:27:57,570 --> 00:27:58,860 the pipe, the old, 413 00:27:58,860 --> 00:28:02,970 the msg and the kmalloc 1k will be replaced 414 00:28:02,970 --> 00:28:05,070 by the pipe buffer. 415 00:28:05,070 --> 00:28:09,836 So from the address leak before from the out-of-bounds read, 416 00:28:09,836 --> 00:28:13,203 we know the location of the pipe buffer. 417 00:28:14,550 --> 00:28:18,063 Then we perform the arbitrary read on the pipe buffer, 418 00:28:19,710 --> 00:28:22,150 to know the value of the ops pointer 419 00:28:23,910 --> 00:28:26,463 to get the kernel text address. 420 00:28:29,100 --> 00:28:32,250 And then we do arbitrary free 421 00:28:32,250 --> 00:28:36,810 using our arbitrary free tricks to... 422 00:28:36,810 --> 00:28:40,263 we control the security pointed to the pipe buffer. 423 00:28:41,760 --> 00:28:46,320 And we now we have use-after-free on the pipe buffer. 424 00:28:46,320 --> 00:28:51,320 So we just reallocate them with the msg seg object. 425 00:28:51,540 --> 00:28:52,920 We have fake pipe buffer 426 00:28:52,920 --> 00:28:55,533 and control over the pipe buffer content. 427 00:28:56,520 --> 00:29:00,750 And because the pipe buffer 428 00:29:00,750 --> 00:29:03,960 will reach the pipe buffers function 429 00:29:03,960 --> 00:29:05,700 with our fake pipe buffer, 430 00:29:05,700 --> 00:29:10,080 and we have kernel control- 431 00:29:10,080 --> 00:29:11,667 control kernel repointer. 432 00:29:14,430 --> 00:29:17,670 So after we have the kernel repointer 433 00:29:17,670 --> 00:29:20,100 we need to convert this to our object. 434 00:29:20,100 --> 00:29:24,180 We can easily find the stack pivot gadget 435 00:29:24,180 --> 00:29:27,723 to convert this to ROP chain execution. 436 00:29:31,170 --> 00:29:34,140 Using commit_creds and the prepare_kernel_creds, 437 00:29:34,140 --> 00:29:38,370 we can install the root credential to the current process. 438 00:29:38,370 --> 00:29:42,808 Before our ROP chain is executed, 439 00:29:42,808 --> 00:29:45,840 we have prepared the child process. 440 00:29:45,840 --> 00:29:48,153 The child process will, 441 00:29:49,380 --> 00:29:50,970 this while loop that, 442 00:29:50,970 --> 00:29:53,550 if we already got root it it will break, 443 00:29:53,550 --> 00:29:54,813 if we already got root. 444 00:29:57,750 --> 00:30:00,960 And then after we installed the kernel, 445 00:30:00,960 --> 00:30:02,340 the root credentials, 446 00:30:02,340 --> 00:30:05,373 we copy the credentials to the child process. 447 00:30:08,970 --> 00:30:13,187 And we switched the namespace of pid 1 to the init process 448 00:30:16,890 --> 00:30:20,793 using the switch text namespace function. 449 00:30:22,530 --> 00:30:25,083 We call this using our ROP chain. 450 00:30:25,950 --> 00:30:30,420 And the child process that we prepared before 451 00:30:30,420 --> 00:30:31,890 will break the while loop, 452 00:30:31,890 --> 00:30:36,890 and it will set the namespace to the namespace in pid 1. 453 00:30:38,370 --> 00:30:43,370 And we cat the flag and spawned the root shell. 454 00:30:54,900 --> 00:30:59,073 So in this demo, we connect to the kCTF instance. 455 00:31:01,263 --> 00:31:03,150 We download our exploit to the internal 456 00:31:03,150 --> 00:31:04,500 and run the exploit 457 00:31:04,500 --> 00:31:06,600 and cat their flag will be printed 458 00:31:06,600 --> 00:31:08,403 and it spawned the root shell. 459 00:31:11,713 --> 00:31:14,880 (audience applauding) 460 00:31:21,960 --> 00:31:25,980 So now I will talk about our second submission. 461 00:31:25,980 --> 00:31:27,870 For the second submission. 462 00:31:27,870 --> 00:31:29,373 We use CVE-2021- 463 00:31:33,730 --> 00:31:35,460 22600 to exploit the kCTF. 464 00:31:35,460 --> 00:31:38,670 This is double free bug in packet_set_ring function, 465 00:31:38,670 --> 00:31:40,833 in the af_packet kernel subsystem. 466 00:31:42,840 --> 00:31:46,920 So this is the snippet code to trigger double free. 467 00:31:46,920 --> 00:31:50,310 I will explain this bug code one by one. 468 00:31:50,310 --> 00:31:52,863 The root cause of this bug is, 469 00:31:54,000 --> 00:31:59,000 happens when we switch version from the version 3 to 2, 470 00:31:59,730 --> 00:32:04,230 but there's some field, because of the bug, 471 00:32:04,230 --> 00:32:06,030 There's some field that didn't clear 472 00:32:09,140 --> 00:32:11,640 if we change the version three to two. 473 00:32:11,640 --> 00:32:14,223 So there's some old set that didn't clear. 474 00:32:16,380 --> 00:32:21,093 So first we create the af_packet socket. 475 00:32:22,830 --> 00:32:26,420 We set the version to version 3 by calling setsockopt. 476 00:32:28,866 --> 00:32:30,970 The TP version variable 477 00:32:33,330 --> 00:32:37,923 will assign to the TP version. 478 00:32:39,360 --> 00:32:42,720 And we call the setsockopt 479 00:32:42,720 --> 00:32:47,720 with packet_rx_ring option. 480 00:32:47,850 --> 00:32:50,403 It will allocate a variable called pg_vec. 481 00:32:51,270 --> 00:32:52,479 As you can see, 482 00:32:52,479 --> 00:32:54,930 we can control the size of allocation 483 00:32:54,930 --> 00:32:56,280 by setting the tp_block_nr. 484 00:33:00,540 --> 00:33:04,950 So the allocated the pg_vec 485 00:33:04,950 --> 00:33:08,190 is stored in pkbdq, 486 00:33:08,190 --> 00:33:11,010 but it overlaps with the rx_owner_map 487 00:33:11,010 --> 00:33:14,313 because of the union data type. 488 00:33:19,090 --> 00:33:24,090 And then from the third setsockopt, we free the pg_vec, 489 00:33:24,159 --> 00:33:29,159 but it didn't clear the pkbdq. 490 00:33:36,180 --> 00:33:39,390 Now, we changed the version to the version 2 491 00:33:39,390 --> 00:33:43,473 by performing setsockopt again. 492 00:33:46,315 --> 00:33:48,587 And when we call the packet_set_ring, 493 00:33:49,423 --> 00:33:52,023 rx_owner_map that's actually coming from the old set 494 00:33:55,080 --> 00:33:55,980 is read. 495 00:33:55,980 --> 00:34:00,630 So we read the pg_vec of pkbdq twice. 496 00:34:00,630 --> 00:34:03,090 So the rx_owner_map is upper limit, 497 00:34:03,090 --> 00:34:05,730 because it's upper limit with the pkbdq. 498 00:34:05,730 --> 00:34:09,090 And it didn't clear from the version 3, 499 00:34:09,090 --> 00:34:11,070 and in the version 2, it will be free. 500 00:34:11,070 --> 00:34:13,563 So we have double free. 501 00:34:17,040 --> 00:34:19,503 So we can control the- 502 00:34:20,970 --> 00:34:23,370 in this block we can control the target chunk size 503 00:34:23,370 --> 00:34:26,403 and we can control when to double free. 504 00:34:32,880 --> 00:34:37,230 So we choose the timerfd object as a sprayable object 505 00:34:37,230 --> 00:34:38,733 to fill the whole slab page. 506 00:34:42,570 --> 00:34:45,002 Using cross cache technique, 507 00:34:45,002 --> 00:34:50,002 we free our timerfd and the pg_vec to make slab page 508 00:34:50,040 --> 00:34:52,163 insert to page allocator. 509 00:34:53,490 --> 00:34:58,490 And then we spray with the msg object. 510 00:35:00,870 --> 00:35:02,403 And using the double free, 511 00:35:03,630 --> 00:35:05,370 we free the msg object 512 00:35:05,370 --> 00:35:08,523 and overwrite them them with the msgseg object. 513 00:35:09,360 --> 00:35:12,483 So we can control over the msg object. 514 00:35:18,920 --> 00:35:21,060 In this condition, 515 00:35:21,060 --> 00:35:26,060 We have the same case as the previous submission, 516 00:35:26,280 --> 00:35:30,130 our previous exploit that we have use-after-free on msg 517 00:35:31,560 --> 00:35:34,590 and reallocate them using the msgseg. 518 00:35:34,590 --> 00:35:36,630 We can just do the same technique. 519 00:35:36,630 --> 00:35:38,550 Plus we do at out-of-bounds read 520 00:35:38,550 --> 00:35:43,550 to leak the address of pipe_buffer on kmalloc 1k. 521 00:35:43,560 --> 00:35:47,828 And we do arbitrary read to leak the kernel text address. 522 00:35:47,828 --> 00:35:51,330 Then we do arbitrary free on the pipe_buffer. 523 00:35:51,330 --> 00:35:52,770 We overwrite the- 524 00:35:52,770 --> 00:35:56,630 and then we overwrite the pipe_buffer using the msgseg. 525 00:35:56,630 --> 00:36:00,660 Then we can close the pipes and control kernel RIP pointer, 526 00:36:00,660 --> 00:36:02,913 and we can escape the container. 527 00:36:04,980 --> 00:36:08,493 So this is the demo of our second submission. 528 00:36:11,250 --> 00:36:16,250 We download, we connect the kCTF and run our exploit. 529 00:36:16,380 --> 00:36:19,323 The kCTF will print it and spawn root shell. 530 00:36:22,413 --> 00:36:25,580 (audience applauding) 531 00:36:27,810 --> 00:36:31,530 For the third and fourth submission, 532 00:36:31,530 --> 00:36:32,703 my friend, Billy, 533 00:36:33,540 --> 00:36:37,710 will explain the third and fourth submission. 534 00:36:37,710 --> 00:36:38,543 Thank you. 535 00:36:39,401 --> 00:36:42,568 (audience applauding) 536 00:36:46,290 --> 00:36:50,580 - So let me talk to the next two submissions. 537 00:36:50,580 --> 00:36:54,376 One is CVE-2022-0185, 538 00:36:54,376 --> 00:36:56,961 it's the first time we used 0day 539 00:36:56,961 --> 00:36:59,722 but unfortunately we didn't properly report it 540 00:36:59,722 --> 00:37:03,093 to the Linux security team after the kCTF submission. 541 00:37:04,140 --> 00:37:04,973 Here is a description of the CVE. 542 00:37:04,973 --> 00:37:09,060 We highlight the keywords we care about- 543 00:37:09,060 --> 00:37:10,890 Heap based buffer overflow. 544 00:37:10,890 --> 00:37:15,890 But ability is placed as a filesystem context sub system. 545 00:37:15,900 --> 00:37:19,200 In case of unprivileged user namespaces, 546 00:37:19,200 --> 00:37:21,363 we can trigger the vulnerability. 547 00:37:23,880 --> 00:37:24,990 Briefly speaking, 548 00:37:24,990 --> 00:37:28,920 there is an integer underflow when boundary tracking. 549 00:37:28,920 --> 00:37:33,630 So if we let the size module and the page_size minus two, 550 00:37:33,630 --> 00:37:35,253 it will cause integer underflow. 551 00:37:36,369 --> 00:37:39,600 And in the following four places, will cause heap overflow 552 00:37:39,600 --> 00:37:41,923 on the the legacy data buffer. 553 00:37:44,220 --> 00:37:48,990 We carefully open data in the legacy data buffer, 554 00:37:48,990 --> 00:37:52,350 and cause heap overflow with one little byte. 555 00:37:52,350 --> 00:37:55,053 We treat this vulnerability as off-by-one. 556 00:37:57,405 --> 00:38:00,560 From the call legacy_data 557 00:38:00,560 --> 00:38:03,240 it is in a kmalloc-4k. 558 00:38:03,240 --> 00:38:06,810 So in summary, this vulnerability is off-by-one 559 00:38:06,810 --> 00:38:08,943 on the kmalloc-4k cache. 560 00:38:10,980 --> 00:38:13,110 We use cross cache heap overflow 561 00:38:13,110 --> 00:38:16,230 in order to overwrite the message structure, 562 00:38:16,230 --> 00:38:19,157 spray legacy_data buffer with message structure 563 00:38:19,157 --> 00:38:20,610 at the same time. 564 00:38:20,610 --> 00:38:25,431 Trigger off-by-one vulnerability on every legacy_data 565 00:38:25,431 --> 00:38:28,107 and it will have allowed change to overwrite 566 00:38:28,107 --> 00:38:31,393 the message list next last byte with zero. 567 00:38:33,729 --> 00:38:38,729 If we are lucky to overwrite message next last byte with 0, 568 00:38:39,330 --> 00:38:42,417 we can make the two messages point to the same next. 569 00:38:47,892 --> 00:38:50,030 Free it through the one message queue 570 00:38:50,030 --> 00:38:51,600 and another message queue 571 00:38:51,600 --> 00:38:54,213 will still point to the free chunk. 572 00:38:57,570 --> 00:39:00,930 And at this point we have made the same situation 573 00:39:00,930 --> 00:39:03,129 as the previous submission. 574 00:39:03,129 --> 00:39:06,690 Through OOB reading pipe buffer address 575 00:39:06,690 --> 00:39:11,250 and through arbitrary read to leak kernel past address. 576 00:39:11,250 --> 00:39:15,090 Next is to do arbitrary free and pipe buffer overwrite 577 00:39:15,090 --> 00:39:16,980 with message segment. 578 00:39:16,980 --> 00:39:21,093 Cross cache to control the kernel RIP for escape container. 579 00:39:22,560 --> 00:39:24,870 There is our demo. 580 00:39:24,870 --> 00:39:26,590 We've connected to the challenge 581 00:39:27,643 --> 00:39:29,790 and get exploit from internal and launch 582 00:39:29,790 --> 00:39:32,673 with the server get fail and take over node. 583 00:39:40,072 --> 00:39:43,239 (audience applauding) 584 00:39:48,060 --> 00:39:51,360 There is a secondary way we use in the kCTF for, 585 00:39:51,360 --> 00:39:53,217 and this time we properly reported 586 00:39:53,217 --> 00:39:57,210 to the Linux kernel security, and get credit. 587 00:39:57,210 --> 00:39:59,700 Here is a description of our CVE. 588 00:39:59,700 --> 00:40:02,430 We also highlight the keyword we care about. 589 00:40:02,430 --> 00:40:05,750 Here is heap corruption in the io_uring. 590 00:40:05,750 --> 00:40:07,923 It is reachable in a container. 591 00:40:09,330 --> 00:40:11,580 This vulnerability is in the io_uring 592 00:40:11,580 --> 00:40:15,620 when request a same message of receive message operation. 593 00:40:15,620 --> 00:40:19,740 It will grab fs structure return before two operation, 594 00:40:19,740 --> 00:40:23,820 but if io_uring contents has io_uring same as before, 595 00:40:23,820 --> 00:40:26,730 he forgot to release the fs structure 596 00:40:26,730 --> 00:40:29,010 when finished the operation. 597 00:40:30,670 --> 00:40:33,210 So we will keep increase the users, 598 00:40:33,210 --> 00:40:34,980 it will cause integer overflow 599 00:40:34,980 --> 00:40:37,863 and none of the users reach the rule again. 600 00:40:40,860 --> 00:40:43,190 When fs structure reaches rule again, 601 00:40:43,190 --> 00:40:45,353 we use another io_uring with other io_urings 602 00:40:46,495 --> 00:40:47,460 that are io pool. 603 00:40:47,460 --> 00:40:50,850 It will free the fs structure after finishing the request, 604 00:40:50,850 --> 00:40:55,850 so we can have a free fs structure as current fs in use. 605 00:40:59,010 --> 00:41:01,680 The key point about cross-cache is allocate a lot 606 00:41:01,680 --> 00:41:03,210 and free up at the same time. 607 00:41:03,210 --> 00:41:05,640 So we allocate a lot of fs structure 608 00:41:05,640 --> 00:41:10,640 and free up, spray kmalloc-128 message segment 609 00:41:10,823 --> 00:41:14,493 to reallocate current fs as message segment. 610 00:41:16,320 --> 00:41:18,420 and then free the current fs again 611 00:41:18,420 --> 00:41:22,060 by io_uring and cross-cache again with kmalloc 612 00:41:23,370 --> 00:41:25,083 64 message segment. 613 00:41:27,420 --> 00:41:29,730 Since it is still message segment, 614 00:41:29,730 --> 00:41:32,850 so we use message receive system call 615 00:41:32,850 --> 00:41:37,560 to leak the next message to get the kernel address 616 00:41:37,560 --> 00:41:38,733 in kmalloc-1024. 617 00:41:41,816 --> 00:41:44,700 Once we have leaked heap address, 618 00:41:44,700 --> 00:41:49,590 we can multiply contents by free allocate again. 619 00:41:49,590 --> 00:41:52,087 We can use it to forge the fs structure 620 00:41:52,087 --> 00:41:55,923 to do arbitrary read in order to leak kernel address. 621 00:41:57,660 --> 00:42:01,440 With our fake fs structure, we are able to arbitrary read 622 00:42:01,440 --> 00:42:05,073 by getcwd system call. 623 00:42:06,480 --> 00:42:08,430 After we get the kernel address, 624 00:42:08,430 --> 00:42:13,430 we can prepare our ROP payload and forge fs structure again. 625 00:42:13,890 --> 00:42:16,238 By system call fchange directory, 626 00:42:16,238 --> 00:42:18,265 we can control the kernel RIP 627 00:42:18,265 --> 00:42:22,265 from fchange directory to set_fs_pwd to path_put 628 00:42:23,113 --> 00:42:26,953 to dput and in the end to a retain_dentry. 629 00:42:26,953 --> 00:42:31,230 In the retain_dentry we can control kernel RIP 630 00:42:31,230 --> 00:42:33,303 when calling function point d_delete. 631 00:42:36,098 --> 00:42:37,230 There is our demo. 632 00:42:37,230 --> 00:42:41,280 Original demo video near about 15 minute to finish. 633 00:42:41,280 --> 00:42:43,380 So I speed up for presentation. 634 00:42:43,380 --> 00:42:45,921 Again, connecting to the challenge 635 00:42:45,921 --> 00:42:48,243 and get exploit from internal and launch. 636 00:42:53,250 --> 00:42:56,253 With a sever get to flag and take the GKE node. 637 00:42:57,576 --> 00:43:00,743 (audience applauding) 638 00:43:04,830 --> 00:43:08,760 All vulnerability we use have already fixed in GKE. 639 00:43:08,760 --> 00:43:10,677 You can see the reference to 640 00:43:10,677 --> 00:43:15,677 the Google Security Bulletin GCP-2022-002 641 00:43:15,900 --> 00:43:17,703 and GCP-2022-016. 642 00:43:19,984 --> 00:43:22,890 We believe that with cross-cache attack with message 643 00:43:22,890 --> 00:43:26,760 we can transform a limited primitive to arbitrary read, 644 00:43:26,760 --> 00:43:29,370 arbitrary free to escape to the container. 645 00:43:29,370 --> 00:43:30,600 But there is a limit here, 646 00:43:30,600 --> 00:43:34,020 we can only allocate size under 4096. 647 00:43:37,740 --> 00:43:41,160 In our last CVE, in our last submission 648 00:43:41,160 --> 00:43:44,974 we were able to convert UAF through the common situation 649 00:43:44,974 --> 00:43:49,530 and a previous submitted CVEs, but with some change. 650 00:43:49,530 --> 00:43:53,580 We still can escape container by cross-cache and message. 651 00:43:53,580 --> 00:43:57,928 As a result, we are awarded more than $100,000+ bounty 652 00:43:57,928 --> 00:44:00,808 from the Google kCTF VRP program. 653 00:44:00,808 --> 00:44:03,975 (audience applauding) 654 00:44:07,390 --> 00:44:10,782 Thank Google for hosting such a great VIP program 655 00:44:10,782 --> 00:44:14,397 to secure the kCTF and GKE infrastructure. 656 00:44:17,340 --> 00:44:18,663 Here is our references. 657 00:44:20,910 --> 00:44:22,241 And thank you. 658 00:44:22,241 --> 00:44:25,408 (audience applauding)