1 00:00:00,570 --> 00:00:04,893 - The COW Who Escaped The Silo, by Eren Segal. 2 00:00:05,820 --> 00:00:08,910 Since it is this speaker's first talk, 3 00:00:08,910 --> 00:00:10,980 we are going to do the DEFCON tradition. 4 00:00:10,980 --> 00:00:13,230 But before we do that, I have two announcements. 5 00:00:13,230 --> 00:00:14,820 Number one, if you're sitting, 6 00:00:14,820 --> 00:00:18,057 please wear your masks, it's required. 7 00:00:18,057 --> 00:00:21,480 And the second announcement is please don't loiter, 8 00:00:21,480 --> 00:00:24,360 or sit along the walls or the back. 9 00:00:24,360 --> 00:00:25,410 Just find yourself a seat, 10 00:00:25,410 --> 00:00:29,130 come on down, come a little closer, and enjoy the show. 11 00:00:29,130 --> 00:00:29,963 All right. 12 00:00:39,036 --> 00:00:42,203 (audience applauding) 13 00:00:46,950 --> 00:00:48,960 - Welcome to my talk, 14 00:00:48,960 --> 00:00:51,843 The Container On Windows Who Escaped The Silo. 15 00:00:52,940 --> 00:00:55,080 In this talk, I'll demonstrate 16 00:00:55,080 --> 00:00:57,960 a malicious Windows container image 17 00:00:57,960 --> 00:01:00,783 can impact the OS it is running on. 18 00:01:02,460 --> 00:01:03,790 My name is Eren Segal 19 00:01:04,650 --> 00:01:08,970 I have been in the cybersecurity field for over seven years. 20 00:01:08,970 --> 00:01:12,750 Currently, I'm working as research team lead 21 00:01:12,750 --> 00:01:14,193 in SafeBreach Labs. 22 00:01:15,300 --> 00:01:17,220 My experience involved research 23 00:01:17,220 --> 00:01:19,473 on Windows and embedded devices. 24 00:01:21,660 --> 00:01:23,460 I'll start with the background 25 00:01:23,460 --> 00:01:26,460 of Windows process isolated containers. 26 00:01:26,460 --> 00:01:29,880 Then I'll continue with how to gain NTsystem 27 00:01:29,880 --> 00:01:31,323 inside of the container. 28 00:01:32,580 --> 00:01:34,695 After we gain NTsystem, 29 00:01:34,695 --> 00:01:36,210 I'll explain the method they use, 30 00:01:36,210 --> 00:01:38,550 in order to find two vulnerabilities 31 00:01:38,550 --> 00:01:40,860 that can impact the host. 32 00:01:40,860 --> 00:01:44,730 And then we'll talk about them and show a quick demo, 33 00:01:44,730 --> 00:01:46,803 and we'll finish with Q&A session. 34 00:01:48,480 --> 00:01:52,650 So the goal is to find the impact of an attacker-crafted 35 00:01:52,650 --> 00:01:56,610 Windows container on the host it is running on. 36 00:01:56,610 --> 00:02:00,033 I chose this research because containers are everywhere. 37 00:02:01,170 --> 00:02:04,170 This attack vector, of a malicious Windows container, 38 00:02:04,170 --> 00:02:06,150 is a real world one, 39 00:02:06,150 --> 00:02:09,393 and reverse engineering Windows kernel is fun. 40 00:02:10,920 --> 00:02:14,583 So let's deep dive into Windows containers. 41 00:02:15,582 --> 00:02:19,170 Containers are similar to virtual machines. 42 00:02:19,170 --> 00:02:23,160 Each container is created from a container image, 43 00:02:23,160 --> 00:02:26,700 which contains all the dependencies of the container. 44 00:02:26,700 --> 00:02:30,450 For example, the application that the container will run, 45 00:02:30,450 --> 00:02:34,800 the file system, or its configuration, registry, 46 00:02:34,800 --> 00:02:37,020 and even permissions. 47 00:02:37,020 --> 00:02:40,290 The container image contains all the dependencies, 48 00:02:40,290 --> 00:02:44,853 therefore it is easy to manage and use it. 49 00:02:46,230 --> 00:02:48,150 And just like virtual machines, 50 00:02:48,150 --> 00:02:53,150 containers are also isolated from the host, 51 00:02:53,460 --> 00:02:56,040 in order to validate 52 00:02:56,040 --> 00:02:58,533 that the container won't be able to impact it. 53 00:02:59,970 --> 00:03:04,950 Windows containers can be deployed in two modes: 54 00:03:04,950 --> 00:03:08,490 process isolated and Hyper-V isolation, 55 00:03:08,490 --> 00:03:13,490 which defines isolation that they will be executed on. 56 00:03:15,420 --> 00:03:19,470 Hyper-V containers are very similar to virtual machines. 57 00:03:19,470 --> 00:03:21,903 Each container have its own kernel. 58 00:03:22,830 --> 00:03:26,130 The Hyper-V containers can't interact directly 59 00:03:26,130 --> 00:03:30,270 with the host kernel, which means that they're more secure, 60 00:03:30,270 --> 00:03:33,183 but it comes with computational overhead. 61 00:03:35,310 --> 00:03:40,310 Process isolated containers are similar to Linux containers. 62 00:03:40,350 --> 00:03:43,443 The entire container runs from the user mode. 63 00:03:44,340 --> 00:03:48,540 Process isolated containers interact with the host kernel, 64 00:03:48,540 --> 00:03:51,540 but the container is isolated from the host 65 00:03:51,540 --> 00:03:53,490 via multiple aspects, 66 00:03:53,490 --> 00:03:57,603 which we will focus and talk about them in the next slides. 67 00:03:58,590 --> 00:04:01,230 The goal of the isolation is, prevent the container 68 00:04:01,230 --> 00:04:04,080 from being able to impact the host. 69 00:04:04,080 --> 00:04:06,360 And because the kernel is shown 70 00:04:06,360 --> 00:04:10,083 between the container and the host, 71 00:04:10,083 --> 00:04:13,980 some validations were added to the kernel 72 00:04:13,980 --> 00:04:17,880 to block a container from doing activities 73 00:04:17,880 --> 00:04:20,223 that can impact the host. 74 00:04:21,192 --> 00:04:22,470 In this presentation, 75 00:04:22,470 --> 00:04:25,863 I'll focus only on process isolated containers. 76 00:04:27,510 --> 00:04:30,630 When running task lists inside Windows container, 77 00:04:30,630 --> 00:04:32,880 we'll see lots of system processes, 78 00:04:32,880 --> 00:04:35,373 which are related to the OS itself, 79 00:04:36,210 --> 00:04:38,010 unlike Linux containers, 80 00:04:38,010 --> 00:04:42,000 which doesn't contain any system processes inside of it. 81 00:04:42,000 --> 00:04:44,220 And the reason lines the differences 82 00:04:44,220 --> 00:04:47,130 between Linux kernel architecture 83 00:04:47,130 --> 00:04:48,813 and Windows kernel architecture. 84 00:04:50,370 --> 00:04:52,440 Both Linux and Windows containers 85 00:04:52,440 --> 00:04:54,330 are running from the user mode only, 86 00:04:54,330 --> 00:04:55,710 in order to validate 87 00:04:55,710 --> 00:04:59,130 that they won't be able to impact the host. 88 00:04:59,130 --> 00:05:01,320 Linux kernel is monolithic. 89 00:05:01,320 --> 00:05:03,750 Therefore, all its basic functionality 90 00:05:03,750 --> 00:05:05,910 is implemented in the kernel, 91 00:05:05,910 --> 00:05:09,390 unlike Windows, which some of its functionality 92 00:05:09,390 --> 00:05:13,353 is implemented in the user mode while other in the kernel. 93 00:05:14,280 --> 00:05:18,180 Therefore Windows containers contain system services 94 00:05:18,180 --> 00:05:19,863 such as SVC host. 95 00:05:21,900 --> 00:05:23,310 So let's deep dive 96 00:05:23,310 --> 00:05:27,273 into how process isolated containers are implemented. 97 00:05:29,782 --> 00:05:33,720 There are two parts for Windows containers, 98 00:05:33,720 --> 00:05:38,070 the engine, which manage all the containers, loads them, 99 00:05:38,070 --> 00:05:40,590 as you might know, Docker engine. 100 00:05:40,590 --> 00:05:45,270 And the second part of the operating system of the Windows, 101 00:05:45,270 --> 00:05:48,090 which are responsible for the isolation 102 00:05:48,090 --> 00:05:50,757 of the container from the host. 103 00:05:50,757 --> 00:05:54,033 And we will focus only on the Windows part. 104 00:05:55,230 --> 00:05:58,140 When a new Windows container begins, 105 00:05:58,140 --> 00:06:01,650 it creates an environment required for the container. 106 00:06:01,650 --> 00:06:04,710 For example, the file system of the container, 107 00:06:04,710 --> 00:06:08,460 object namespace, job object, and of course, 108 00:06:08,460 --> 00:06:11,943 the processes that are going to run inside of it. 109 00:06:13,920 --> 00:06:18,240 Windows container isolation is separated into three parts, 110 00:06:18,240 --> 00:06:22,136 job objects, namespaces, and layers. 111 00:06:22,136 --> 00:06:26,550 I'm going to focus on bypass the kernel isolation 112 00:06:26,550 --> 00:06:27,903 of the job objects. 113 00:06:28,980 --> 00:06:33,210 So let's focus on, what are job objects? 114 00:06:33,210 --> 00:06:37,200 Job objects were created in Windows a long, long time ago 115 00:06:37,200 --> 00:06:42,180 to group processes as units and manage the resources. 116 00:06:42,180 --> 00:06:47,180 For example, manage the CPU time, memory limits, and so on. 117 00:06:48,720 --> 00:06:52,050 But in order to support isolation as well, 118 00:06:52,050 --> 00:06:55,563 the job object is required to be converted into silo. 119 00:06:57,000 --> 00:07:00,150 Silo object provide basic isolation, 120 00:07:00,150 --> 00:07:02,790 but it is not enough for containers, 121 00:07:02,790 --> 00:07:04,860 which require much more. 122 00:07:04,860 --> 00:07:08,550 So in order for a silo to have all the capabilities 123 00:07:08,550 --> 00:07:10,740 required to support containers, 124 00:07:10,740 --> 00:07:14,163 it must be converted into server silo. 125 00:07:15,000 --> 00:07:18,063 So any server silo is also a silo. 126 00:07:19,650 --> 00:07:23,130 After we converted our silo into server silo, 127 00:07:23,130 --> 00:07:26,250 which support redirection of resources, 128 00:07:26,250 --> 00:07:28,470 now we can use the process- 129 00:07:28,470 --> 00:07:31,020 now the processes inside of the container 130 00:07:31,020 --> 00:07:34,950 can use object manager, registry, network stack, 131 00:07:34,950 --> 00:07:37,620 that were loaded from the container image 132 00:07:37,620 --> 00:07:39,093 and not from the host. 133 00:07:41,130 --> 00:07:44,187 But this isolation is not enough, 134 00:07:44,187 --> 00:07:48,822 because the container can interact directly with the kernel. 135 00:07:48,822 --> 00:07:53,400 So some validations is required to be added 136 00:07:53,400 --> 00:07:55,200 in the kernel itself. 137 00:07:55,200 --> 00:07:59,373 So let's understand how the kernel block dangerous syscalls. 138 00:08:01,410 --> 00:08:06,117 So if a container does dangerous syscalls, 139 00:08:07,080 --> 00:08:11,403 for example, loading driver that can impact the host, 140 00:08:14,224 --> 00:08:17,700 the kernel won't allow this activity. 141 00:08:17,700 --> 00:08:21,060 And as you can see in the slide, it's validated 142 00:08:21,060 --> 00:08:25,500 if a process, the thread that did the syscall 143 00:08:25,500 --> 00:08:27,243 is inside server silo, 144 00:08:28,950 --> 00:08:31,803 which means that it is inside of a container. 145 00:08:33,090 --> 00:08:36,450 Let's deep dive into how it detect that. 146 00:08:36,450 --> 00:08:37,923 When the kernel need to detect 147 00:08:37,923 --> 00:08:42,600 that the current process is isolated, as a container, 148 00:08:42,600 --> 00:08:44,700 it checks for server silo, 149 00:08:44,700 --> 00:08:49,293 all silo in the ETHREAD or EPROCESS structs, 150 00:08:49,293 --> 00:08:51,657 which are the structs that represent 151 00:08:51,657 --> 00:08:54,427 the process and threads. 152 00:08:54,427 --> 00:08:57,643 The kernel need to check all the job objects, 153 00:08:57,643 --> 00:09:01,375 which attach to the thread or the process, 154 00:09:01,375 --> 00:09:05,256 because it is possible to attach multiple job objects 155 00:09:05,256 --> 00:09:08,339 to a single thread or process struct. 156 00:09:09,870 --> 00:09:12,240 Another example of a flow in the kernel, 157 00:09:12,240 --> 00:09:14,793 which required to validate if the process 158 00:09:14,793 --> 00:09:17,460 is inside of the container or not, 159 00:09:17,460 --> 00:09:20,160 is a flow of the process list. 160 00:09:20,160 --> 00:09:24,090 In this flow, the kernel just skips the processes 161 00:09:24,090 --> 00:09:26,760 that are outside of the container. 162 00:09:26,760 --> 00:09:28,110 And because of that, 163 00:09:28,110 --> 00:09:30,660 when a process inside of the container 164 00:09:30,660 --> 00:09:32,910 queries for all the process list, 165 00:09:32,910 --> 00:09:36,993 it gets only the processes that are inside of the container. 166 00:09:40,080 --> 00:09:44,190 So before we try to break out of the container, 167 00:09:44,190 --> 00:09:48,393 we need to know if we are running inside of the container. 168 00:09:49,380 --> 00:09:51,630 Using a single task list command, 169 00:09:51,630 --> 00:09:53,310 I'll show you how to detect 170 00:09:53,310 --> 00:09:56,910 if we are running inside of the container 171 00:09:56,910 --> 00:10:00,693 and with which isolation method we are using. 172 00:10:08,430 --> 00:10:11,520 It is possible to detect that the process is running 173 00:10:11,520 --> 00:10:15,480 from Hyper-V container by listing all the processes 174 00:10:15,480 --> 00:10:20,480 and checking: if the process CExecSVC exists, 175 00:10:21,000 --> 00:10:24,540 Dockerd must not exist on the task list, 176 00:10:24,540 --> 00:10:28,293 and CExecSVC must run from session one. 177 00:10:30,570 --> 00:10:32,840 Similar to Hyper-V isolation, 178 00:10:32,840 --> 00:10:35,910 it is possible to detect process isolated containers 179 00:10:35,910 --> 00:10:39,960 with all the first condition. 180 00:10:39,960 --> 00:10:42,660 But the last one, the third, 181 00:10:42,660 --> 00:10:46,653 the session ID of CExecSVC must not be one. 182 00:10:48,630 --> 00:10:50,670 So after we understood 183 00:10:50,670 --> 00:10:53,313 that we are running inside of the container, 184 00:10:54,210 --> 00:10:57,393 let's detect if we are totally isolated from it. 185 00:10:58,410 --> 00:10:59,790 When I began my research, 186 00:10:59,790 --> 00:11:01,860 I found couple of indications 187 00:11:01,860 --> 00:11:06,030 that containers aren't that isolated from the host. 188 00:11:06,030 --> 00:11:08,070 This methods are trivial, 189 00:11:08,070 --> 00:11:10,413 but important for our understanding. 190 00:11:12,101 --> 00:11:14,880 The process IDs inside of the container 191 00:11:14,880 --> 00:11:17,283 and outside of the container are the same. 192 00:11:18,189 --> 00:11:23,189 In the slide, you can see that the PID of CExecSVC 193 00:11:23,640 --> 00:11:25,290 inside of the container 194 00:11:25,290 --> 00:11:28,053 is the same as outside of the container. 195 00:11:29,670 --> 00:11:32,910 When looking and comparing all the other ones, 196 00:11:32,910 --> 00:11:34,683 we will see that they are same. 197 00:11:35,670 --> 00:11:38,250 I guess it can lead us to side channel attack 198 00:11:38,250 --> 00:11:41,520 between two containers by knowing the IDs, 199 00:11:41,520 --> 00:11:43,980 but it is doesn't valuable enough. 200 00:11:43,980 --> 00:11:46,260 I want much more. 201 00:11:46,260 --> 00:11:48,630 So I continue to research. 202 00:11:48,630 --> 00:11:51,873 When running a container as container user, 203 00:11:52,860 --> 00:11:54,840 I noticed that Process Explorer, 204 00:11:54,840 --> 00:11:57,630 which running outside of the container, 205 00:11:57,630 --> 00:12:01,260 doesn't detect the user, container user, 206 00:12:01,260 --> 00:12:05,310 but it did detect all the other system processes 207 00:12:05,310 --> 00:12:08,550 that are running inside of the container, 208 00:12:08,550 --> 00:12:10,890 which raise the question, 209 00:12:10,890 --> 00:12:15,120 why we have system processes inside of the container? 210 00:12:15,120 --> 00:12:18,930 And do they have the same permissions 211 00:12:18,930 --> 00:12:22,923 as system processes outside of the container? 212 00:12:25,260 --> 00:12:30,260 So basically, system processes inside of the container 213 00:12:31,770 --> 00:12:34,260 have almost the same permissions, 214 00:12:34,260 --> 00:12:38,733 but if there are isolation checks, as I showed you before, 215 00:12:40,710 --> 00:12:41,640 we can't do that. 216 00:12:41,640 --> 00:12:44,613 So we need to find a way to bypass that. 217 00:12:45,660 --> 00:12:50,660 So before we jump to how to escape the container, 218 00:12:50,760 --> 00:12:52,923 let's gain system permissions. 219 00:12:55,440 --> 00:12:57,330 When running Docker run command 220 00:12:57,330 --> 00:13:00,723 with the user flag of container user, which is a weak user, 221 00:13:01,890 --> 00:13:05,550 I would've expected we will run only container user, 222 00:13:05,550 --> 00:13:08,040 which, weak processes. 223 00:13:08,040 --> 00:13:09,930 But if you see the boot process, 224 00:13:09,930 --> 00:13:12,120 lots of system processes are starting 225 00:13:12,120 --> 00:13:13,533 from the container image. 226 00:13:14,490 --> 00:13:18,360 The only process running as the user we defined 227 00:13:18,360 --> 00:13:20,883 is the CMD, which we executed, 228 00:13:22,020 --> 00:13:26,460 which means that our process can communicate 229 00:13:26,460 --> 00:13:29,220 with system processes. 230 00:13:29,220 --> 00:13:30,720 And more interestingly, 231 00:13:30,720 --> 00:13:34,710 this processes are loaded from the container image, 232 00:13:34,710 --> 00:13:36,033 which we control. 233 00:13:36,900 --> 00:13:39,790 So if you can control the executables 234 00:13:42,200 --> 00:13:43,533 we can gain NT/System. 235 00:13:45,090 --> 00:13:50,090 So it doesn't matter with which users container will run, 236 00:13:50,130 --> 00:13:52,530 we can get system permissions. 237 00:13:52,530 --> 00:13:55,203 But how exactly can we do it? 238 00:13:57,660 --> 00:13:59,880 In order to craft a container image 239 00:13:59,880 --> 00:14:02,310 that will run as system always, 240 00:14:02,310 --> 00:14:05,820 we need to follow just these four steps. 241 00:14:05,820 --> 00:14:09,180 First, run the container as system, 242 00:14:09,180 --> 00:14:12,360 to add our backdoor inside of it. 243 00:14:12,360 --> 00:14:17,276 Then we'll create a service that will run as system. 244 00:14:17,276 --> 00:14:18,420 We'll start it, 245 00:14:18,420 --> 00:14:21,360 and convert the container into container image, 246 00:14:21,360 --> 00:14:24,753 that we can deploy for future use. 247 00:14:25,710 --> 00:14:30,600 But this method is not the only one. 248 00:14:30,600 --> 00:14:34,263 It is possible to do it with much more than this method. 249 00:14:35,490 --> 00:14:37,260 For example, we can override 250 00:14:37,260 --> 00:14:41,400 system32 executables that are found in the image, 251 00:14:41,400 --> 00:14:44,250 use DLL side-loading 252 00:14:44,250 --> 00:14:47,700 and modify the configurations, the registry, 253 00:14:47,700 --> 00:14:51,090 and even changing the permissions of the container user 254 00:14:51,090 --> 00:14:53,673 to have admin startup permissions. 255 00:14:56,040 --> 00:15:00,720 So we gained system permissions inside of the container, 256 00:15:00,720 --> 00:15:03,570 but we can't do anything we want yet, 257 00:15:03,570 --> 00:15:04,860 because we are blocked. 258 00:15:04,860 --> 00:15:09,000 We can't load DLLs- drivers, sorry. 259 00:15:09,000 --> 00:15:12,150 And we are isolated from the host. 260 00:15:12,150 --> 00:15:14,133 We can't access the file system. 261 00:15:15,270 --> 00:15:18,180 So in order to break the isolation, 262 00:15:18,180 --> 00:15:21,243 we need to learn first about past vulnerabilities. 263 00:15:22,800 --> 00:15:24,720 I'm going to explain two examples 264 00:15:24,720 --> 00:15:27,480 of past container escape vulnerabilities. 265 00:15:27,480 --> 00:15:31,110 Each one of them represent a different method to look for 266 00:15:31,110 --> 00:15:33,540 in container escape vulnerabilities. 267 00:15:33,540 --> 00:15:36,720 The first method to look are APIs 268 00:15:36,720 --> 00:15:41,370 that Microsoft just forgot to block them from the container. 269 00:15:41,370 --> 00:15:44,220 Unit 42 found a vulnerability 270 00:15:44,220 --> 00:15:46,920 in object manager symbolic link, 271 00:15:46,920 --> 00:15:49,650 that let processes inside of the container 272 00:15:49,650 --> 00:15:52,353 access any hard drive they want. 273 00:15:54,270 --> 00:15:59,130 The second method is to try to bypass Microsoft mitigations. 274 00:15:59,130 --> 00:16:01,474 James Forshaw found a way to bypass 275 00:16:01,474 --> 00:16:04,560 the kernel validation of the server silo, 276 00:16:04,560 --> 00:16:09,560 by creating a new silo object which is not a server silo. 277 00:16:11,010 --> 00:16:13,680 Microsoft added the support for containers 278 00:16:13,680 --> 00:16:17,220 after most of the kernel was implemented. 279 00:16:17,220 --> 00:16:22,170 Therefore, I chose the first method to look for syscalls 280 00:16:22,170 --> 00:16:24,783 that Microsoft just forgot to block. 281 00:16:25,740 --> 00:16:27,540 I didn't put a lot of effort, right, 282 00:16:27,540 --> 00:16:30,900 to bypass existing mitigations and validations. 283 00:16:30,900 --> 00:16:33,603 It looks much harder and less cost effective. 284 00:16:36,240 --> 00:16:40,530 So in my research, I looked for vulnerable syscalls, 285 00:16:40,530 --> 00:16:42,603 but over five hundred, 286 00:16:43,560 --> 00:16:47,370 it is not possible to go over all of them manually. 287 00:16:47,370 --> 00:16:51,900 So I had to find, to narrow this attack vector 288 00:16:51,900 --> 00:16:55,260 into much better and more interesting functions. 289 00:16:55,260 --> 00:16:56,580 So, as I said before, 290 00:16:56,580 --> 00:16:57,810 it has to be a syscall 291 00:16:57,810 --> 00:17:01,020 because otherwise we can't interact with it. 292 00:17:01,020 --> 00:17:05,370 The second, this syscall must not have isolation checks, 293 00:17:05,370 --> 00:17:08,310 which means that Microsoft may or may not 294 00:17:08,310 --> 00:17:11,370 forgot to add isolation check. 295 00:17:11,370 --> 00:17:12,993 And the third one is tricky. 296 00:17:14,370 --> 00:17:19,370 If the syscall must require system permissions, 297 00:17:19,770 --> 00:17:23,100 the higher the privileges, the better. 298 00:17:23,100 --> 00:17:26,579 Then it assured that the impact of the syscall 299 00:17:26,579 --> 00:17:28,530 will be major info leak, 300 00:17:28,530 --> 00:17:31,803 or let us impact the host drastically. 301 00:17:35,160 --> 00:17:37,230 After I build this recipe, 302 00:17:37,230 --> 00:17:39,600 my life become much easier 303 00:17:39,600 --> 00:17:42,123 and I began to find vulnerable functions. 304 00:17:43,950 --> 00:17:48,420 I did a quick triage of syscalls that matched the pattern 305 00:17:48,420 --> 00:17:50,740 and the syscall NTQuerySystemInformation 306 00:17:51,840 --> 00:17:52,923 caught my attention. 307 00:17:53,970 --> 00:17:57,150 This function contains a huge switch case 308 00:17:57,150 --> 00:18:00,750 over the parameter SystemInformationClass, 309 00:18:00,750 --> 00:18:05,160 which is an Enum that contains about 200 options. 310 00:18:05,160 --> 00:18:08,823 I could not go over all of them manually. 311 00:18:10,140 --> 00:18:14,460 But luckily I had symbols, I knew which one does what. 312 00:18:14,460 --> 00:18:17,022 So I wrote a small code, 313 00:18:17,022 --> 00:18:20,100 go over all the interesting ones. 314 00:18:20,100 --> 00:18:22,443 And I found an interesting option. 315 00:18:24,000 --> 00:18:27,690 If I called the system call 316 00:18:27,690 --> 00:18:31,590 with inner value of system handle information, 317 00:18:31,590 --> 00:18:35,760 it return to me a list of all the handles and addresses 318 00:18:35,760 --> 00:18:40,080 of the objects, from all the processes on the host. 319 00:18:40,080 --> 00:18:44,460 It is not possible to use these handles or addresses, 320 00:18:44,460 --> 00:18:46,930 because we can't open processes 321 00:18:48,589 --> 00:18:50,793 that are outside of the container. 322 00:18:51,660 --> 00:18:54,600 And we can't also duplicate that. 323 00:18:54,600 --> 00:18:58,293 So what I found is a minor info leak. 324 00:18:59,310 --> 00:19:02,763 We can gain all the process IDs on the host. 325 00:19:03,867 --> 00:19:06,423 But I want much more, so I continue to look. 326 00:19:07,980 --> 00:19:11,370 Additional interesting syscall that matched the pattern 327 00:19:11,370 --> 00:19:13,713 was NTSystemDebugControl, 328 00:19:14,580 --> 00:19:16,083 which sound much better. 329 00:19:17,370 --> 00:19:21,507 NTSystemDebugControl is similar to the previous function. 330 00:19:21,507 --> 00:19:26,507 It is huge and enumerate over the Enum SysDebug command. 331 00:19:32,010 --> 00:19:34,920 This syscall called multiple interesting functions, 332 00:19:34,920 --> 00:19:37,533 for example, enable kernel debugger, 333 00:19:38,760 --> 00:19:41,910 but all these options were disabled 334 00:19:41,910 --> 00:19:45,098 if the kernel debugger is not enabled. 335 00:19:45,098 --> 00:19:48,393 Even enable kernel debugger requires that. 336 00:19:49,620 --> 00:19:54,180 But all of them except user dump, 337 00:19:55,380 --> 00:19:57,840 which won't give me any actual value 338 00:19:57,840 --> 00:20:01,290 because I need a handle to user mode, 339 00:20:01,290 --> 00:20:04,080 to a process that I can open, 340 00:20:04,080 --> 00:20:09,080 only processes inside of the container, and kernel dump. 341 00:20:09,240 --> 00:20:10,803 That sound much interesting. 342 00:20:12,180 --> 00:20:14,550 So let's understand how to do kernel dump 343 00:20:14,550 --> 00:20:15,500 using this syscall. 344 00:20:17,460 --> 00:20:19,230 In order to do kernel dump, 345 00:20:19,230 --> 00:20:22,383 I need to fill the struct SYSDBG_LIVEDUMP_CONTROL, 346 00:20:24,330 --> 00:20:27,630 which contains two interesting variables: 347 00:20:27,630 --> 00:20:30,480 handle to a file, easy, 348 00:20:30,480 --> 00:20:33,060 and flags to the dump, 349 00:20:33,060 --> 00:20:37,713 which specify what the dump will contain in the kernel. 350 00:20:38,760 --> 00:20:41,040 I took a source code from the internet, 351 00:20:41,040 --> 00:20:44,400 that triggers the kernel dump, change it a bit, 352 00:20:44,400 --> 00:20:48,900 and now I can dump the entire kernel, 353 00:20:48,900 --> 00:20:50,343 from inside the container. 354 00:20:53,100 --> 00:20:55,383 But let's understand what I can dump. 355 00:20:56,490 --> 00:20:58,650 So the flags that control 356 00:20:58,650 --> 00:21:02,880 which information will be included in the kernel dump, 357 00:21:02,880 --> 00:21:06,120 are listed here, they are undocumented. 358 00:21:06,120 --> 00:21:10,170 And the most interesting ones are, dump Hyper-V pages, 359 00:21:10,170 --> 00:21:13,913 and user space memory pages, because of LSASS. 360 00:21:15,180 --> 00:21:17,730 I attach VM kernel debugger, 361 00:21:17,730 --> 00:21:19,410 and I tried to do a kernel dump 362 00:21:19,410 --> 00:21:21,030 from inside of the container. 363 00:21:21,030 --> 00:21:22,170 And it worked. 364 00:21:22,170 --> 00:21:25,830 I managed to dump all user processes, 365 00:21:25,830 --> 00:21:28,620 including LSASS, on the host. 366 00:21:28,620 --> 00:21:31,200 But on a clean Windows machine, 367 00:21:31,200 --> 00:21:34,170 dumping user mode is not possible. 368 00:21:34,170 --> 00:21:36,030 And the root cause, again, 369 00:21:36,030 --> 00:21:39,153 is that kernel debugger is not enabled. 370 00:21:40,260 --> 00:21:43,200 All the other flags worked as expected, 371 00:21:43,200 --> 00:21:44,850 without kernel debugger. 372 00:21:44,850 --> 00:21:48,390 So I can dump the entire kernel, 373 00:21:48,390 --> 00:21:50,523 I can dump additional pages, 374 00:21:51,390 --> 00:21:54,693 but I can't dump the user mode processes. 375 00:21:56,940 --> 00:22:01,110 But I still want to access passwords on the host. 376 00:22:01,110 --> 00:22:03,060 So let's understand how to access them. 377 00:22:03,906 --> 00:22:05,130 There are multiple ways 378 00:22:05,130 --> 00:22:08,457 to access passwords on the host without LSASS. 379 00:22:08,457 --> 00:22:11,760 The first one is via the command line. 380 00:22:11,760 --> 00:22:14,580 The kernel dump contains all the information 381 00:22:14,580 --> 00:22:17,550 about all the processes on the host, 382 00:22:17,550 --> 00:22:19,800 including the command line argument. 383 00:22:19,800 --> 00:22:24,120 So if you pass a password in the command line argument, 384 00:22:24,120 --> 00:22:28,590 all the environment variables on the process, 385 00:22:28,590 --> 00:22:32,287 so I can access it from inside the container. 386 00:22:32,287 --> 00:22:36,570 Another way that sometimes passwords are stored 387 00:22:36,570 --> 00:22:40,470 in the registry, which we can also access 388 00:22:40,470 --> 00:22:41,823 using the kernel dump. 389 00:22:43,230 --> 00:22:45,450 And if the kernel bugger is enabled, 390 00:22:45,450 --> 00:22:48,660 it is possible to dump LSASS directly 391 00:22:48,660 --> 00:22:53,493 and access all the passwords from here. 392 00:22:54,690 --> 00:22:59,640 And of course, kernel dump from inside of the container 393 00:22:59,640 --> 00:23:02,670 can discover much more. 394 00:23:02,670 --> 00:23:06,060 It can discover which EDLs and security products 395 00:23:06,060 --> 00:23:10,113 are running on the host event on Windows, 396 00:23:11,160 --> 00:23:15,183 stack traces, kernel memory, and much more. 397 00:23:17,700 --> 00:23:20,460 So, additional vulnerability I found 398 00:23:20,460 --> 00:23:23,220 is related to the UEFI. 399 00:23:23,220 --> 00:23:25,620 So in order to understand the impact 400 00:23:25,620 --> 00:23:28,350 and how can we use this vulnerability, 401 00:23:28,350 --> 00:23:30,213 I'll give a bit of background. 402 00:23:32,070 --> 00:23:34,980 When we boot a new Windows PC, 403 00:23:34,980 --> 00:23:37,680 it probably boot in this following sequence. 404 00:23:37,680 --> 00:23:41,190 First, the UEFI image the CPU, 405 00:23:41,190 --> 00:23:44,400 loads the UEFI device and drivers, 406 00:23:44,400 --> 00:23:48,120 then, the UEFI loads the configuration, 407 00:23:48,120 --> 00:23:50,010 from the NVRAM memory, 408 00:23:50,010 --> 00:23:52,683 in order to know how to continue the boot. 409 00:23:53,700 --> 00:23:58,560 Then the execution forwards from the UEFI to the Windows. 410 00:23:58,560 --> 00:24:02,370 On the third step, Windows begins the boot sequence. 411 00:24:02,370 --> 00:24:05,430 Windows pull the configuration from BCD, 412 00:24:05,430 --> 00:24:08,250 which are stored in the EFI partition. 413 00:24:08,250 --> 00:24:10,260 Then it continues the rest of the boot 414 00:24:10,260 --> 00:24:12,093 until Windows completes the boot. 415 00:24:13,980 --> 00:24:17,073 Let's focus on the NVRAM storage. 416 00:24:17,073 --> 00:24:22,073 The UEFI NVRAM contains the configuration of the UEFI. 417 00:24:22,080 --> 00:24:25,920 These configurations are not stored on the hard disk itself, 418 00:24:25,920 --> 00:24:28,083 but on a chip in the motherboard. 419 00:24:28,950 --> 00:24:31,230 This memory is not shared 420 00:24:31,230 --> 00:24:34,560 between the operating system and the UEFI, 421 00:24:34,560 --> 00:24:38,280 and the multiple name spaces in the NVRAM. 422 00:24:38,280 --> 00:24:41,940 So in order to access a specific variable there, 423 00:24:41,940 --> 00:24:44,910 we need to know its GUID, its namespace, 424 00:24:44,910 --> 00:24:46,533 and the variable name. 425 00:24:48,870 --> 00:24:52,853 Two examples of major variables are found, 426 00:24:52,853 --> 00:24:55,830 Boot, and BootOrder. 427 00:24:55,830 --> 00:24:59,910 Boot is a variable that define the UEFI, 428 00:24:59,910 --> 00:25:02,580 how to boot using a specific method, 429 00:25:02,580 --> 00:25:06,543 for example, boot from hard disk or boot from CD. 430 00:25:09,060 --> 00:25:10,890 The content of the Boot variable 431 00:25:10,890 --> 00:25:14,190 sometimes point to files on the hard disk, 432 00:25:14,190 --> 00:25:18,833 but they're stored in the UEFI partition on the FAT32, 433 00:25:20,070 --> 00:25:22,830 so the container can't access them, 434 00:25:22,830 --> 00:25:24,603 so we can't modify them. 435 00:25:25,860 --> 00:25:28,980 The BootOrder defined in which order 436 00:25:28,980 --> 00:25:31,050 the UEFI will try to boot, 437 00:25:31,050 --> 00:25:34,380 whether it's going to try to boot from the CD first, 438 00:25:34,380 --> 00:25:36,603 hard disk, network, and so on. 439 00:25:37,821 --> 00:25:42,821 There are multiple types and flags for the NVRAM variables, 440 00:25:44,340 --> 00:25:47,550 which can be classified into two sections: 441 00:25:47,550 --> 00:25:50,397 storage method, which defines 442 00:25:50,397 --> 00:25:54,780 whether the NVRAM variable is going to be volatile or not, 443 00:25:54,780 --> 00:25:58,080 and the access, when we can access the variable, 444 00:25:58,080 --> 00:26:01,230 whether we can access it only on the boot, 445 00:26:01,230 --> 00:26:05,987 or we can access it on the OS part from the Windows itself. 446 00:26:08,840 --> 00:26:11,583 So let's jump to the vulnerability itself. 447 00:26:12,810 --> 00:26:17,280 This vulnerability is related to multiple syscalls, 448 00:26:17,280 --> 00:26:19,613 which all are related to the NVRAM. 449 00:26:22,170 --> 00:26:24,720 So the first capability we want is 450 00:26:24,720 --> 00:26:28,590 listing all the NVRAM variables on the host. 451 00:26:28,590 --> 00:26:31,320 We can do that using the syscall 452 00:26:31,320 --> 00:26:33,273 NTEnumerateSystemEnvironmentValue, 453 00:26:35,220 --> 00:26:40,023 which let us discover all the NVRAM variables from the host, 454 00:26:41,010 --> 00:26:46,010 but it is possible to do that from the container itself. 455 00:26:46,110 --> 00:26:50,310 But this operation won't be useful without reading them, 456 00:26:50,310 --> 00:26:53,269 which lead us to the second syscall 457 00:26:53,269 --> 00:26:55,980 NTQuerySystemEnvironmentValue, 458 00:26:55,980 --> 00:27:00,930 which let us read a value from a specific NVRAM variable, 459 00:27:00,930 --> 00:27:03,840 which is stored on the host. 460 00:27:03,840 --> 00:27:06,270 Microsoft didn't block this syscall 461 00:27:06,270 --> 00:27:07,743 from the container as well. 462 00:27:08,640 --> 00:27:11,250 And the last capability we need 463 00:27:11,250 --> 00:27:14,643 is to read and write NVRAM variable, 464 00:27:15,900 --> 00:27:19,800 which means that we have read, write, and listing 465 00:27:19,800 --> 00:27:22,320 all the NVRAM variables. 466 00:27:22,320 --> 00:27:26,583 So it raised the question, what can we do with it? 467 00:27:29,040 --> 00:27:32,040 After the container is killed and start over, 468 00:27:32,040 --> 00:27:34,740 sometimes the storage is reverted, 469 00:27:34,740 --> 00:27:37,983 which means it is not possible to store permanent data. 470 00:27:39,060 --> 00:27:41,400 Writing and reading NVRAM 471 00:27:41,400 --> 00:27:44,340 will let us store persistent storage, 472 00:27:44,340 --> 00:27:47,340 that will store between container reboots, 473 00:27:47,340 --> 00:27:49,620 even reboots of the host. 474 00:27:49,620 --> 00:27:54,620 And because NVRAM is stored on the motherboard itself, 475 00:27:54,690 --> 00:27:57,183 we can even stay after formats. 476 00:27:59,460 --> 00:28:01,890 Additional impact is communication 477 00:28:01,890 --> 00:28:05,700 between two containers, isolated containers. 478 00:28:05,700 --> 00:28:09,870 Because both of the containers can read and write 479 00:28:09,870 --> 00:28:13,273 from the same memory variables on the NVRAM, 480 00:28:13,273 --> 00:28:16,533 we can extricate data between them. 481 00:28:18,930 --> 00:28:20,760 And the most interesting impact 482 00:28:20,760 --> 00:28:25,320 is triggering permanent denial of service of the host. 483 00:28:25,320 --> 00:28:28,800 Because the UEFI parse the NVRAM variables, 484 00:28:28,800 --> 00:28:31,440 it is possible to change some of them 485 00:28:31,440 --> 00:28:34,143 to make the host unbootable forever. 486 00:28:35,280 --> 00:28:38,250 Changing the variables Boot and BootOrder, 487 00:28:38,250 --> 00:28:40,338 which we talked about before, 488 00:28:40,338 --> 00:28:43,500 doesn't prevent the UEFI from booting Windows 489 00:28:43,500 --> 00:28:47,043 because of backup configurations, which we cannot touch. 490 00:28:48,270 --> 00:28:52,643 Therefore, had to look for other flows and variables. 491 00:28:52,643 --> 00:28:57,643 Another NVRAM variable, exists on some UEFI, is HDDP. 492 00:28:58,710 --> 00:29:03,570 Writing non-valid value to it will do the job, 493 00:29:03,570 --> 00:29:07,083 and it will cause permanent denial of service to the host. 494 00:29:08,640 --> 00:29:11,740 The impact of this writing 495 00:29:13,170 --> 00:29:17,013 will happen only after the host restart itself. 496 00:29:18,030 --> 00:29:19,950 It will shut down as expected. 497 00:29:19,950 --> 00:29:22,380 Everything will work perfectly. 498 00:29:22,380 --> 00:29:25,860 And when the host will try to boot up again, 499 00:29:25,860 --> 00:29:27,747 it won't be possible. 500 00:29:27,747 --> 00:29:32,040 The UEFI won't be able to pass the execution 501 00:29:32,040 --> 00:29:33,153 to the Windows part. 502 00:29:35,520 --> 00:29:37,710 So it doesn't matter how much restart 503 00:29:37,710 --> 00:29:40,545 you will do to the machine, to the host. 504 00:29:40,545 --> 00:29:41,795 It won't start. 505 00:29:44,010 --> 00:29:47,283 The impacted UEFI was VMware UEFI. 506 00:29:49,230 --> 00:29:54,060 So, if you run Windows container inside Windows VM, 507 00:29:54,060 --> 00:29:56,130 running in Windows machine, 508 00:29:56,130 --> 00:29:59,343 for example, EF6 or VMware Workstation, 509 00:30:00,320 --> 00:30:04,143 the UEFI of the Windows VM is a vulnerable component. 510 00:30:05,430 --> 00:30:08,910 When writing the HDDP variable from the container, 511 00:30:08,910 --> 00:30:12,993 it will cause permanent denial of service to the VMware VM. 512 00:30:14,430 --> 00:30:17,553 Sadly, the host machine won't be impacted. 513 00:30:19,980 --> 00:30:23,253 So let's deep dive and find the root cause. 514 00:30:24,529 --> 00:30:27,540 The UEFI built from multiple parts. 515 00:30:27,540 --> 00:30:31,080 The vulnerable part is BDS driver, 516 00:30:31,080 --> 00:30:33,660 which is responsible for selecting 517 00:30:33,660 --> 00:30:35,193 which device to boot from. 518 00:30:47,259 --> 00:30:50,340 The root cause in the BdsDxe 519 00:30:50,340 --> 00:30:53,520 is that it reads the HDDP variable. 520 00:30:53,520 --> 00:30:57,933 And because it is invalid, it called to ASSERT_EFI_ERROR. 521 00:30:59,910 --> 00:31:03,090 This function stops the boot sequence 522 00:31:03,090 --> 00:31:06,483 and cause the UEFI to loop, 523 00:31:09,602 --> 00:31:13,830 to enter into loop that it won't be possible to enter into, 524 00:31:13,830 --> 00:31:16,860 or trigger a brake point, which, 525 00:31:16,860 --> 00:31:19,140 no debugger will be attached to it, 526 00:31:19,140 --> 00:31:20,913 so the UEFI will stop. 527 00:31:21,870 --> 00:31:25,200 Which means that the boot sequence will stop 528 00:31:25,200 --> 00:31:27,753 and it won't be possible to do it. 529 00:31:29,490 --> 00:31:30,990 So let's jump to a demo 530 00:31:30,990 --> 00:31:33,360 containing a chain of vulnerabilities, 531 00:31:33,360 --> 00:31:35,430 we will do a privilege escalation 532 00:31:35,430 --> 00:31:37,800 using a malicious Windows container, 533 00:31:37,800 --> 00:31:41,880 and how we can cause a permanent denial of service 534 00:31:41,880 --> 00:31:43,083 to the VMware VM? 535 00:31:48,510 --> 00:31:53,510 So here, you can see a container that we are about to start, 536 00:31:53,940 --> 00:31:56,583 which will run with weak privileges, 537 00:31:57,420 --> 00:32:00,393 and it will load a malicious Windows container. 538 00:32:03,390 --> 00:32:07,560 So you can see that the user doesn't have admin privileges, 539 00:32:07,560 --> 00:32:12,180 but there is a background service, that I created before, 540 00:32:12,180 --> 00:32:16,350 and it reads and writes to the input file and output file. 541 00:32:16,350 --> 00:32:18,420 So we wrote the whoami command, 542 00:32:18,420 --> 00:32:21,600 and we will read the output, 543 00:32:21,600 --> 00:32:23,823 and you can see that we have system. 544 00:32:24,690 --> 00:32:29,690 And if you override the HDDP variable of the NVRAM, 545 00:32:31,800 --> 00:32:36,393 it's possible to see that we override that by six time A. 546 00:32:37,860 --> 00:32:42,213 So now, what we need to do is wait for the restart. 547 00:32:43,410 --> 00:32:47,970 So you can see that it'll restart as expected, 548 00:32:47,970 --> 00:32:52,970 no special actions, Windows won't detect that as an issue. 549 00:32:54,480 --> 00:32:57,513 And once it will start up again, 550 00:32:58,380 --> 00:33:01,653 the Windows part won't be able to boot. 551 00:33:02,494 --> 00:33:05,366 The UEFI will just be stuck on that. 552 00:33:05,366 --> 00:33:10,366 So here, with the UEFI start, and it's in the resources, 553 00:33:10,860 --> 00:33:15,003 and when it will continue, that's it. 554 00:33:15,990 --> 00:33:18,213 We won't pass this step. 555 00:33:20,274 --> 00:33:23,441 (audience applauding) 556 00:33:28,590 --> 00:33:31,773 So let us explain how the demo worked. 557 00:33:33,480 --> 00:33:34,800 So before the demo, 558 00:33:34,800 --> 00:33:36,630 I created the malicious Windows container, 559 00:33:36,630 --> 00:33:40,320 contains the backdoor service that run as system. 560 00:33:40,320 --> 00:33:45,320 It read and write from the input file and output file. 561 00:33:46,050 --> 00:33:48,873 And when we executed using this service, 562 00:33:49,800 --> 00:33:54,800 the NVRAM executable, which overrides the HDDP variable, 563 00:33:55,380 --> 00:33:58,045 and restarted the machine, 564 00:33:58,045 --> 00:34:00,445 which triggered the permanent denial of service. 565 00:34:02,880 --> 00:34:06,870 So let's jump to mitigating this. 566 00:34:06,870 --> 00:34:09,570 It is not easy to mitigate these vulnerabilities 567 00:34:09,570 --> 00:34:12,690 without official patch from Microsoft, 568 00:34:12,690 --> 00:34:16,557 but there are few workarounds that we can do. 569 00:34:16,557 --> 00:34:21,420 For example, instead of using process isolated containers, 570 00:34:21,420 --> 00:34:22,860 which are easy to use, 571 00:34:22,860 --> 00:34:26,820 and doesn't have overhead of computational power, 572 00:34:26,820 --> 00:34:29,460 we can use the Hyper-V isolation, 573 00:34:29,460 --> 00:34:31,650 which costs more in performance, 574 00:34:31,650 --> 00:34:35,070 but it is not vulnerable to the UEFI 575 00:34:35,070 --> 00:34:37,693 and the kernel dump vulnerabilities. 576 00:34:38,693 --> 00:34:42,900 Another flow is to run only signed executables, 577 00:34:42,900 --> 00:34:45,330 which you can trust, and therefore, 578 00:34:45,330 --> 00:34:49,050 you won't fear of malicious Windows containers, 579 00:34:49,050 --> 00:34:52,290 but it's really hard to do that. 580 00:34:52,290 --> 00:34:55,740 And another one is to assume 581 00:34:55,740 --> 00:34:59,340 that container image will run as system 582 00:34:59,340 --> 00:35:04,340 and use it in the network topology. 583 00:35:09,540 --> 00:35:13,140 Container image scanning is used in order to ensure 584 00:35:13,140 --> 00:35:16,950 that no such issues such as privilege escalation 585 00:35:16,950 --> 00:35:21,510 in the Windows container exist on the container. 586 00:35:21,510 --> 00:35:26,510 So I tested my container, with a privileged escalation, 587 00:35:26,820 --> 00:35:31,140 and they didn't detect that. 588 00:35:31,140 --> 00:35:35,490 But only after I dug into the website, I discovered that 589 00:35:35,490 --> 00:35:38,430 they don't support Windows container officially, 590 00:35:38,430 --> 00:35:42,120 but they did mark the container as clean. 591 00:35:42,120 --> 00:35:46,560 So if you are using container images and you scan them, 592 00:35:46,560 --> 00:35:49,920 please ensure that the product 593 00:35:49,920 --> 00:35:51,933 is support Windows containers. 594 00:35:53,070 --> 00:35:57,450 Sadly, I could not put my hands on Windows container image 595 00:35:57,450 --> 00:36:01,323 scanning product that support Windows containers. 596 00:36:03,600 --> 00:36:06,240 Regarding the vendor response. 597 00:36:06,240 --> 00:36:08,580 Basically, Microsoft said that, 598 00:36:08,580 --> 00:36:12,570 because administrators can start containers, 599 00:36:12,570 --> 00:36:15,120 the privilege escalation that we can gain, 600 00:36:15,120 --> 00:36:17,160 NT-system inside of the container, 601 00:36:17,160 --> 00:36:18,543 is not a vulnerability. 602 00:36:19,980 --> 00:36:21,766 Regarding the kernel dump, 603 00:36:21,766 --> 00:36:26,766 that we can dump the kernel from inside of the container, 604 00:36:27,630 --> 00:36:31,050 they answered that it is not a vulnerability, 605 00:36:31,050 --> 00:36:35,040 because we need administrator user inside of the container, 606 00:36:35,040 --> 00:36:37,473 which we gained in the privilege escalation. 607 00:36:38,670 --> 00:36:41,103 But they do plan to fix it in the future. 608 00:36:42,870 --> 00:36:46,110 Regarding the open NVRAM syscalls, 609 00:36:46,110 --> 00:36:51,090 which we can write, read, and list NVRAM variables, 610 00:36:51,090 --> 00:36:53,490 Microsoft defines this attack as 611 00:36:53,490 --> 00:36:55,383 moderate denial of service, 612 00:36:56,250 --> 00:36:59,700 which is outside of the Windows security update, 613 00:36:59,700 --> 00:37:01,083 but they will fix it. 614 00:37:02,070 --> 00:37:07,070 And regarding the VMware UEFI HDDP, 615 00:37:08,100 --> 00:37:11,733 which cause the permanent denial of service to the host, 616 00:37:12,720 --> 00:37:15,330 VMware treated as functional issue 617 00:37:15,330 --> 00:37:19,650 because it impacts only the VM itself, 618 00:37:19,650 --> 00:37:24,510 and requires admin privileges from inside, 619 00:37:24,510 --> 00:37:27,483 but they do plan to fix it in future releases. 620 00:37:30,060 --> 00:37:34,178 I uploaded all the tools and modifications that I use, 621 00:37:34,178 --> 00:37:36,450 how to do privilege escalation 622 00:37:36,450 --> 00:37:41,450 and create the malicious Windows container, 623 00:37:41,490 --> 00:37:42,780 to GitHub. 624 00:37:42,780 --> 00:37:45,600 In addition, in this repo, you can see, 625 00:37:45,600 --> 00:37:49,110 you can use the code that does the kernel dump 626 00:37:49,110 --> 00:37:51,270 from inside of the container, 627 00:37:51,270 --> 00:37:56,270 and manual to how to cause permanent denial of service 628 00:37:56,610 --> 00:37:58,833 to VMware VM. 629 00:38:03,270 --> 00:38:06,090 So, some acknowledgements, I would like to thank Mickey, 630 00:38:06,090 --> 00:38:10,110 for helping me reversing the VMware UEFI, 631 00:38:10,110 --> 00:38:12,060 and additional researchers, 632 00:38:12,060 --> 00:38:14,913 that I based my research on top of theirs. 633 00:38:16,530 --> 00:38:18,390 Thank you for joining. 634 00:38:18,390 --> 00:38:21,693 The Q&A will be happening there. 635 00:38:22,680 --> 00:38:23,879 So, thank you. 636 00:38:23,879 --> 00:38:27,046 (audience applauding)