1 00:00:04,170 --> 00:00:06,620 - If you are a macOS developer, and you've updated 2 00:00:06,620 --> 00:00:09,870 to Xcode 13 and created a new project, 3 00:00:09,870 --> 00:00:13,103 you may have noticed that there is this new method 4 00:00:15,090 --> 00:00:16,657 in the application delegate, 5 00:00:16,657 --> 00:00:19,830 applicationSupportsSecureRestorableState, 6 00:00:19,830 --> 00:00:21,573 which by default returns YES. 7 00:00:22,860 --> 00:00:27,060 In this talk, I'm going to describe the vulnerability 8 00:00:27,060 --> 00:00:29,730 that's necessitated this change, 9 00:00:29,730 --> 00:00:31,500 and show how to this could be applied 10 00:00:31,500 --> 00:00:33,753 for three different types of attacks. 11 00:00:35,910 --> 00:00:37,050 I'm Thijs Alkemade. 12 00:00:37,050 --> 00:00:39,720 I'm a security researcher at Computest. 13 00:00:39,720 --> 00:00:42,930 Computest is a security testing company in the Netherlands. 14 00:00:42,930 --> 00:00:44,400 It provides security services 15 00:00:44,400 --> 00:00:47,040 like pen testing, incident response, 16 00:00:47,040 --> 00:00:50,310 and other things, stuff like that. 17 00:00:50,310 --> 00:00:53,310 But I'm, together with my colleague Daan Keuper, 18 00:00:53,310 --> 00:00:55,260 part of the research department, 19 00:00:55,260 --> 00:00:57,420 which means that we don't work for customers, 20 00:00:57,420 --> 00:01:01,050 but instead we can basically research anything 21 00:01:01,050 --> 00:01:03,180 that we think is important. 22 00:01:03,180 --> 00:01:05,391 So we try to look for stuff 23 00:01:05,391 --> 00:01:08,823 that has a lot of users or where impact can be large. 24 00:01:09,810 --> 00:01:12,033 Just to make the world a little bit safer. 25 00:01:13,080 --> 00:01:14,820 Other work you may have seen from us 26 00:01:14,820 --> 00:01:19,680 is our 0click RCE Zoom at Pwn2Own last year. 27 00:01:19,680 --> 00:01:21,390 And we won Pwn2Own Miami this year 28 00:01:21,390 --> 00:01:24,840 with five different vulnerabilities in ICS systems. 29 00:01:24,840 --> 00:01:26,850 There's write-ups of these on our website 30 00:01:26,850 --> 00:01:28,833 if you want to know more about these. 31 00:01:30,990 --> 00:01:33,780 But today, I'm going to be talking about macOS security, 32 00:01:33,780 --> 00:01:36,330 which has been the method of specialty for me. 33 00:01:36,330 --> 00:01:39,750 I've been doing a lot of work with macOS over the years. 34 00:01:39,750 --> 00:01:42,270 It's a system I really know the best. 35 00:01:42,270 --> 00:01:43,680 All of these were just incidents, 36 00:01:43,680 --> 00:01:47,257 but macOS is really where I'm passionate for. 37 00:01:49,410 --> 00:01:51,990 This talk will consist of three parts. 38 00:01:51,990 --> 00:01:54,180 First of all, I'll talk a little bit 39 00:01:54,180 --> 00:01:57,090 about the macOS security model because many people 40 00:01:57,090 --> 00:02:00,079 don't really understand how this security model works. 41 00:02:00,079 --> 00:02:02,400 Many people still have incorrect assumptions 42 00:02:02,400 --> 00:02:05,073 about how the security works on macOS. 43 00:02:06,360 --> 00:02:08,910 And then I'll describe the vulnerability that I found, 44 00:02:08,910 --> 00:02:11,610 a process injection vulnerability. 45 00:02:11,610 --> 00:02:14,190 And then in the third part, I will demonstrate 46 00:02:14,190 --> 00:02:15,990 how this vulnerability could be applied 47 00:02:15,990 --> 00:02:19,500 for escaping the sandbox, privilege escalation, 48 00:02:19,500 --> 00:02:20,733 and bypassing SIP. 49 00:02:23,640 --> 00:02:26,700 So first of all, the macOS security model. 50 00:02:26,700 --> 00:02:29,190 So to describe the security model, 51 00:02:29,190 --> 00:02:33,420 I'll first describe the UNIX security model 52 00:02:33,420 --> 00:02:36,420 that used to be used by macOS as well. 53 00:02:36,420 --> 00:02:38,193 And the basic idea behind this security model 54 00:02:38,193 --> 00:02:41,850 is that users are security boundaries, 55 00:02:41,850 --> 00:02:43,083 but processes are not. 56 00:02:44,070 --> 00:02:47,640 So if you look at the permissions for files, 57 00:02:47,640 --> 00:02:51,420 and that is determined by the owner and the group. 58 00:02:51,420 --> 00:02:53,010 And there is these nine different bits 59 00:02:53,010 --> 00:02:55,800 that determine whether the owner, or group, 60 00:02:55,800 --> 00:02:58,110 or everybody is allowed to read, write, 61 00:02:58,110 --> 00:02:59,583 or execute that file. 62 00:03:00,900 --> 00:03:03,043 Also, if you want to attach a debugger to another process, 63 00:03:03,043 --> 00:03:06,243 then in general, those need to be running as the same user. 64 00:03:07,410 --> 00:03:08,280 There's one exception. 65 00:03:08,280 --> 00:03:11,850 There's the root user, who always has access to all files, 66 00:03:11,850 --> 00:03:13,530 can attach to any process, 67 00:03:13,530 --> 00:03:16,440 and therefore, they can basically access all of the data 68 00:03:16,440 --> 00:03:18,990 on the system by just, yeah... 69 00:03:18,990 --> 00:03:21,090 Whether on memory or on disk, 70 00:03:21,090 --> 00:03:22,773 they can always get access to it. 71 00:03:23,640 --> 00:03:26,970 Now, this used to be the same security model as macOS has, 72 00:03:26,970 --> 00:03:30,120 but this has changed. 73 00:03:30,120 --> 00:03:33,930 So in 2015 with the release of El Capitan, 74 00:03:33,930 --> 00:03:37,140 Apple introduced System Integrity Protection. 75 00:03:37,140 --> 00:03:39,683 And this is a screenshot from the WWDC talk, 76 00:03:39,683 --> 00:03:41,493 where they introduced this. 77 00:03:43,260 --> 00:03:45,870 And the basic idea behind System Integrity Protection 78 00:03:45,870 --> 00:03:48,930 was at the time there were two things. 79 00:03:48,930 --> 00:03:52,710 There was to make a security boundary 80 00:03:52,710 --> 00:03:56,670 between any process running as roots and the kernel. 81 00:03:56,670 --> 00:04:00,510 And secondly, to protect the operating system 82 00:04:00,510 --> 00:04:03,573 from being modified even by the root user. 83 00:04:05,430 --> 00:04:09,390 So this feature's also known 84 00:04:09,390 --> 00:04:12,030 as rootless sometimes internally. 85 00:04:12,030 --> 00:04:14,760 Many people thought that that would mean that Apple 86 00:04:14,760 --> 00:04:18,450 would take the root user away from normal users, 87 00:04:18,450 --> 00:04:21,330 like in iOS where you have no root user, 88 00:04:21,330 --> 00:04:24,302 but this is really not what's meant by that name. 89 00:04:24,302 --> 00:04:28,110 The idea behind it is that root is less powerful, 90 00:04:28,110 --> 00:04:29,823 so that's why it's rootless. 91 00:04:31,650 --> 00:04:33,540 But of course, they do need to meet processes 92 00:04:33,540 --> 00:04:35,400 that can modify the system because you need 93 00:04:35,400 --> 00:04:37,830 to be able to install updates. 94 00:04:37,830 --> 00:04:41,880 So for that, what they use are entitlements, 95 00:04:41,880 --> 00:04:44,340 which are basically metadata that is included 96 00:04:44,340 --> 00:04:47,703 when generating a code signature for an application. 97 00:04:49,110 --> 00:04:51,930 So to do dangerous operations 98 00:04:51,930 --> 00:04:55,380 like loading a kernel extension, modifying the system files, 99 00:04:55,380 --> 00:04:57,690 or debugging a system process, 100 00:04:57,690 --> 00:05:00,120 you no longer need to be a specific user, 101 00:05:00,120 --> 00:05:02,580 but instead, the system will check if the process 102 00:05:02,580 --> 00:05:05,043 trying to do that has a certain entitlement. 103 00:05:07,080 --> 00:05:11,370 Now, this SIP has over the years been extended by Apple 104 00:05:11,370 --> 00:05:13,530 with more and more restrictions. 105 00:05:13,530 --> 00:05:15,570 For example, debugging any application 106 00:05:15,570 --> 00:05:18,240 is now also forbidden by SIP, 107 00:05:18,240 --> 00:05:20,703 unless the application specifically allows that. 108 00:05:21,600 --> 00:05:23,800 And there's this feature called data vaults. 109 00:05:25,350 --> 00:05:27,330 I have an example of that here. 110 00:05:27,330 --> 00:05:29,370 So Apple considers your email database, 111 00:05:29,370 --> 00:05:31,710 but also your iChat history, 112 00:05:31,710 --> 00:05:34,623 or your Safari browsing history. 113 00:05:36,210 --> 00:05:40,269 That's very sensitive, so Apple doesn't want any process 114 00:05:40,269 --> 00:05:42,630 to be able to read that. 115 00:05:42,630 --> 00:05:47,630 So this is placed into what's known as a data vault, 116 00:05:47,760 --> 00:05:50,760 and as you can see, you cannot just list the contents 117 00:05:50,760 --> 00:05:53,670 of that directory, but even if you use pseudo, 118 00:05:53,670 --> 00:05:56,020 you cannot list the contents of that directory. 119 00:05:58,380 --> 00:06:01,050 So the only processes that are allowed to access 120 00:06:01,050 --> 00:06:04,383 that directory are those that have a special entitlement. 121 00:06:05,280 --> 00:06:07,530 So your mail client, of course, needs to be able 122 00:06:07,530 --> 00:06:10,800 to access that directory, so it has this entitlement, 123 00:06:10,800 --> 00:06:13,428 com.apple.rootless.storage.Mail. 124 00:06:13,428 --> 00:06:17,430 And that gives it access to the mail data vaults, 125 00:06:17,430 --> 00:06:19,830 which is that location that I showed before. 126 00:06:19,830 --> 00:06:21,510 So mail can access the files in there, 127 00:06:21,510 --> 00:06:23,313 but any other process cannot. 128 00:06:27,870 --> 00:06:31,014 Of course, this new security model also introduces 129 00:06:31,014 --> 00:06:33,185 new types of vulnerabilities 130 00:06:33,185 --> 00:06:37,170 or vulnerabilities become suddenly more important. 131 00:06:37,170 --> 00:06:40,440 One of those is what's known as process injection. 132 00:06:40,440 --> 00:06:43,440 And that's basically the ability for one process 133 00:06:43,440 --> 00:06:46,890 to execute codes or to add codes that the system 134 00:06:46,890 --> 00:06:48,780 thinks is another process. 135 00:06:48,780 --> 00:06:50,940 So a system thinks it's process B 136 00:06:50,940 --> 00:06:53,337 with the entitlement of process B, 137 00:06:53,337 --> 00:06:56,823 but actually process A specified the code that's being run. 138 00:06:58,230 --> 00:07:00,630 And when Apple introduced SIP, 139 00:07:00,630 --> 00:07:03,780 on the right, there's this one slide of that presentation, 140 00:07:03,780 --> 00:07:06,660 they already disabled a lot of things that could be used 141 00:07:06,660 --> 00:07:11,070 for that, like rootkits, or DTrace, 142 00:07:11,070 --> 00:07:13,870 dynamic library, environment variables, stuff like that. 143 00:07:16,260 --> 00:07:18,720 And also, they added the hardened runtime 144 00:07:18,720 --> 00:07:22,410 to make this also possible for third party applications. 145 00:07:22,410 --> 00:07:25,260 If they opt into that hardened runtime, 146 00:07:25,260 --> 00:07:29,553 then it's now also harder to inject into that process. 147 00:07:31,050 --> 00:07:34,170 But macOS is old, it's large, it's established. 148 00:07:34,170 --> 00:07:37,560 So there's a lot of code that was written before this change 149 00:07:37,560 --> 00:07:41,251 in the security model, and it's really hard to reevaluate 150 00:07:41,251 --> 00:07:44,283 the entire system when you make a change like this. 151 00:07:47,370 --> 00:07:49,417 Now, process injection is a vulnerability type 152 00:07:49,417 --> 00:07:52,530 that's found often in incidental ways. 153 00:07:52,530 --> 00:07:56,790 So you find a third party application that is missing 154 00:07:56,790 --> 00:07:58,120 the hardened runtime, or something like that, 155 00:07:58,120 --> 00:08:02,431 or it has an exception, and that kind of impacts, 156 00:08:02,431 --> 00:08:04,559 like you could for example, 157 00:08:04,559 --> 00:08:07,290 if an application has access to your webcam 158 00:08:07,290 --> 00:08:10,080 and you have malware installed on that machine, 159 00:08:10,080 --> 00:08:13,350 then if you can inject into that other application, 160 00:08:13,350 --> 00:08:15,450 you can use that application's permission 161 00:08:15,450 --> 00:08:17,755 to access the webcam without the user 162 00:08:17,755 --> 00:08:20,013 being asked to give permission for that. 163 00:08:21,510 --> 00:08:25,830 And these attacks also often work by creating an application 164 00:08:25,830 --> 00:08:28,833 to an older version that did not have the hardened runtime. 165 00:08:30,570 --> 00:08:32,580 But of course, that's incidental 166 00:08:32,580 --> 00:08:34,710 process injection vulnerabilities. 167 00:08:34,710 --> 00:08:36,330 What's way more fun, of course, 168 00:08:36,330 --> 00:08:39,000 is if you have a process injection vulnerability 169 00:08:39,000 --> 00:08:41,103 that applies everywhere. 170 00:08:42,450 --> 00:08:46,283 So we get to this vulnerability, CVE-2021-30873, 171 00:08:48,930 --> 00:08:51,480 which was a process injection vulnerability in AppKit, 172 00:08:51,480 --> 00:08:53,790 which therefore affected all of the applications 173 00:08:53,790 --> 00:08:55,860 that are developed using AppKit, 174 00:08:55,860 --> 00:08:57,779 which is basically the framework 175 00:08:57,779 --> 00:09:00,383 that you use for creating desktop applications on macOS. 176 00:09:01,800 --> 00:09:04,911 And this vulnerability was in a feature 177 00:09:04,911 --> 00:09:09,213 that's called saved state, or also persistent UI internally. 178 00:09:10,800 --> 00:09:14,850 And what this feature is used for is for example, 179 00:09:14,850 --> 00:09:16,050 if you shut down your computer, 180 00:09:16,050 --> 00:09:18,778 it asks if you want to restore your open windows 181 00:09:18,778 --> 00:09:20,433 next time you log in. 182 00:09:21,487 --> 00:09:23,580 And when it restores those windows, 183 00:09:23,580 --> 00:09:25,500 they will have the same locations. 184 00:09:25,500 --> 00:09:28,290 And if you have an unsafe document and you shut down, 185 00:09:28,290 --> 00:09:31,050 and then the windows are recovered, 186 00:09:31,050 --> 00:09:32,597 then the documents should still be there 187 00:09:32,597 --> 00:09:34,923 if they correctly implement this. 188 00:09:36,300 --> 00:09:37,963 Now, most of this works out of the box. 189 00:09:37,963 --> 00:09:40,200 There's nothing the application needs to do 190 00:09:40,200 --> 00:09:44,610 to opt into this, but for document-based applications, 191 00:09:44,610 --> 00:09:47,220 it can be necessary that it store some extra data 192 00:09:47,220 --> 00:09:48,917 about the documents into that saved state. 193 00:09:48,917 --> 00:09:51,371 So it can be extended, but by default, 194 00:09:51,371 --> 00:09:54,843 it already affects or works in all applications. 195 00:09:57,660 --> 00:10:00,540 Now, the way this works is that it stores 196 00:10:00,540 --> 00:10:02,741 a couple of files into a directory, 197 00:10:02,741 --> 00:10:06,210 in your /Library/Saved Application State directory. 198 00:10:06,210 --> 00:10:09,390 There's two files important here for this vulnerability. 199 00:10:09,390 --> 00:10:13,890 That's the windows.plist file, and this is basically a list 200 00:10:13,890 --> 00:10:16,980 of all of the windows that the application has open 201 00:10:16,980 --> 00:10:21,720 with an encryption key for each window. 202 00:10:21,720 --> 00:10:25,936 And there's the data.data file, which is a custom format. 203 00:10:25,936 --> 00:10:29,493 As far as I know, it's not used anywhere else in macOS. 204 00:10:29,493 --> 00:10:31,830 But there's also a list of records. 205 00:10:31,830 --> 00:10:35,190 And each entry in that list corresponds 206 00:10:35,190 --> 00:10:39,123 to an entry from the windows file, 207 00:10:40,140 --> 00:10:43,713 which contains a encrypted serialized object. 208 00:10:44,760 --> 00:10:47,853 Now, the encryption here, it's AES-CBC. 209 00:10:49,140 --> 00:10:51,300 I have no idea why it's encrypted 210 00:10:51,300 --> 00:10:54,450 because the key and the file are right next to each other, 211 00:10:54,450 --> 00:10:57,060 there's no different permissions for the files. 212 00:10:57,060 --> 00:11:00,900 So anything that can read that key can also read the file. 213 00:11:00,900 --> 00:11:03,570 So I don't understand why it's encrypted. 214 00:11:03,570 --> 00:11:05,820 There's also no integrity check on it at all. 215 00:11:07,950 --> 00:11:09,900 And the vulnerability here 216 00:11:09,900 --> 00:11:12,600 is that it was a serialized object 217 00:11:12,600 --> 00:11:15,480 using an insecure serializer, 218 00:11:15,480 --> 00:11:18,183 which means that it was possible to exploit it. 219 00:11:19,480 --> 00:11:22,170 Now, serialization vulnerabilities are fairly well known 220 00:11:22,170 --> 00:11:25,080 for languages like C# or Java. 221 00:11:25,080 --> 00:11:26,730 They also affect Python, and Ruby, 222 00:11:26,730 --> 00:11:28,980 and a lot of other languages. 223 00:11:28,980 --> 00:11:32,043 But there hasn't been much published about it for macOS. 224 00:11:33,330 --> 00:11:36,243 Apple has a serialization format called NSCoding, 225 00:11:37,080 --> 00:11:38,220 and they also realized 226 00:11:38,220 --> 00:11:40,710 that these same serialization type vulnerabilities 227 00:11:40,710 --> 00:11:42,510 could affect it. 228 00:11:42,510 --> 00:11:46,050 So they introduced NSSecureCoding way back in 2012. 229 00:11:46,050 --> 00:11:50,430 So quite a long time ago already. 230 00:11:50,430 --> 00:11:54,456 And many users of NSCoding, where security is important, 231 00:11:54,456 --> 00:11:58,320 now use that NSSecureCoding for variants. 232 00:11:58,320 --> 00:12:02,100 So it's often used for communication between processes, 233 00:12:02,100 --> 00:12:05,730 and there, it's exclusively the secure coding. 234 00:12:05,730 --> 00:12:08,490 And it's even apparently used within iMessage. 235 00:12:08,490 --> 00:12:10,740 If you send a message to another user, 236 00:12:10,740 --> 00:12:13,950 then that message is a serialized object. 237 00:12:13,950 --> 00:12:15,660 So you can see that the security 238 00:12:15,660 --> 00:12:17,973 of the secure version is very important. 239 00:12:20,130 --> 00:12:22,560 And to demonstrate the difference between the insecure 240 00:12:22,560 --> 00:12:24,330 and the secure version. 241 00:12:24,330 --> 00:12:28,140 In the insecure version, you first create the object. 242 00:12:28,140 --> 00:12:29,197 And then you can check, 243 00:12:29,197 --> 00:12:31,887 "Is this the correct type of what I expect?" 244 00:12:33,060 --> 00:12:36,568 But for the secure version, you decode the object 245 00:12:36,568 --> 00:12:39,960 only if it is of a specific class. 246 00:12:39,960 --> 00:12:43,140 So the reason why this first version is insecure 247 00:12:43,140 --> 00:12:47,610 is that by the time you create it, it already exists. 248 00:12:47,610 --> 00:12:51,150 The constructor or something like that may have been called. 249 00:12:51,150 --> 00:12:53,793 Or the destructor might have been doing something. 250 00:12:54,810 --> 00:12:57,240 So yeah, that could lead to a vulnerability 251 00:12:57,240 --> 00:13:01,353 if those objects sort of just by existing. 252 00:13:04,410 --> 00:13:06,690 So how would an attack like that work? 253 00:13:06,690 --> 00:13:10,050 So you could create a new saved state. 254 00:13:10,050 --> 00:13:12,150 Write it to that directory with the new encryption key 255 00:13:12,150 --> 00:13:13,860 or something like that. 256 00:13:13,860 --> 00:13:17,165 And then ask the system to open the application. 257 00:13:17,165 --> 00:13:19,857 Then the application will automatically deserialize 258 00:13:19,857 --> 00:13:22,260 the object because it sees there is a saved state 259 00:13:22,260 --> 00:13:24,960 that it should be restoring. 260 00:13:24,960 --> 00:13:27,080 And then at that point, you are now deserializing 261 00:13:27,080 --> 00:13:30,450 that object in another application, 262 00:13:30,450 --> 00:13:33,633 which could mean code execution in another application. 263 00:13:34,600 --> 00:13:37,320 But of course, now is the challenge. 264 00:13:37,320 --> 00:13:40,203 What malicious object can we write there? 265 00:13:41,370 --> 00:13:44,610 So I spent some time looking at prior work for this. 266 00:13:44,610 --> 00:13:47,220 One of the famous projects for generating 267 00:13:47,220 --> 00:13:50,104 serialized objects for Java is YSoSerial. 268 00:13:50,104 --> 00:13:53,070 And for C#, there's YSoSerial .NET, 269 00:13:53,070 --> 00:13:55,773 but ysoserial-objective-c does not exist. 270 00:13:56,730 --> 00:13:57,630 I also spent some time 271 00:13:57,630 --> 00:14:00,180 digging through some Google Project Zero write-ups 272 00:14:00,180 --> 00:14:02,520 about serialization vulnerabilities, 273 00:14:02,520 --> 00:14:05,970 but those were targeting the secure version 274 00:14:05,970 --> 00:14:08,250 using specific vulnerabilities 275 00:14:08,250 --> 00:14:10,350 that have long since been fixed. 276 00:14:10,350 --> 00:14:11,910 So they were also not very useful 277 00:14:11,910 --> 00:14:13,413 for what I was trying to do. 278 00:14:14,760 --> 00:14:18,133 So I had to really come up with my own chain of objects 279 00:14:18,133 --> 00:14:20,403 to get that code execution. 280 00:14:24,150 --> 00:14:26,700 So how did I look for that? 281 00:14:26,700 --> 00:14:30,093 So I disassembled a lot of the objects that I could use. 282 00:14:31,710 --> 00:14:33,900 I loaded AppKit into a decompiler 283 00:14:33,900 --> 00:14:36,450 and looked through all of the initWithCoder functions, 284 00:14:36,450 --> 00:14:38,190 which are the methods that are being called 285 00:14:38,190 --> 00:14:40,537 when an object is deserialized. 286 00:14:41,850 --> 00:14:43,620 And I noticed that many of those classes 287 00:14:43,620 --> 00:14:47,790 do not support secure coding. 288 00:14:47,790 --> 00:14:50,310 Also, often those classes are not really intended 289 00:14:50,310 --> 00:14:52,950 to be sent to another process. 290 00:14:52,950 --> 00:14:55,332 And they were also not very interesting 291 00:14:55,332 --> 00:14:57,510 from an attacking point of view 292 00:14:57,510 --> 00:14:59,640 because they were not doing very much. 293 00:14:59,640 --> 00:15:03,622 They were just recursively decoding some instance variables, 294 00:15:03,622 --> 00:15:06,450 but that didn't really help me. 295 00:15:06,450 --> 00:15:09,243 I wanted to do more than just decoding an object. 296 00:15:10,590 --> 00:15:12,300 But eventually, I found a couple of objects 297 00:15:12,300 --> 00:15:13,323 that I could use. 298 00:15:14,910 --> 00:15:18,150 First of all, there's the NSRuleEditor. 299 00:15:18,150 --> 00:15:20,079 This is basically the widget that you have in mail, 300 00:15:20,079 --> 00:15:23,433 if you create a mail rule to configure that. 301 00:15:24,960 --> 00:15:28,680 When this object is deserialized, it takes two objects 302 00:15:28,680 --> 00:15:33,300 from the archive, an owner and a keypath. 303 00:15:33,300 --> 00:15:34,980 And then it creates a binding 304 00:15:34,980 --> 00:15:37,830 using that keypath to the owner. 305 00:15:37,830 --> 00:15:41,146 Now, bindings are a sort of reactive programming technique 306 00:15:41,146 --> 00:15:45,000 in macOS, which means that you can directly connect 307 00:15:45,000 --> 00:15:48,540 a model to a view without having to create a controller 308 00:15:48,540 --> 00:15:51,120 to do all of the boilerplate work 309 00:15:51,120 --> 00:15:53,463 of updating the view or updating the model. 310 00:15:55,440 --> 00:15:58,530 And one interesting thing about creating a binding 311 00:15:58,530 --> 00:16:01,830 is that you can sort of specify a keypath. 312 00:16:01,830 --> 00:16:04,560 So this can be if your model is a person, 313 00:16:04,560 --> 00:16:06,496 then you can bind to the person's name 314 00:16:06,496 --> 00:16:11,250 or the person's child's name or something like that. 315 00:16:11,250 --> 00:16:14,920 You can sort of go through nested properties with a keypath. 316 00:16:16,372 --> 00:16:20,100 And those are intended to be used for properties, 317 00:16:20,100 --> 00:16:21,300 but there's basically no check 318 00:16:21,300 --> 00:16:24,840 that you're trying to actually bind to a property. 319 00:16:24,840 --> 00:16:29,430 You can also specify a method with no arguments, 320 00:16:29,430 --> 00:16:32,280 and that will also be possible to bind to. 321 00:16:32,280 --> 00:16:34,560 And at the moment that you create the binding 322 00:16:34,560 --> 00:16:36,690 it will invoke that method. 323 00:16:36,690 --> 00:16:38,220 So it'll call that method 324 00:16:38,220 --> 00:16:41,160 to get an initial value for the binding. 325 00:16:41,160 --> 00:16:43,740 So by just deserializing this object, 326 00:16:43,740 --> 00:16:46,470 at this point, I could call new methods, 327 00:16:46,470 --> 00:16:48,780 but only if they have no arguments. 328 00:16:48,780 --> 00:16:50,283 But it's a good first step. 329 00:16:52,830 --> 00:16:54,240 Then is the second step. 330 00:16:54,240 --> 00:16:55,690 There's the NSCustomImageRep. 331 00:16:57,310 --> 00:16:59,670 This takes two objects from the archive, 332 00:16:59,670 --> 00:17:01,563 a drawObject and a drawMethod. 333 00:17:05,730 --> 00:17:08,284 And this is basically a selector. 334 00:17:08,284 --> 00:17:10,950 A selector is something like a function pointer, 335 00:17:10,950 --> 00:17:12,651 but for Objective-C methods. 336 00:17:12,651 --> 00:17:15,068 So it's the name of a method. 337 00:17:16,650 --> 00:17:19,560 And then in the draw function of this clause, 338 00:17:19,560 --> 00:17:21,060 it would call that method 339 00:17:21,060 --> 00:17:23,257 on the object that it deserialized. 340 00:17:25,710 --> 00:17:29,763 One argument's namely the image rep itself. 341 00:17:31,110 --> 00:17:34,020 So by combining this with the previous step, 342 00:17:34,020 --> 00:17:36,480 where we could call a method with no arguments, 343 00:17:36,480 --> 00:17:39,240 we can call the draw method on this object. 344 00:17:39,240 --> 00:17:42,280 And at this point, we can now call methods 345 00:17:43,770 --> 00:17:45,030 even if they have arguments, 346 00:17:45,030 --> 00:17:48,303 but we don't have any control yet over those arguments. 347 00:17:55,560 --> 00:17:56,700 Now for the sake of time, 348 00:17:56,700 --> 00:17:59,430 I have to skip a couple of steps here. 349 00:17:59,430 --> 00:18:01,020 Also for disclosure reasons, 350 00:18:01,020 --> 00:18:03,120 there's still some unfixed stuff in there. 351 00:18:04,680 --> 00:18:05,940 But I have two steps here now. 352 00:18:05,940 --> 00:18:08,190 I can call zero-argument methods. 353 00:18:08,190 --> 00:18:11,613 I could extend that to call arbitrary methods, 354 00:18:11,613 --> 00:18:15,283 but these are still only on objects that I can deserialize. 355 00:18:16,647 --> 00:18:20,310 And then I use the trick to also create objects 356 00:18:20,310 --> 00:18:22,263 that are not deserializable, 357 00:18:23,970 --> 00:18:27,273 objects that do not implement that protocol. 358 00:18:28,440 --> 00:18:30,582 And then I use a similar trick with a binding 359 00:18:30,582 --> 00:18:33,903 to call zero-argument methods on those objects. 360 00:18:34,770 --> 00:18:37,830 And another trick to call 361 00:18:37,830 --> 00:18:40,350 arbitrary methods on those objects. 362 00:18:40,350 --> 00:18:41,763 And at this point, 363 00:18:43,140 --> 00:18:45,330 I also have control of the arguments here. 364 00:18:45,330 --> 00:18:47,580 So at this point, I can basically call 365 00:18:47,580 --> 00:18:49,950 any Objective-C method that I want 366 00:18:49,950 --> 00:18:51,870 with arguments that I specify. 367 00:18:51,870 --> 00:18:53,310 So one thing I could do here 368 00:18:53,310 --> 00:18:56,583 is just evaluate AppleScript within the process. 369 00:18:57,450 --> 00:19:00,150 So this is already very powerful. 370 00:19:00,150 --> 00:19:02,373 So for example, if I was attacking mail, 371 00:19:02,373 --> 00:19:05,400 then I could use some AppleScripts to copy some files 372 00:19:05,400 --> 00:19:07,140 from the data vaults to a location 373 00:19:07,140 --> 00:19:08,394 where any process can read it, 374 00:19:08,394 --> 00:19:12,690 or just read the contents and send it off to somewhere else. 375 00:19:12,690 --> 00:19:16,150 I can also execute the shell script or something like that 376 00:19:17,280 --> 00:19:19,410 for my AppleScript. 377 00:19:19,410 --> 00:19:21,780 So at this point, I was now executing code 378 00:19:21,780 --> 00:19:23,338 within another process, 379 00:19:23,338 --> 00:19:25,897 but this was limited to AppleScripts. 380 00:19:27,072 --> 00:19:30,543 And for the attacks that I wanted to do later on, 381 00:19:32,582 --> 00:19:35,220 for two of them, this was enough. 382 00:19:35,220 --> 00:19:37,170 But for one of them, I really needed something 383 00:19:37,170 --> 00:19:39,780 that was equivalent to executing native codes. 384 00:19:39,780 --> 00:19:42,026 So this AppleScript is fairly limited. 385 00:19:42,026 --> 00:19:43,280 There's no... 386 00:19:44,250 --> 00:19:46,920 Yeah, there's restriction in what you can do. 387 00:19:46,920 --> 00:19:49,293 So I had to go one step further. 388 00:19:52,380 --> 00:19:55,338 But as I mentioned, there's this hardened runtime 389 00:19:55,338 --> 00:19:59,160 that is meant to make attacks like this harder. 390 00:19:59,160 --> 00:20:03,330 So I could not create any memory pages that were JIT map, 391 00:20:03,330 --> 00:20:07,590 so not any executable and writable pages. 392 00:20:07,590 --> 00:20:10,110 I could not create unsigned memory. 393 00:20:10,110 --> 00:20:11,850 I could not load any libraries 394 00:20:11,850 --> 00:20:16,710 that were not signed by either Apple or the same developer. 395 00:20:16,710 --> 00:20:19,200 This is library validation. 396 00:20:19,200 --> 00:20:22,380 I could not use dynamic link editor environment variables, 397 00:20:22,380 --> 00:20:24,483 which is not relevant here. 398 00:20:25,980 --> 00:20:28,200 So it was really tricky to figure out 399 00:20:28,200 --> 00:20:30,773 how can I execute something that's equivalent to native code 400 00:20:30,773 --> 00:20:32,913 within all of these restrictions. 401 00:20:33,780 --> 00:20:38,780 And then I noticed that I could load Python.framework. 402 00:20:38,880 --> 00:20:43,274 So Python was included in macOS at that time, 403 00:20:43,274 --> 00:20:44,940 and it was signed by Apple, 404 00:20:44,940 --> 00:20:47,520 so I can just load it into any process. 405 00:20:47,520 --> 00:20:49,350 And if you import the ctypes module, 406 00:20:49,350 --> 00:20:51,240 then you can evaluate basically something 407 00:20:51,240 --> 00:20:52,650 that's equivalent to native code. 408 00:20:52,650 --> 00:20:53,970 You can call C functions. 409 00:20:53,970 --> 00:20:57,213 You can create structures. Stuff like that. 410 00:21:04,064 --> 00:21:07,260 And also ctypes does not conflict 411 00:21:07,260 --> 00:21:09,480 with any of the restrictions of the hardened runtime. 412 00:21:09,480 --> 00:21:11,850 So many NET programming languages, 413 00:21:11,850 --> 00:21:14,790 you can create bindings, but they often need to be compiled 414 00:21:14,790 --> 00:21:17,763 and that doesn't work due to the hardened runtime. 415 00:21:19,887 --> 00:21:21,120 And now, I have this challenge. 416 00:21:21,120 --> 00:21:22,741 I can call Objective-C methods, 417 00:21:22,741 --> 00:21:25,410 but I wanted to evaluate Python. 418 00:21:25,410 --> 00:21:27,257 And Python doesn't have an Objective-C API 419 00:21:27,257 --> 00:21:28,920 that I could go into. 420 00:21:28,920 --> 00:21:30,810 So I needed some intermediate step 421 00:21:30,810 --> 00:21:32,433 to bridge these two together. 422 00:21:34,200 --> 00:21:37,380 So I found another framework that I could use. 423 00:21:37,380 --> 00:21:40,203 And this is the AppleScript-Objective-C bridge. 424 00:21:41,147 --> 00:21:43,920 Now, this is basically Apple Script 425 00:21:43,920 --> 00:21:47,640 combined with access to the Objective-C runtime. 426 00:21:47,640 --> 00:21:52,080 So AppleScript, it can basically call Objective-C methods, 427 00:21:52,080 --> 00:21:54,453 create Objective-C objects. 428 00:21:55,860 --> 00:21:58,110 And one interesting thing about this 429 00:21:58,110 --> 00:22:02,340 is that you can load new scripts into a process, 430 00:22:02,340 --> 00:22:05,040 but even when you have that hardened runtime 431 00:22:05,040 --> 00:22:06,870 and library validation, 432 00:22:06,870 --> 00:22:10,590 the scripts can be loaded from a bundle that is not signed. 433 00:22:10,590 --> 00:22:13,450 So I could put some new scripts into a new bundle, 434 00:22:13,450 --> 00:22:16,230 load only the scripts from that bundle, 435 00:22:16,230 --> 00:22:19,473 and they would be added to the Objective-C runtime. 436 00:22:21,960 --> 00:22:25,170 Now, with this, I could create Objective-C objects, 437 00:22:25,170 --> 00:22:27,930 call methods, all of these I could already do before. 438 00:22:27,930 --> 00:22:31,020 But what is new here is that I could call C-functions 439 00:22:31,020 --> 00:22:34,443 from Objective-C, or the AppleScript-Objective-C bridge. 440 00:22:36,480 --> 00:22:39,370 But one annoying restriction of this bridge 441 00:22:39,370 --> 00:22:43,800 is that I could not create non-object pointers, 442 00:22:43,800 --> 00:22:47,730 so pointers to anything else than an Objective-C object. 443 00:22:47,730 --> 00:22:49,226 I could not create structs. 444 00:22:49,226 --> 00:22:51,270 And I could not work with any C strings. 445 00:22:51,270 --> 00:22:53,733 That's just not supported by that language. 446 00:22:55,620 --> 00:22:59,520 And Python, in order to basically call anything, 447 00:22:59,520 --> 00:23:03,213 you need to pass either a file path or the Python code 448 00:23:03,213 --> 00:23:04,980 that you want to evaluate. 449 00:23:04,980 --> 00:23:07,020 So you really need a character pointer 450 00:23:07,020 --> 00:23:11,010 to include either the path or some string 451 00:23:11,010 --> 00:23:12,310 that you want to evaluate. 452 00:23:13,860 --> 00:23:16,200 But then finally, I had this breakthrough 453 00:23:16,200 --> 00:23:17,190 of something that worked. 454 00:23:17,190 --> 00:23:21,420 I could call Py_Main with 0 and NULL, 455 00:23:21,420 --> 00:23:25,053 and that's a valid object in AppleScript-Objective-C. 456 00:23:25,920 --> 00:23:27,960 And when you do this, it basically works 457 00:23:27,960 --> 00:23:30,240 as if you start a Python REPL. 458 00:23:30,240 --> 00:23:33,570 So it reads a script from standard input, 459 00:23:33,570 --> 00:23:36,750 and then acts basically just like Python would 460 00:23:36,750 --> 00:23:39,000 if you launched it on the command line. 461 00:23:39,000 --> 00:23:42,990 So with this, I could then import ctypes 462 00:23:42,990 --> 00:23:46,893 and evaluate codes that's equivalent to native code. 463 00:23:48,568 --> 00:23:52,290 Now, if you think that AppleScript or Objective-C... 464 00:23:52,290 --> 00:23:53,621 Many people say it's verbose. 465 00:23:53,621 --> 00:23:55,680 But if you don't think it's verbose enough, 466 00:23:55,680 --> 00:23:56,640 then you really should work 467 00:23:56,640 --> 00:23:59,580 with the AppleScript-Objective-C bridge. 468 00:23:59,580 --> 00:24:01,290 I have an example here. 469 00:24:01,290 --> 00:24:03,330 So this is how you would call a method 470 00:24:03,330 --> 00:24:06,180 in the AppleScript-Objective-C bridge. 471 00:24:06,180 --> 00:24:10,890 So you need to use that apostrophe to call new methods. 472 00:24:10,890 --> 00:24:12,660 And you get this really weird sentences 473 00:24:12,660 --> 00:24:14,790 that sort of look like they're supposed 474 00:24:14,790 --> 00:24:16,984 to be readable English, 475 00:24:16,984 --> 00:24:20,253 but it's really incomprehensible as a language. 476 00:24:25,380 --> 00:24:30,380 So to summarize the steps needed to get the code execution. 477 00:24:31,380 --> 00:24:32,880 We can evaluate AppleScripts 478 00:24:32,880 --> 00:24:35,520 with the AppleScript-Objective-C bridge. 479 00:24:35,520 --> 00:24:37,920 Then we can evaluate Python. 480 00:24:37,920 --> 00:24:40,200 We can import the ctypes module. 481 00:24:40,200 --> 00:24:42,150 And at this point, you can just evaluate code 482 00:24:42,150 --> 00:24:44,610 that's just equivalent to native code, 483 00:24:44,610 --> 00:24:46,721 despite all of the restrictions of the hardened runtime 484 00:24:46,721 --> 00:24:48,063 and stuff like that. 485 00:24:50,520 --> 00:24:52,920 Now, how could we exploit this? 486 00:24:52,920 --> 00:24:54,720 I wanted to really make sure that I had 487 00:24:54,720 --> 00:24:56,680 all of the impact that this could have 488 00:24:58,470 --> 00:25:00,690 described in a report to Apple. 489 00:25:00,690 --> 00:25:02,700 So I tried to look for all of the different ways 490 00:25:02,700 --> 00:25:05,340 that this vulnerability could be applied. 491 00:25:05,340 --> 00:25:08,493 So first of all, to escape the Mac application sandbox. 492 00:25:11,117 --> 00:25:13,890 Now, what you see here is an open panel. 493 00:25:13,890 --> 00:25:17,250 And this may look like a very boring window 494 00:25:17,250 --> 00:25:20,580 you see 100 times a day if you use macOS, 495 00:25:20,580 --> 00:25:23,760 but technically, it's actually quite complicated 496 00:25:23,760 --> 00:25:26,370 because if you are in the sandbox application, 497 00:25:26,370 --> 00:25:29,640 then that application doesn't know about all of your files. 498 00:25:29,640 --> 00:25:32,640 It cannot list all the files that you have 499 00:25:32,640 --> 00:25:34,590 because it's sandbox. 500 00:25:34,590 --> 00:25:36,237 But if the user wants to open a file, 501 00:25:36,237 --> 00:25:38,580 then it would be really annoying if they cannot see 502 00:25:38,580 --> 00:25:40,880 their files in the application they are using. 503 00:25:42,360 --> 00:25:45,483 So Apple created this technology for that. 504 00:25:47,670 --> 00:25:51,960 But while the window itself is part of the application, 505 00:25:51,960 --> 00:25:53,730 the actual contents of the window 506 00:25:53,730 --> 00:25:56,640 are being drawn by a different process. 507 00:25:56,640 --> 00:25:59,340 It basically works like an iframe on a website. 508 00:25:59,340 --> 00:26:03,243 So it's a different process drawing those contents. 509 00:26:04,500 --> 00:26:07,170 And it's an open and save panel service. 510 00:26:07,170 --> 00:26:09,127 So this service does have access to your files. 511 00:26:09,127 --> 00:26:11,490 It's not sandbox. 512 00:26:11,490 --> 00:26:14,520 And when you select a file in this panel, 513 00:26:14,520 --> 00:26:16,830 and click Okay, then the application 514 00:26:16,830 --> 00:26:19,236 will get temporary access to that file 515 00:26:19,236 --> 00:26:21,783 that it can then use to read or write that file. 516 00:26:23,160 --> 00:26:24,870 And one thing I noticed about this open panel 517 00:26:24,870 --> 00:26:27,570 if it was being opened 518 00:26:27,570 --> 00:26:31,920 is that this open and panel save service was loading 519 00:26:31,920 --> 00:26:34,140 its saved state from the same directory 520 00:26:34,140 --> 00:26:35,823 as the application itself. 521 00:26:36,930 --> 00:26:41,234 So by creating a new malicious serialized object 522 00:26:41,234 --> 00:26:44,580 into that saved state, then triggering the opening 523 00:26:44,580 --> 00:26:47,640 of such a panel, it is possible to execute code 524 00:26:47,640 --> 00:26:51,060 within that open and save panel service. 525 00:26:51,060 --> 00:26:53,610 And that service was not sandbox, so at that point, 526 00:26:53,610 --> 00:26:55,233 I have escaped sandbox. 527 00:26:57,090 --> 00:27:00,780 I'm not completely sure why it was sharing that saved state, 528 00:27:00,780 --> 00:27:03,406 but it might have something to do with if the user 529 00:27:03,406 --> 00:27:08,160 resizes that window, and then they shut down their Mac, 530 00:27:08,160 --> 00:27:11,190 then it might need to restore the state of that window 531 00:27:11,190 --> 00:27:13,140 complete with the state of the panel, 532 00:27:13,140 --> 00:27:15,840 and it might need to be separated by application. 533 00:27:15,840 --> 00:27:18,033 Something like that. I'm not entirely sure. 534 00:27:19,440 --> 00:27:21,510 And this was fixed earlier than the rest by Apple. 535 00:27:21,510 --> 00:27:25,197 This was fixed in 11.3 by no longer sharing 536 00:27:25,197 --> 00:27:27,723 the same saved state directory. 537 00:27:30,439 --> 00:27:32,190 And the next step was to elevate 538 00:27:32,190 --> 00:27:33,483 privileges to root. 539 00:27:34,980 --> 00:27:37,260 And for this, I basically used the same technique 540 00:27:37,260 --> 00:27:40,230 already found by Ilias Morad, 541 00:27:40,230 --> 00:27:43,080 written in the Unauthd - Logic Bugs For the Win write-up. 542 00:27:44,580 --> 00:27:47,220 I looked for an application with the entitlement 543 00:27:47,220 --> 00:27:51,142 com.apple.private.AuthorizationServices 544 00:27:51,142 --> 00:27:55,110 with the value for system.install.apple.software. 545 00:27:55,110 --> 00:27:58,080 And what this entitlement means is that this application 546 00:27:58,080 --> 00:28:02,280 is allowed to install packages that are signed by Apple 547 00:28:02,280 --> 00:28:05,010 without any authorization by the user. 548 00:28:05,010 --> 00:28:07,510 User doesn't even see that something is happening. 549 00:28:08,790 --> 00:28:10,200 So this is used, for example, 550 00:28:10,200 --> 00:28:13,633 by the Install Command Line Developer Tools application, 551 00:28:13,633 --> 00:28:16,923 which can update certain parts of the system. 552 00:28:23,190 --> 00:28:26,130 And then this can be combined with this specific package, 553 00:28:26,130 --> 00:28:29,133 the macOS Public Beta Access Utility package. 554 00:28:30,960 --> 00:28:33,810 This package, when it's installed to a disk, 555 00:28:33,810 --> 00:28:35,460 it will run a post-install script. 556 00:28:35,460 --> 00:28:37,500 So after the installation is finished, 557 00:28:37,500 --> 00:28:41,100 it will run a script as root from the disk 558 00:28:41,100 --> 00:28:42,350 that you installed it to. 559 00:28:43,590 --> 00:28:44,423 But there's no check 560 00:28:44,423 --> 00:28:48,630 that you actually installed it through a macOS disk. 561 00:28:48,630 --> 00:28:50,773 You can just install it through any disk, 562 00:28:50,773 --> 00:28:53,490 disk image, RAM disk, something like that. 563 00:28:53,490 --> 00:28:56,130 And it will still run that same path, 564 00:28:56,130 --> 00:28:58,743 the same command on that disk. 565 00:29:00,510 --> 00:29:02,880 So because mounting a disk does not require 566 00:29:02,880 --> 00:29:05,670 any root privileges, you can mount a disk, 567 00:29:05,670 --> 00:29:07,980 put a file on the same path, 568 00:29:07,980 --> 00:29:10,170 perform the installation of this package. 569 00:29:10,170 --> 00:29:11,700 And then in the post-install script, 570 00:29:11,700 --> 00:29:13,860 it will invoke that script as root, 571 00:29:13,860 --> 00:29:16,503 and therefore, elevate privileges to root. 572 00:29:19,860 --> 00:29:21,540 And then finally to bypass SIP, 573 00:29:21,540 --> 00:29:24,183 or the SIP filesystem restrictions part. 574 00:29:26,880 --> 00:29:27,843 Because I wanted to make sure 575 00:29:27,843 --> 00:29:32,280 that we had all of the possible attack service mapped out, 576 00:29:32,280 --> 00:29:34,620 I looked at all of the applications I could find 577 00:29:34,620 --> 00:29:38,220 with what kind of entitlements they might have. 578 00:29:38,220 --> 00:29:40,970 So not just everything included in macOS, 579 00:29:40,970 --> 00:29:44,730 we also looked at the data installation disk image. 580 00:29:44,730 --> 00:29:47,130 And there, I found this very interesting application, 581 00:29:47,130 --> 00:29:49,473 the macOS Update Assistant application. 582 00:29:50,670 --> 00:29:52,920 And it turns out, this has an entitlement, 583 00:29:52,920 --> 00:29:57,540 com.apple.rootless.install.heritable. 584 00:29:57,540 --> 00:29:59,970 And what this means is that it's basically allowed 585 00:29:59,970 --> 00:30:02,370 to write to any SIP protected location 586 00:30:02,370 --> 00:30:07,260 or read from any SIP protected location on disk. 587 00:30:07,260 --> 00:30:09,120 And as a bonus, it's also heritable. 588 00:30:09,120 --> 00:30:10,290 So any subprocesses that start 589 00:30:11,242 --> 00:30:13,860 will also have the same permission, 590 00:30:13,860 --> 00:30:16,042 which is very easy because then you can just spawn 591 00:30:16,042 --> 00:30:19,293 reverse shell instead of having to work in process. 592 00:30:23,850 --> 00:30:26,460 And what can we do with a SIP bypass like this? 593 00:30:26,460 --> 00:30:28,373 So as mentioned earlier, 594 00:30:28,373 --> 00:30:31,860 you can read the mail database of the user. 595 00:30:31,860 --> 00:30:34,170 You can read the messages database, the Safari history, 596 00:30:34,170 --> 00:30:35,730 stuff like that. 597 00:30:35,730 --> 00:30:38,100 We can also grant our own application permission 598 00:30:38,100 --> 00:30:39,270 to use the webcam. 599 00:30:39,270 --> 00:30:41,430 So we can just add ourself to the database, 600 00:30:41,430 --> 00:30:43,530 and then we can use the webcam 601 00:30:43,530 --> 00:30:45,783 without any permission by the user. 602 00:30:48,270 --> 00:30:50,520 We could also persist very well into the system 603 00:30:50,520 --> 00:30:52,224 because we can write ourself to a location 604 00:30:52,224 --> 00:30:54,480 that is SIP protected. 605 00:30:54,480 --> 00:30:56,670 So for example, we could also remove 606 00:30:56,670 --> 00:31:00,123 the malware removal tool Apple uses to delete malware. 607 00:31:01,380 --> 00:31:04,590 Maybe even replace it with our own malware. 608 00:31:04,590 --> 00:31:07,650 And at that point, Apple could still delete us 609 00:31:07,650 --> 00:31:10,140 from the system, but any other AV vendor 610 00:31:10,140 --> 00:31:13,140 would not be able to delete it because it was SIP protected. 611 00:31:14,910 --> 00:31:17,970 And now finally, we can also load a kernel extension 612 00:31:17,970 --> 00:31:19,920 without user approval. 613 00:31:19,920 --> 00:31:21,150 So normally loading a kernel extension 614 00:31:21,150 --> 00:31:23,940 creates a prompt like that, and then the user still needs 615 00:31:23,940 --> 00:31:26,310 to click a couple of times in the security preferences 616 00:31:26,310 --> 00:31:28,260 to really make sure that they want 617 00:31:28,260 --> 00:31:29,670 to load that kernel extension. 618 00:31:29,670 --> 00:31:31,680 But we can just preapprove 619 00:31:31,680 --> 00:31:33,663 any kernel extension to be loaded. 620 00:31:35,070 --> 00:31:37,680 Now, that doesn't directly give kernel code execution 621 00:31:37,680 --> 00:31:41,520 because you still need a validly signed kernel extension, 622 00:31:41,520 --> 00:31:44,400 and because Apple's deprecating kernel extensions, 623 00:31:44,400 --> 00:31:45,347 getting such a certificate 624 00:31:45,347 --> 00:31:48,990 is pretty much impossible right now. 625 00:31:48,990 --> 00:31:51,690 But because you can approve just any kernel extension, 626 00:31:51,690 --> 00:31:53,400 we could look at all of them. 627 00:31:53,400 --> 00:31:56,340 Try to find one with a vulnerability we could abuse, 628 00:31:56,340 --> 00:31:59,237 and then we could also get kernel code execution 629 00:31:59,237 --> 00:32:01,440 if we wanted to. 630 00:32:01,440 --> 00:32:04,200 But with the SIP filesystem bypass, 631 00:32:04,200 --> 00:32:05,700 we already have a lot of access 632 00:32:05,700 --> 00:32:07,770 to all of the files in the system. 633 00:32:07,770 --> 00:32:11,160 So we have already compromised a lot of the data there 634 00:32:11,160 --> 00:32:13,710 and kernel code execution. 635 00:32:13,710 --> 00:32:14,973 It would be a nice bonus, 636 00:32:15,856 --> 00:32:18,693 but wouldn't give that much extra access to the system. 637 00:32:20,700 --> 00:32:23,173 Now, here's a video to demonstrate this attack. 638 00:32:23,173 --> 00:32:27,690 This is a macOS 11.2.3, I think. 639 00:32:27,690 --> 00:32:28,613 First of all, it demonstrates 640 00:32:28,613 --> 00:32:32,643 that the sandbox application is actually sandbox. 641 00:32:35,670 --> 00:32:38,883 And then it will do the three steps in order here. 642 00:32:39,900 --> 00:32:42,180 The privilege escalation step is a little bit slower 643 00:32:42,180 --> 00:32:44,370 because it needs to create that RAM disk 644 00:32:44,370 --> 00:32:46,070 through the installation for that. 645 00:32:47,340 --> 00:32:48,750 So as I'm not trying to be subtle, 646 00:32:48,750 --> 00:32:51,500 you can see the disk image appear on the desktop there. 647 00:32:54,450 --> 00:32:57,100 And then the next step should be a little bit faster. 648 00:32:59,580 --> 00:33:03,030 And as you can see here, we now have a root shell, 649 00:33:03,030 --> 00:33:05,280 but not only that, we can also go 650 00:33:05,280 --> 00:33:08,880 to the system policy configuration directory, 651 00:33:08,880 --> 00:33:09,900 which is the location 652 00:33:09,900 --> 00:33:12,540 where the approved kernel extensions are stored 653 00:33:12,540 --> 00:33:16,080 in a database, which is a very sensitive location 654 00:33:16,080 --> 00:33:18,090 normally protected by SIP. 655 00:33:18,090 --> 00:33:19,410 And as we can demonstrate here, 656 00:33:19,410 --> 00:33:21,993 we can write a new file into this directory. 657 00:33:23,661 --> 00:33:26,661 (audience applauds) 658 00:33:32,130 --> 00:33:33,240 Thank you. 659 00:33:33,240 --> 00:33:35,987 And now about the fixes. 660 00:33:35,987 --> 00:33:40,080 So with the release of Monterey, 661 00:33:40,080 --> 00:33:43,680 that new method that I showed at the start, was added. 662 00:33:43,680 --> 00:33:45,450 And applications can now indicate 663 00:33:45,450 --> 00:33:48,453 that they only accept secure serialized objects. 664 00:33:49,770 --> 00:33:52,290 So Apple enabled this for all of their own applications, 665 00:33:52,290 --> 00:33:55,740 so the exploits previously are no longer possible. 666 00:33:55,740 --> 00:33:59,550 But third party applications may use that ability 667 00:33:59,550 --> 00:34:02,103 to store their own objects in that saved state. 668 00:34:03,150 --> 00:34:06,300 So therefore, that method is needed for applications 669 00:34:06,300 --> 00:34:09,870 so they can opt out if they don't support that yet. 670 00:34:09,870 --> 00:34:11,896 I'm not completely clear if it's still exploitable 671 00:34:11,896 --> 00:34:15,840 if the applications don't store any objects, 672 00:34:15,840 --> 00:34:17,940 I still need to look into that a bit more. 673 00:34:18,900 --> 00:34:21,993 This was reported to Apple on December 4, 2020, 674 00:34:22,850 --> 00:34:24,810 and then they fixed the sandbox escape 675 00:34:24,810 --> 00:34:28,473 earlier than the rest in 11.3 in April. 676 00:34:29,463 --> 00:34:33,060 And then they fixed it completely with the release 677 00:34:33,060 --> 00:34:36,183 of macOS Monterey, which was in October 2021. 678 00:34:37,620 --> 00:34:41,130 Now, originally I thought they did not backport this fix 679 00:34:41,130 --> 00:34:44,070 to the two older macOS versions. 680 00:34:44,070 --> 00:34:46,470 Generally, Apple keeps supporting three versions, 681 00:34:46,470 --> 00:34:49,260 so the previous one and the one before. 682 00:34:49,260 --> 00:34:51,360 But in the release notes, it was only mentioned 683 00:34:51,360 --> 00:34:54,870 for macOS Monterey when it was released. 684 00:34:54,870 --> 00:34:56,967 So I thought they didn't backport it, 685 00:34:56,967 --> 00:34:59,220 but then I was working on these slides, 686 00:34:59,220 --> 00:35:01,893 and two weeks ago or something like that, I noticed 687 00:35:01,893 --> 00:35:05,910 that Apple had updated the release notes 688 00:35:05,910 --> 00:35:07,856 of the Catalina security update. 689 00:35:07,856 --> 00:35:10,350 That was at the same time as Monterey. 690 00:35:10,350 --> 00:35:13,800 They updated this back in May, so half a year later. 691 00:35:13,800 --> 00:35:15,570 And then they also now list 692 00:35:15,570 --> 00:35:17,433 this vulnerability as being fixed. 693 00:35:18,690 --> 00:35:23,690 And a week before now, Apple Product Security 694 00:35:23,850 --> 00:35:26,745 emailed me spontaneously with, 695 00:35:26,745 --> 00:35:29,640 "We see you are going to do a talk at DEF CON. 696 00:35:29,640 --> 00:35:31,110 Would you be willing to tell us 697 00:35:31,110 --> 00:35:32,310 what you're going to talk about? 698 00:35:32,310 --> 00:35:34,770 Maybe we could provide some feedback." 699 00:35:34,770 --> 00:35:36,187 So I just asked them, 700 00:35:36,187 --> 00:35:40,260 "Well, is it fixed in Catalina and Big Sur? 701 00:35:40,260 --> 00:35:43,170 Because it was not in the release notes for Big Sur, 702 00:35:43,170 --> 00:35:45,240 which is weird because it was in Catalina, 703 00:35:45,240 --> 00:35:47,237 which is the older version." 704 00:35:47,237 --> 00:35:50,011 And then yesterday at about 8:00 am, 705 00:35:50,011 --> 00:35:51,667 they got back to me and told me, 706 00:35:51,667 --> 00:35:54,780 "Yeah, it's supposed to be fixed in all of these. 707 00:35:54,780 --> 00:35:58,230 If you can still reproduce it, then please let us know." 708 00:35:58,230 --> 00:36:01,140 But that really wasn't enough time for me to look into it 709 00:36:01,140 --> 00:36:03,633 a bit more if it's actually fixed. 710 00:36:05,340 --> 00:36:07,170 Yeah, I still need to look a bit more 711 00:36:07,170 --> 00:36:10,233 into whether it was actually fixed in those older versions. 712 00:36:13,260 --> 00:36:17,520 So to conclude, macOS has a security boundary 713 00:36:17,520 --> 00:36:21,120 between processes, not only between users. 714 00:36:21,120 --> 00:36:24,280 And process injection vulnerabilities are now very important 715 00:36:25,230 --> 00:36:28,290 because it can create those boundaries between processes 716 00:36:28,290 --> 00:36:30,060 and allow dangerous entitlements 717 00:36:30,060 --> 00:36:31,863 to be used by other processes. 718 00:36:32,730 --> 00:36:37,293 The CVE-2021-30873 was a process injection vulnerability 719 00:36:37,293 --> 00:36:41,580 affecting all AppKit based applications, 720 00:36:41,580 --> 00:36:43,620 therefore allowing all powerful entitlements 721 00:36:43,620 --> 00:36:45,213 to be abused by malware. 722 00:36:46,290 --> 00:36:48,390 We demonstrated how it could be applied 723 00:36:48,390 --> 00:36:51,270 to escape the sandbox, elevate privileges to root, 724 00:36:51,270 --> 00:36:54,270 and to bypass the filesystem restrictions of SIP. 725 00:36:54,270 --> 00:36:57,033 And it was fixed in October last year. 726 00:36:58,650 --> 00:37:01,020 Some takeaways here. 727 00:37:01,020 --> 00:37:05,070 macOS security keeps adding more and more defensive layers, 728 00:37:05,070 --> 00:37:06,180 but adding new layers 729 00:37:06,180 --> 00:37:09,690 to an established system is quite difficult. 730 00:37:09,690 --> 00:37:13,410 Code written 10 years ago or more than that 731 00:37:13,410 --> 00:37:15,990 can suddenly become attack surface 732 00:37:15,990 --> 00:37:18,790 that nobody has thought about when it was being written. 733 00:37:19,800 --> 00:37:21,600 And also, I think an interesting point here 734 00:37:21,600 --> 00:37:25,080 is that the effort of attackers may not really increase 735 00:37:25,080 --> 00:37:26,730 if you add more layers, 736 00:37:26,730 --> 00:37:28,590 if you can just use the same bug 737 00:37:28,590 --> 00:37:33,540 for bypassing multiple layers in the same way. 738 00:37:33,540 --> 00:37:35,580 So to make sure that security layers work, 739 00:37:35,580 --> 00:37:37,860 you really need to make sure that they actually 740 00:37:39,210 --> 00:37:42,210 are different enough that you cannot use the same technique. 741 00:37:43,710 --> 00:37:47,190 I have some references here about work that I used, 742 00:37:47,190 --> 00:37:48,870 the write-up from Ilias, for example, 743 00:37:48,870 --> 00:37:52,023 and some other resources about serialized objects. 744 00:37:53,910 --> 00:37:55,680 And we will publish a full write-up 745 00:37:55,680 --> 00:37:58,383 with a lot more technical details that I had to skip. 746 00:37:58,383 --> 00:38:03,000 I will do this over the next couple of days at most. 747 00:38:03,000 --> 00:38:04,260 If you want to know more, 748 00:38:04,260 --> 00:38:06,930 follow me on Twitter or our research department. 749 00:38:06,930 --> 00:38:11,582 And I'll take any questions if you have them. 750 00:38:11,582 --> 00:38:14,582 (audience applauds) 751 00:38:28,673 --> 00:38:30,988 - [Audience Member] Great job. 752 00:38:30,988 --> 00:38:35,422 Is there remaining risk for individuals or enterprises, 753 00:38:35,422 --> 00:38:37,976 and what should individuals and enterprises do 754 00:38:37,976 --> 00:38:41,144 to protect against these kinds of vulnerabilities? 755 00:38:41,144 --> 00:38:43,020 - Okay. So the question is, "Is there remaining risk 756 00:38:43,020 --> 00:38:46,020 for enterprises and users?" 757 00:38:46,020 --> 00:38:49,080 Well, I don't really know if older versions 758 00:38:49,080 --> 00:38:51,750 of macOS are vulnerable, as I said at the end. 759 00:38:51,750 --> 00:38:53,594 So updating to the latest version 760 00:38:53,594 --> 00:38:56,853 would be a good recommendation and keeping updated. 761 00:38:58,080 --> 00:38:59,779 Yeah, if you're developing an application yourself, 762 00:38:59,779 --> 00:39:02,670 then being aware of this type of vulnerability 763 00:39:02,670 --> 00:39:04,260 would also be important. 764 00:39:04,260 --> 00:39:07,323 But otherwise, users cannot really do that much about this. 765 00:39:08,460 --> 00:39:09,540 There's not really any tools 766 00:39:09,540 --> 00:39:11,840 that can protect against something this... 767 00:39:14,070 --> 00:39:15,470 Against this type of attack.