1 00:00:00,360 --> 00:00:03,360 - Welcome to the last talk of Saturday, 2 00:00:03,360 --> 00:00:06,180 today, here at DEF CON, in track three. 3 00:00:06,180 --> 00:00:09,810 So, this is the CSRF Resurrections, 4 00:00:09,810 --> 00:00:13,578 starring the Unholy Trinity: Service Worker of PWA, 5 00:00:13,578 --> 00:00:17,910 SameSite of HTTP Cookie and Fetch. 6 00:00:17,910 --> 00:00:20,224 Please welcome Dongsung Kim. 7 00:00:20,224 --> 00:00:23,224 (audience applauds) 8 00:00:27,060 --> 00:00:27,893 - Oh. 9 00:00:30,030 --> 00:00:30,863 Right. 10 00:00:32,070 --> 00:00:35,844 Sorry for making you wait. Thank you. (laughs) 11 00:00:35,844 --> 00:00:37,713 (audience applauds) 12 00:00:37,713 --> 00:00:39,332 Well, this is the last time so I can use 13 00:00:39,332 --> 00:00:41,790 whatever the time I have. 14 00:00:41,790 --> 00:00:43,020 Thank you. Good evening. 15 00:00:43,020 --> 00:00:44,970 Thank you for all for coming to my talk. 16 00:00:44,970 --> 00:00:47,400 So great to see you all in person. 17 00:00:47,400 --> 00:00:49,860 So I'm excited to present my research, 18 00:00:49,860 --> 00:00:51,210 The CSRF Resurrections! 19 00:00:51,210 --> 00:00:54,053 Starring the Unholy Trinity: Service Worker of PWA, 20 00:00:54,053 --> 00:00:56,880 SameSite of HTTP Cookie, and Fetch. 21 00:00:56,880 --> 00:00:58,530 That's a long name. 22 00:00:58,530 --> 00:01:00,870 Before we begin, let me introduce myself. 23 00:01:00,870 --> 00:01:04,230 My name is Dongsung Kim, I'm an IT Security Expert 24 00:01:04,230 --> 00:01:06,480 at Security Office. 25 00:01:06,480 --> 00:01:08,610 We are based in Sweden and in South Korea, 26 00:01:08,610 --> 00:01:10,650 and are part of the Truesec Group. 27 00:01:10,650 --> 00:01:12,150 If you have any questions or comments, 28 00:01:12,150 --> 00:01:14,013 please feel free to reach out. 29 00:01:16,320 --> 00:01:19,410 So firstly, let's touch on the current landscape 30 00:01:19,410 --> 00:01:22,470 of the web and what we're going to discuss. 31 00:01:22,470 --> 00:01:25,680 The web platform is evolving faster than ever before. 32 00:01:25,680 --> 00:01:29,250 Every day, new features are, and APIs are constantly 33 00:01:29,250 --> 00:01:31,830 being proposed, developed, tested, shipped, 34 00:01:31,830 --> 00:01:32,793 and standardized. 35 00:01:33,660 --> 00:01:35,850 They not only include aesthetic improvements, 36 00:01:35,850 --> 00:01:40,850 but also open powerful operations to web developers 37 00:01:40,877 --> 00:01:43,711 such as WebUSB, WebGPU, 38 00:01:43,711 --> 00:01:46,923 NFC, Serial, Sockets, Sensor, etcetera. 39 00:01:49,770 --> 00:01:51,993 Then what does it mean for security? 40 00:01:52,830 --> 00:01:54,559 Well, new technologies bring new 41 00:01:54,559 --> 00:01:56,520 security problems to consider. 42 00:01:56,520 --> 00:02:00,240 They are intertwined with each other which by nature, 43 00:02:00,240 --> 00:02:04,170 it is highly complex to maintain. 44 00:02:04,170 --> 00:02:07,228 Previously, researchers like Franken et al. 45 00:02:07,228 --> 00:02:11,353 took a look at broader features, such as PDF JS, AppCache, 46 00:02:11,353 --> 00:02:14,250 prerender, WebSocket, et cetera, 47 00:02:14,250 --> 00:02:16,425 and they discovered that for all browsers, 48 00:02:16,425 --> 00:02:20,550 at least one cookie protection policy can be bypassed. 49 00:02:20,550 --> 00:02:23,943 Some of the findings that had been fixed were reintroduced. 50 00:02:25,047 --> 00:02:27,420 Meltdown and Spectre, 51 00:02:27,420 --> 00:02:32,130 they changed our way of thinking about the traditional 52 00:02:32,130 --> 00:02:34,800 web threat model, powerful web APIs, 53 00:02:34,800 --> 00:02:37,710 such as performance or SharedArrayBuffer 54 00:02:37,710 --> 00:02:40,470 had to be disabled or reduced. 55 00:02:40,470 --> 00:02:44,490 This show the complexity of keeping the web secure, 56 00:02:44,490 --> 00:02:48,540 although every step of the way, it gets thoroughly reviewed, 57 00:02:48,540 --> 00:02:50,763 errors slip through the cracks. 58 00:02:54,450 --> 00:02:58,380 In this talk, I will put my focus on that complexity, 59 00:02:58,380 --> 00:03:01,320 especially we'll discuss HTTP Cookie SameSite, 60 00:03:01,320 --> 00:03:04,680 PWA Service Worker, Fetch, 61 00:03:04,680 --> 00:03:08,643 then how the three can bring back CSRF from the dead. 62 00:03:09,840 --> 00:03:11,700 So let's dive in. 63 00:03:11,700 --> 00:03:13,710 So first, SameSite Cookie, 64 00:03:13,710 --> 00:03:15,993 the conclusive antidote to CSRF. 65 00:03:17,760 --> 00:03:21,651 So, but before we even get to SameSite Cookies, 66 00:03:21,651 --> 00:03:25,260 let's start with what actually is HTTP Cookie. 67 00:03:25,260 --> 00:03:28,410 So HTTP Cookie is a state management mechanism 68 00:03:28,410 --> 00:03:31,260 built on top of the stateless HTTP protocol. 69 00:03:31,260 --> 00:03:34,320 It defines two headers, a Cookie for requests, 70 00:03:34,320 --> 00:03:35,979 Set-Cookie for responses. 71 00:03:35,979 --> 00:03:39,900 Typically used to store server's session identifier, 72 00:03:39,900 --> 00:03:43,680 often a random secret in the client storage. 73 00:03:43,680 --> 00:03:47,040 Then user agents or clients or browsers 74 00:03:47,040 --> 00:03:49,860 always send the appropriate Cookie value, 75 00:03:49,860 --> 00:03:52,830 but only with the matching requests. 76 00:03:52,830 --> 00:03:56,580 What we're gonna focus is the matching part. 77 00:03:56,580 --> 00:03:59,010 What does that matching mean? 78 00:03:59,010 --> 00:04:02,076 If we dissect the below example into parts, 79 00:04:02,076 --> 00:04:05,010 SESSION is the cookie value, 80 00:04:05,010 --> 00:04:06,273 no, Cookie name, sorry. 81 00:04:07,655 --> 00:04:10,080 Secret nonce is the Cookie Value. 82 00:04:10,080 --> 00:04:14,280 Domain and Expires are the Attribute Names, 83 00:04:14,280 --> 00:04:16,770 and example.com and the written date 84 00:04:16,770 --> 00:04:19,710 are the Attribute Values. 85 00:04:19,710 --> 00:04:23,130 So matching is mainly about the attributes. 86 00:04:23,130 --> 00:04:26,160 The Domain attribute states that this Cookie is for 87 00:04:26,160 --> 00:04:28,716 example.com and the Expires attributes 88 00:04:28,716 --> 00:04:33,093 states that it should be discarded after that specific date. 89 00:04:35,700 --> 00:04:39,810 Assume the user agent accepted the Set-Cookie header 90 00:04:39,810 --> 00:04:43,290 when the user agent makes a request like img.gif. 91 00:04:43,290 --> 00:04:46,050 Since the domain is a match with the server 92 00:04:46,050 --> 00:04:49,530 and the expiration data is a match with the clock, 93 00:04:49,530 --> 00:04:53,400 it will include the Cookie Value in the Cookie Header. 94 00:04:53,400 --> 00:04:56,883 That's kind of about it. And that is a problem. 95 00:04:59,310 --> 00:05:02,739 The Cookie standard, put it bluntly, quote: 96 00:05:02,739 --> 00:05:04,350 For historical reasons, 97 00:05:04,350 --> 00:05:06,000 cookies contain a number of security 98 00:05:06,000 --> 00:05:07,863 and privacy infelicities. 99 00:05:08,850 --> 00:05:11,220 Just to name a few, third-party cookie, 100 00:05:11,220 --> 00:05:13,830 super cookie, eavesdropping, cross-site scripting 101 00:05:13,830 --> 00:05:16,050 as cross-site request forgery. 102 00:05:16,050 --> 00:05:18,390 What we're going to focus on is the cross-site 103 00:05:18,390 --> 00:05:19,443 request forgery. 104 00:05:22,440 --> 00:05:26,820 Then first, what is cross-site anyways? 105 00:05:26,820 --> 00:05:29,670 What is cross-site and cross-site request anyways? 106 00:05:29,670 --> 00:05:32,130 Let's consult the specifications. 107 00:05:32,130 --> 00:05:35,340 First, we need to define what an origin is. 108 00:05:35,340 --> 00:05:38,893 An origin is defined as a tuple of three elements. 109 00:05:38,893 --> 00:05:41,880 A scheme, host and port. 110 00:05:41,880 --> 00:05:44,610 Below on the left side are URLs 111 00:05:44,610 --> 00:05:47,204 and the right side are the origins. 112 00:05:47,204 --> 00:05:50,850 A URL like https://example.com/page 113 00:05:50,850 --> 00:05:55,378 becomes a tuple of https://example.com:443 114 00:05:55,378 --> 00:05:57,273 as it's origin. 115 00:05:58,170 --> 00:05:59,970 If the host is just different, 116 00:05:59,970 --> 00:06:04,080 like sub.example.com or if the port is different, 117 00:06:04,080 --> 00:06:07,770 port is custom like 8443, the tuple changes, 118 00:06:07,770 --> 00:06:09,783 hence the origin is different. 119 00:06:13,290 --> 00:06:16,710 Then we need to define what our registrable domain is. 120 00:06:16,710 --> 00:06:20,160 It is a domain name the internet users can, 121 00:06:20,160 --> 00:06:22,227 or historically could (indistinct). 122 00:06:23,908 --> 00:06:27,708 A registrable domain is defined as a public suffix of host 123 00:06:27,708 --> 00:06:30,480 plus one additional label. 124 00:06:30,480 --> 00:06:33,810 A Public Suffix List is a database 125 00:06:33,810 --> 00:06:36,360 of effective top level domains. 126 00:06:36,360 --> 00:06:40,560 It contains names like com, co.uk, github.io, 127 00:06:40,560 --> 00:06:42,993 ngrok.io, et cetera. 128 00:06:44,100 --> 00:06:47,220 So if the host is example.com, 129 00:06:47,220 --> 00:06:50,463 then its public suffix becomes just com, 130 00:06:51,498 --> 00:06:55,383 then plus one additional label becomes example.com. 131 00:06:56,757 --> 00:07:00,930 Which is its registrable domain. 132 00:07:00,930 --> 00:07:03,450 For sub.example.com, 133 00:07:03,450 --> 00:07:05,670 its public suffix is com, 134 00:07:05,670 --> 00:07:09,210 so registrable domain is example.com. 135 00:07:09,210 --> 00:07:11,160 The same as the last one. 136 00:07:11,160 --> 00:07:14,310 The registrable domain of a sub domain is the same 137 00:07:14,310 --> 00:07:15,723 as its parent domain. 138 00:07:19,620 --> 00:07:22,620 Next, we define what a site is. 139 00:07:22,620 --> 00:07:26,520 A site is defined as a tuple of two elements: 140 00:07:26,520 --> 00:07:28,800 scheme, registrable domain. 141 00:07:28,800 --> 00:07:31,080 We are using the same examples again, 142 00:07:31,080 --> 00:07:33,120 and the schemes are the same, 143 00:07:33,120 --> 00:07:36,900 but the host and ports are slightly different. 144 00:07:36,900 --> 00:07:41,040 But since the registrable domains are all example.com, 145 00:07:41,040 --> 00:07:45,030 the site, a tuple of https, example.com, 146 00:07:45,030 --> 00:07:46,260 are all the same. 147 00:07:46,260 --> 00:07:51,260 Hence the origins are all same-site with each other. 148 00:07:54,870 --> 00:07:58,920 Then we need to choose which one should be the site for 149 00:07:58,920 --> 00:08:01,410 cookies for a given request. 150 00:08:01,410 --> 00:08:04,560 This varies under different circumstances, 151 00:08:04,560 --> 00:08:07,620 but for the usual browsing cases, 152 00:08:07,620 --> 00:08:10,620 it is the documents top-level origin, 153 00:08:10,620 --> 00:08:14,310 also known as the URI displayed in the address bar. 154 00:08:14,310 --> 00:08:15,143 Simple as that. 155 00:08:18,780 --> 00:08:20,250 We need to define one more thing 156 00:08:20,250 --> 00:08:22,860 and the client object of a request. 157 00:08:22,860 --> 00:08:26,287 This is an object that holds among other things, 158 00:08:26,287 --> 00:08:29,550 context for JavaScript and browsing 159 00:08:29,550 --> 00:08:33,360 and an origin used in security checks. 160 00:08:33,360 --> 00:08:36,783 We'll denote it with curly brackets like so. 161 00:08:40,620 --> 00:08:42,900 With this information, we can finally define 162 00:08:42,900 --> 00:08:45,480 what a SameSite request is. 163 00:08:45,480 --> 00:08:49,560 A request is SameSite when it satisfies A, 164 00:08:49,560 --> 00:08:52,650 the request's URL's origin is SameSite 165 00:08:52,650 --> 00:08:55,290 with its client's site for cookies, 166 00:08:55,290 --> 00:08:59,000 B, the request URL's origin is SameSite 167 00:09:00,870 --> 00:09:03,360 with every URL in its URL list, 168 00:09:03,360 --> 00:09:06,480 C, the request is not triggered by a user 169 00:09:06,480 --> 00:09:08,100 pressing the reload button. 170 00:09:08,100 --> 00:09:13,100 Moving forward, we will only focus on the first criteria. 171 00:09:14,190 --> 00:09:17,790 And then a cross-site request is defined 172 00:09:17,790 --> 00:09:20,253 to be a request that is not SameSite. 173 00:09:24,450 --> 00:09:26,280 That was quite formal, 174 00:09:26,280 --> 00:09:28,560 but so let me give you a basic example 175 00:09:28,560 --> 00:09:30,600 to make it more digestible. 176 00:09:30,600 --> 00:09:31,433 As we discussed, 177 00:09:31,433 --> 00:09:35,550 a site is a tuple of scheme and registrable domain. 178 00:09:35,550 --> 00:09:37,500 And the typical site for cookies 179 00:09:37,500 --> 00:09:40,470 is the user agent's address bar. 180 00:09:40,470 --> 00:09:44,430 Below is a document hosted at https, example.com. 181 00:09:44,430 --> 00:09:47,970 And this is our site for cookies 182 00:09:47,970 --> 00:09:49,383 for the rest of the example. 183 00:09:50,340 --> 00:09:54,003 Its site is a tuple of https, example.com. 184 00:09:57,270 --> 00:09:58,103 On this page, 185 00:09:58,103 --> 00:10:00,870 there's a link to https, example.com 186 00:10:00,870 --> 00:10:05,310 whose site is a tuple of https, example.com. 187 00:10:05,310 --> 00:10:08,490 So clicking the link will spawn a request. 188 00:10:08,490 --> 00:10:12,540 Since the request URL's origin's site is the same as 189 00:10:12,540 --> 00:10:15,300 that of site for cookies, the address bar, 190 00:10:15,300 --> 00:10:18,000 it is a SameSite request. 191 00:10:18,000 --> 00:10:21,270 Also, clicking a link will make the browser 192 00:10:21,270 --> 00:10:23,100 navigate to the URL. 193 00:10:23,100 --> 00:10:27,780 It's a navigation request and also top-level 194 00:10:27,780 --> 00:10:31,353 since the document does not have a parent document. 195 00:10:32,310 --> 00:10:34,530 It is also an HTTP safe request 196 00:10:34,530 --> 00:10:39,513 since as per the HTTP semantics specification, 197 00:10:40,350 --> 00:10:43,113 the GET method is considered safe. 198 00:10:46,230 --> 00:10:49,095 Embedding an image will also spawn a request. 199 00:10:49,095 --> 00:10:52,614 The URL is https://example.com/image.gif. 200 00:10:52,614 --> 00:10:56,490 Like the previous link, it is a SameSite request. 201 00:10:56,490 --> 00:11:00,000 If a request is for an image, audio, script style, 202 00:11:00,000 --> 00:11:03,540 et cetera, we call it a subresource request. 203 00:11:03,540 --> 00:11:07,443 It is an HTTP GET, safe request, just like clicking a link. 204 00:11:12,060 --> 00:11:16,890 Now there is a different link to https, victim.com. 205 00:11:16,890 --> 00:11:21,890 Its site becomes a tuple of HTTPS and victim.com, 206 00:11:22,320 --> 00:11:25,950 which is different from that of site for cookies, 207 00:11:25,950 --> 00:11:26,853 the address bar. 208 00:11:28,110 --> 00:11:31,080 It is a cross-site request. 209 00:11:31,080 --> 00:11:33,750 Just like the previous link, it is a top-level 210 00:11:33,750 --> 00:11:37,743 navigation request and then HTTP safe request. 211 00:11:40,860 --> 00:11:44,970 Finally, we have a form for https, victim.com. 212 00:11:44,970 --> 00:11:46,110 Like the previous link, 213 00:11:46,110 --> 00:11:48,114 it is a cross-site request. 214 00:11:48,114 --> 00:11:50,274 Submitting the form will make the browser 215 00:11:50,274 --> 00:11:52,320 navigate to the URL. 216 00:11:52,320 --> 00:11:55,080 So it is a top-level navigation request. 217 00:11:55,080 --> 00:11:58,410 But since the form's method attribute is POST, 218 00:11:58,410 --> 00:12:01,953 it is now an HTTP unsafe request. 219 00:12:05,070 --> 00:12:07,800 Now we know what a cross-site request is, 220 00:12:07,800 --> 00:12:10,590 we can define what a CSRF is. 221 00:12:10,590 --> 00:12:13,815 It is when an attacker forces our victim to execute forged 222 00:12:13,815 --> 00:12:16,380 cross-site requests. 223 00:12:16,380 --> 00:12:18,780 It's possible because as we discussed, 224 00:12:18,780 --> 00:12:23,223 user agents send the cookies with matching requests. 225 00:12:24,360 --> 00:12:25,770 Below is an example. 226 00:12:25,770 --> 00:12:28,950 Let's say user is visiting example.com 227 00:12:28,950 --> 00:12:33,950 and it has a forged form which has malicious inputs 228 00:12:33,990 --> 00:12:35,853 like delete and all. 229 00:12:38,910 --> 00:12:42,644 Submitting the form to victim.com by making the user click 230 00:12:42,644 --> 00:12:47,644 on it or using JavaScript, will spawn a cross-site request, 231 00:12:48,450 --> 00:12:51,120 also, a top-level navigation request, 232 00:12:51,120 --> 00:12:53,880 and an HTTP unsafe request. 233 00:12:53,880 --> 00:12:57,330 Crucially, the user's cookie will be sent. 234 00:12:57,330 --> 00:13:00,524 The server will recognize and authorize it as the user 235 00:13:00,524 --> 00:13:02,910 to run the malicious command. 236 00:13:02,910 --> 00:13:06,270 It is indeed possible to perform a CSRF with the HTTP GET 237 00:13:06,270 --> 00:13:09,255 method like clicking a link or embedding an image, 238 00:13:09,255 --> 00:13:11,703 as long as the server is susceptible. 239 00:13:14,975 --> 00:13:18,903 There are many known (indistinct) to mitigate CSRF. 240 00:13:22,962 --> 00:13:24,780 These are the mitigations. 241 00:13:24,780 --> 00:13:28,833 And one of them is to adopt the SameSite policy. 242 00:13:31,560 --> 00:13:35,346 So the SameSite attribute introduces an additional 243 00:13:35,346 --> 00:13:38,130 attribute to the matching process. 244 00:13:38,130 --> 00:13:42,660 If the attribute is set to strict, then the browser 245 00:13:42,660 --> 00:13:45,690 send the cookie only for SameSite requests. 246 00:13:45,690 --> 00:13:48,180 The browser does not send the cookie for clicking 247 00:13:48,180 --> 00:13:50,880 a cross-site link, nor embedding a cross-site image, 248 00:13:50,880 --> 00:13:53,538 nor submitting a cross-site form. 249 00:13:53,538 --> 00:13:57,090 But SameSite=Lax is like strict, 250 00:13:57,090 --> 00:13:59,250 but there's an exception. 251 00:13:59,250 --> 00:14:04,250 It allows cross-site top-level navigation safe requests. 252 00:14:04,560 --> 00:14:06,188 What it means is that 253 00:14:06,188 --> 00:14:11,188 the browser will send a cookie 254 00:14:11,220 --> 00:14:14,190 only when clicking a cross-site link, 255 00:14:14,190 --> 00:14:16,590 with our previous examples, 256 00:14:16,590 --> 00:14:19,290 but not when embedding a cross-site image, 257 00:14:19,290 --> 00:14:22,263 but not when submitting a cross-site form. 258 00:14:23,400 --> 00:14:24,693 If it is set to none, 259 00:14:25,620 --> 00:14:27,510 the browser will behave just like before. 260 00:14:27,510 --> 00:14:31,383 The SameSiteness is ignored and the cookie is sent. 261 00:14:32,400 --> 00:14:35,583 Let me show you how it's all supposed to work. 262 00:14:39,660 --> 00:14:42,240 Right, we start with the victim page here 263 00:14:42,240 --> 00:14:46,560 where it echoes the cookie header of the browser's request. 264 00:14:46,560 --> 00:14:48,360 It shows three cookies, 265 00:14:48,360 --> 00:14:51,363 none-cookie=1, lax-cookie=2, strict-cookie=3. 266 00:14:53,370 --> 00:14:58,370 And you can see the SameSite attributes 267 00:14:58,590 --> 00:15:00,393 are set respectively. 268 00:15:05,340 --> 00:15:08,160 Let's navigate to the attacker page 269 00:15:08,160 --> 00:15:10,320 and then navigate back to the victim page 270 00:15:10,320 --> 00:15:13,113 by simply clicking a link using GET method. 271 00:15:17,430 --> 00:15:21,300 And now the page echoes only two cookies, none and lax. 272 00:15:21,300 --> 00:15:25,380 Meaning the browser did not send a strict cookie, 273 00:15:25,380 --> 00:15:28,383 since it was a cross-site request. 274 00:15:29,790 --> 00:15:33,363 Even though they are actually properly stored. 275 00:15:34,440 --> 00:15:38,583 We tried same by submitting a form using POST request. 276 00:15:41,040 --> 00:15:44,010 Now the page shows only one cookie, none, 277 00:15:44,010 --> 00:15:47,400 meaning the browser did not send lax-cookie either 278 00:15:47,400 --> 00:15:52,320 since the request was HTTP unsafe. 279 00:15:52,320 --> 00:15:57,320 So that is a quick look at how it's all supposed to work 280 00:15:57,570 --> 00:15:59,073 with SameSite attribute. 281 00:16:01,290 --> 00:16:05,040 And the SameSite attribute has been widely supported 282 00:16:05,040 --> 00:16:08,670 by browsers, but the adoption has been kind of slow. 283 00:16:08,670 --> 00:16:12,870 Then in 2020, Chrome started treating cookies 284 00:16:12,870 --> 00:16:16,920 without SameSite attribute as Lax by default. 285 00:16:16,920 --> 00:16:19,920 The cookie draft standard has been also revised. 286 00:16:19,920 --> 00:16:23,130 So there has been some sentiment that CSRF dead, 287 00:16:23,130 --> 00:16:26,580 is really dead and SameSite cookies alone 288 00:16:26,580 --> 00:16:29,313 are sufficient to protect against CSRF. 289 00:16:30,150 --> 00:16:31,560 We're gonna leave it at that 290 00:16:31,560 --> 00:16:33,723 and move on to a different topic. 291 00:16:35,370 --> 00:16:36,840 And the next is... 292 00:16:36,840 --> 00:16:40,983 Our next topic is Service Worker, PWAs Network Layer. 293 00:16:43,320 --> 00:16:46,920 So service worker is one of the core technologies 294 00:16:46,920 --> 00:16:48,840 of progressive Web App. 295 00:16:48,840 --> 00:16:51,450 Progressive Web Apps in a nutshell 296 00:16:51,450 --> 00:16:54,738 is a type of web application that is native-like, 297 00:16:54,738 --> 00:16:57,480 installable and offline. 298 00:16:57,480 --> 00:17:00,120 Service worker runs in a worker context, 299 00:17:00,120 --> 00:17:03,180 meaning it is running in a different thread 300 00:17:03,180 --> 00:17:06,690 from the main JavaScript execution context. 301 00:17:06,690 --> 00:17:09,360 Service worker can act as a proxy server 302 00:17:09,360 --> 00:17:12,720 between web application, browser and network. 303 00:17:12,720 --> 00:17:15,570 It can intercept network requests, 304 00:17:15,570 --> 00:17:18,183 then respond with custom responses. 305 00:17:19,500 --> 00:17:21,870 Together with CacheStorage API, 306 00:17:21,870 --> 00:17:24,690 it makes offline fallback pages possible 307 00:17:24,690 --> 00:17:26,223 in a web application. 308 00:17:27,060 --> 00:17:30,600 Service worker is mainly used for custom caching strategies 309 00:17:30,600 --> 00:17:33,630 by a front-end web developer, 310 00:17:33,630 --> 00:17:35,913 just like Twitter on the right example. 311 00:17:39,660 --> 00:17:42,570 So this is how caching works with service worker. 312 00:17:42,570 --> 00:17:45,360 There are roughly four layers to consider, 313 00:17:45,360 --> 00:17:48,750 the HTML, CSS, JavaScript layer on the top, 314 00:17:48,750 --> 00:17:49,583 in the middle, 315 00:17:49,583 --> 00:17:51,993 the service worker interacting with CacheStorage API, 316 00:17:53,760 --> 00:17:57,513 the browser with its HTTP Cache, and the server. 317 00:18:00,330 --> 00:18:05,010 So let's say the HTML layer requests an asset. 318 00:18:05,010 --> 00:18:07,560 It could be an image, a video, a CSS file, 319 00:18:07,560 --> 00:18:09,153 a JS file, et cetera. 320 00:18:10,920 --> 00:18:15,150 Then a FetchEvent is dispatched to the service worker, 321 00:18:15,150 --> 00:18:17,400 which intercepts the request. 322 00:18:17,400 --> 00:18:21,630 Here, a web developer can implement their custom caching 323 00:18:21,630 --> 00:18:25,323 strategy, using JavaScript and CacheStorage API. 324 00:18:27,930 --> 00:18:32,370 In case of a cache miss, or an expiration, or else, 325 00:18:32,370 --> 00:18:34,650 the service worker can call the Fetch API 326 00:18:34,650 --> 00:18:37,170 using the events request. 327 00:18:37,170 --> 00:18:42,016 Then the browser makes use of its HTTP cache strategy 328 00:18:42,016 --> 00:18:45,993 based on the headers, Cache-Control, Expires, etcetera. 329 00:18:48,060 --> 00:18:51,549 If that also encounters a cache miss or else... 330 00:18:51,549 --> 00:18:52,710 (clears throat) 331 00:18:52,710 --> 00:18:53,543 Excuse me. 332 00:18:53,543 --> 00:18:56,400 The browser makes an HTTP request to the server 333 00:18:56,400 --> 00:19:00,933 over the network and receives an HTTP response. 334 00:19:03,600 --> 00:19:07,020 The HTTP response is handled, then passed to 335 00:19:07,020 --> 00:19:11,343 the service worker in the form of a response class object. 336 00:19:13,350 --> 00:19:15,870 The service worker then receives the object, 337 00:19:15,870 --> 00:19:20,343 stores it in CacheStorage, then passes into the event. 338 00:19:21,870 --> 00:19:24,930 So let's implement this flow with a quote, 339 00:19:24,930 --> 00:19:28,383 Example from the perspective of a web developer. 340 00:19:29,460 --> 00:19:30,330 Before anything, 341 00:19:30,330 --> 00:19:32,940 we register the service worker. 342 00:19:32,940 --> 00:19:35,072 This does not require any user interaction 343 00:19:35,072 --> 00:19:38,670 and the developer will typically just want it to be happen 344 00:19:38,670 --> 00:19:39,993 as soon as possible. 345 00:19:41,850 --> 00:19:44,040 The service worker looks like this, 346 00:19:44,040 --> 00:19:46,354 it adds an EventListener on Fetch 347 00:19:46,354 --> 00:19:49,623 then starts intercepting all requests. 348 00:19:51,300 --> 00:19:54,900 If there is a request, in this example, it's an image, 349 00:19:54,900 --> 00:19:58,683 it triggers and dispatches a Fetch event to the listener. 350 00:20:00,990 --> 00:20:04,830 Now the callback function is called to handle the request. 351 00:20:04,830 --> 00:20:08,354 The function checks if there is an existing match 352 00:20:08,354 --> 00:20:11,460 in the CacheStorage, if there is a match, 353 00:20:11,460 --> 00:20:15,090 it is returned to the event.respondWith method. 354 00:20:15,090 --> 00:20:17,703 We call this the Cached Flow. 355 00:20:20,700 --> 00:20:22,170 If there is no match, 356 00:20:22,170 --> 00:20:27,170 we call the Fetch API simply using the events request as is. 357 00:20:27,330 --> 00:20:29,640 We call this the Passthrough flow. 358 00:20:29,640 --> 00:20:32,070 The browser returns a response object, 359 00:20:32,070 --> 00:20:34,953 which also gets returned untouched. 360 00:20:38,490 --> 00:20:42,093 Then finally, the image receives the response object. 361 00:20:44,610 --> 00:20:47,130 The Cached flow isn't required, 362 00:20:47,130 --> 00:20:51,570 the service worker can simply pass through every request. 363 00:20:51,570 --> 00:20:54,993 Then we will revisit this example later. 364 00:20:57,150 --> 00:21:00,701 For more complex or caching strategies, 365 00:21:00,701 --> 00:21:05,130 most web developers rely on an Open Source Library 366 00:21:05,130 --> 00:21:06,810 to make the job easier. 367 00:21:06,810 --> 00:21:08,961 One of the most popular ones is Workbox 368 00:21:08,961 --> 00:21:11,880 created and maintained by Google Chrome. 369 00:21:11,880 --> 00:21:15,840 It is a collection of JavaScript libraries for PWAs. 370 00:21:15,840 --> 00:21:16,890 Importantly, 371 00:21:16,890 --> 00:21:20,673 it includes service worker routing and caching modules. 372 00:21:24,270 --> 00:21:28,650 We simply import the workbox-sw.js, 373 00:21:28,650 --> 00:21:30,660 then the developer can specify 374 00:21:30,660 --> 00:21:33,240 whatever custom cache strategy they want. 375 00:21:33,240 --> 00:21:35,790 In this Workbox example number one, 376 00:21:35,790 --> 00:21:38,730 a route is registered in such that if the request 377 00:21:38,730 --> 00:21:41,250 is for an image, it uses the strategy 378 00:21:41,250 --> 00:21:43,230 that looks up the cache first, 379 00:21:43,230 --> 00:21:46,473 effectively caching all the image assets. 380 00:21:47,730 --> 00:21:51,810 Then a default handler is registered so that all the other 381 00:21:51,810 --> 00:21:55,413 unspecified requests will only go to the network. 382 00:21:58,200 --> 00:21:59,880 Something like this is also possible, 383 00:21:59,880 --> 00:22:01,560 Workbox example number two, 384 00:22:01,560 --> 00:22:05,520 a route is registered such that if the request URL 385 00:22:05,520 --> 00:22:08,760 has a path name of /transfer, 386 00:22:08,760 --> 00:22:11,100 it should only go to the network, 387 00:22:11,100 --> 00:22:15,450 but will time out after 600 seconds for POST requests. 388 00:22:15,450 --> 00:22:18,648 The intention is to make the request wait 389 00:22:18,648 --> 00:22:23,163 a little bit more because the server is slow somehow. 390 00:22:26,760 --> 00:22:29,910 For React development, Create React App 391 00:22:29,910 --> 00:22:32,880 provides a built-in support for service worker 392 00:22:32,880 --> 00:22:34,080 and caching. 393 00:22:34,080 --> 00:22:35,550 Inside index.js, 394 00:22:35,550 --> 00:22:37,350 there is a line that can be changed. 395 00:22:39,480 --> 00:22:44,220 Changing the method to register, registers service/worker.js 396 00:22:44,220 --> 00:22:46,650 as soon as the page is loaded. 397 00:22:46,650 --> 00:22:51,300 It is also using Workbox under the hood and customizable. 398 00:22:51,300 --> 00:22:54,033 We'll also revisit the examples later. 399 00:22:57,090 --> 00:23:00,900 Now that we learned SameSite cookie and service worker, 400 00:23:00,900 --> 00:23:02,550 let's get into the main part, 401 00:23:02,550 --> 00:23:04,710 the collaboration that leads to CSRF. 402 00:23:07,740 --> 00:23:10,440 We will take a deep dive into the specifications 403 00:23:10,440 --> 00:23:13,020 to spot the smells radiating from them. 404 00:23:13,020 --> 00:23:16,200 This is going to be a bit crude and simplified read, 405 00:23:16,200 --> 00:23:17,583 so bear that in mind. 406 00:23:19,680 --> 00:23:21,881 The scene is familiar, 407 00:23:21,881 --> 00:23:23,910 it is the same example. 408 00:23:23,910 --> 00:23:26,610 We have a service worker registered, 409 00:23:26,610 --> 00:23:29,681 intercepting and passing the request through. 410 00:23:29,681 --> 00:23:32,910 Then we have an image element waiting to be loaded 411 00:23:32,910 --> 00:23:33,903 by the browser. 412 00:23:36,960 --> 00:23:39,750 As per the HTTP specification, 413 00:23:39,750 --> 00:23:41,372 when updating the image data, 414 00:23:41,372 --> 00:23:45,360 the browser should simply fetch the image request. 415 00:23:45,360 --> 00:23:47,793 But how does that actually happen? 416 00:23:49,620 --> 00:23:52,080 As per the fetch specification, 417 00:23:52,080 --> 00:23:55,020 the browser should perform fetching, main fetch, 418 00:23:55,020 --> 00:23:58,530 scheme fetch, and HTTP fetch. 419 00:23:58,530 --> 00:23:59,940 In the middle of the process, 420 00:23:59,940 --> 00:24:03,072 if we have an active service worker, 5.4, 421 00:24:03,072 --> 00:24:07,230 set response to the result of invoking handle fetch 422 00:24:07,230 --> 00:24:09,803 for requestForServiceWorker. 423 00:24:13,110 --> 00:24:14,932 Then what is handle fetch? 424 00:24:14,932 --> 00:24:18,180 We look at the service worker's specification. 425 00:24:18,180 --> 00:24:20,490 Appendix A: Handle Fetch, 426 00:24:20,490 --> 00:24:25,110 let e be the result of creating an event with FetchEvent. 427 00:24:25,110 --> 00:24:29,370 Dispatch e at activeWorker's global object. 428 00:24:29,370 --> 00:24:32,580 Now, the event is created and is passed on 429 00:24:32,580 --> 00:24:33,813 to the service worker. 430 00:24:37,800 --> 00:24:40,140 The service worker code is the same. 431 00:24:40,140 --> 00:24:41,970 It is a passthrough. 432 00:24:41,970 --> 00:24:44,490 Simply fetch the events request, 433 00:24:44,490 --> 00:24:49,490 then responds with return the response as is. 434 00:24:49,590 --> 00:24:52,563 But then what does that fetch method do? 435 00:24:55,530 --> 00:24:57,510 As per the fetch spec, 436 00:24:57,510 --> 00:25:00,016 the fetch input, init method steps are, 437 00:25:00,016 --> 00:25:03,515 let request object be the result of invoking 438 00:25:03,515 --> 00:25:06,515 the initial value of request as constructor 439 00:25:06,515 --> 00:25:09,990 with input and init as arguments. 440 00:25:09,990 --> 00:25:12,603 That is one sentence. 441 00:25:14,400 --> 00:25:17,790 Then let's see what the constructor does. 442 00:25:17,790 --> 00:25:21,090 For the request class, 443 00:25:21,090 --> 00:25:25,530 6.2, set request to input's request, 444 00:25:25,530 --> 00:25:28,590 then 12, set request to a new request 445 00:25:28,590 --> 00:25:30,576 with the following properties. 446 00:25:30,576 --> 00:25:34,055 What's happening here is that the browser creates 447 00:25:34,055 --> 00:25:39,055 a new request object out of the input request object, 448 00:25:39,180 --> 00:25:41,880 copying one property at a time. 449 00:25:41,880 --> 00:25:43,860 But then there's something peculiar, 450 00:25:43,860 --> 00:25:48,690 the origin of the new request is set to client, 451 00:25:48,690 --> 00:25:50,640 a placeholder string, 452 00:25:50,640 --> 00:25:54,723 meaning it will follow it's client object. 453 00:25:57,300 --> 00:25:59,670 Then what's the client object? 454 00:25:59,670 --> 00:26:01,750 It's this object's 455 00:26:02,790 --> 00:26:05,010 context and origin. 456 00:26:05,010 --> 00:26:07,323 This is context and origin. 457 00:26:08,220 --> 00:26:09,053 At this point, 458 00:26:09,053 --> 00:26:11,340 "This" points to the service worker, 459 00:26:11,340 --> 00:26:15,450 rather than the requested image or the HTML. 460 00:26:15,450 --> 00:26:17,103 This is a red flag. 461 00:26:19,693 --> 00:26:23,280 Then how is the cookie header computed? 462 00:26:23,280 --> 00:26:25,050 Let's continue fetching. 463 00:26:25,050 --> 00:26:26,790 Let cookies be the result of running 464 00:26:26,790 --> 00:26:28,350 the "cookie string" algorithm. 465 00:26:28,350 --> 00:26:31,200 See section 5.4 of COOKIES. 466 00:26:31,200 --> 00:26:35,160 Cookies refers to the IETF spec. 467 00:26:35,160 --> 00:26:37,200 So let's look into that. 468 00:26:37,200 --> 00:26:39,180 And in that spec, 469 00:26:39,180 --> 00:26:41,700 there is a separate section for service workers. 470 00:26:41,700 --> 00:26:42,982 It reads, quote: 471 00:26:42,982 --> 00:26:45,720 Requests which are initiated by a service worker itself, 472 00:26:45,720 --> 00:26:48,720 via a direct call to fetch, for instance, on the other hand, 473 00:26:48,720 --> 00:26:52,650 will have a client which is a ServiceWorkerGlobalScope. 474 00:26:52,650 --> 00:26:55,950 Its "site for cookies" will be the registrable domain 475 00:26:55,950 --> 00:26:58,263 of the service worker's URI, unquote. 476 00:27:00,240 --> 00:27:02,490 So some familiar words here, 477 00:27:02,490 --> 00:27:05,670 but the point is that "site for cookies" 478 00:27:05,670 --> 00:27:07,653 is always the service worker's URI, 479 00:27:08,580 --> 00:27:11,032 rather than that of the image request, 480 00:27:11,032 --> 00:27:14,013 same situation, same red flag. 481 00:27:16,320 --> 00:27:20,040 What happens if attacker.com comes into play, 482 00:27:20,040 --> 00:27:23,853 which embeds a cross-site request to victim.com? 483 00:27:24,720 --> 00:27:27,937 The service worker is hosted at victim.com. 484 00:27:27,937 --> 00:27:30,783 "Site for cookies" is always the service worker's URI. 485 00:27:32,310 --> 00:27:37,140 The request URL, victim.com/image.gif is same-site 486 00:27:37,140 --> 00:27:41,743 with its site for cookies, victim.com/sw.js. 487 00:27:42,780 --> 00:27:46,023 Suddenly, it is a SameSite request by definition. 488 00:27:49,290 --> 00:27:53,070 Looks like CSRF is back. So let's put it to the test. 489 00:27:53,070 --> 00:27:55,680 We are going to revisit the previous code examples, 490 00:27:55,680 --> 00:27:58,620 but this time we are adding an attacker. 491 00:27:58,620 --> 00:28:01,860 The attacker has two elements, a link and a form. 492 00:28:01,860 --> 00:28:04,860 Activating other will trigger a FetchEvent, 493 00:28:04,860 --> 00:28:07,293 then passthrough to the server. 494 00:28:08,760 --> 00:28:09,813 Let me show you. 495 00:28:16,500 --> 00:28:17,333 Okay. 496 00:28:23,490 --> 00:28:24,323 Right. 497 00:28:24,323 --> 00:28:26,040 We have the same setup, a victim page, 498 00:28:26,040 --> 00:28:31,020 which echoes the cookie header, none, lax, strict-cookie 499 00:28:31,020 --> 00:28:32,280 set in the browser. 500 00:28:32,280 --> 00:28:36,153 Let's register the service worker. 501 00:28:37,890 --> 00:28:42,690 Now, it is listening for fetch events and the code itself 502 00:28:42,690 --> 00:28:44,883 is simple passthrough. 503 00:28:47,070 --> 00:28:50,673 Let's navigate to the attacker page, 504 00:28:52,230 --> 00:28:55,260 then navigate back to the victim page with a link. 505 00:28:55,260 --> 00:28:57,390 As per the SameSite policy, 506 00:28:57,390 --> 00:28:59,490 the strict-cookie should not be sent. 507 00:28:59,490 --> 00:29:01,560 It is a cross-site request. 508 00:29:01,560 --> 00:29:04,263 Only none and lax should be sent. 509 00:29:05,280 --> 00:29:08,733 But now it shows all three cookies. 510 00:29:12,738 --> 00:29:16,323 The browser simply disregarded the SameSite policy. 511 00:29:17,850 --> 00:29:19,410 Let's try the same with the form. 512 00:29:19,410 --> 00:29:23,310 Now as for the SameSite policy, 513 00:29:23,310 --> 00:29:25,863 now only the none-cookie should be sent. 514 00:29:27,630 --> 00:29:29,483 But all three cookies again. 515 00:29:30,797 --> 00:29:31,949 (audience applauds) 516 00:29:31,949 --> 00:29:33,282 - [Dongsung Kim] Thank you. 517 00:29:38,340 --> 00:29:42,750 Now let's try that again without the service worker. 518 00:29:42,750 --> 00:29:47,100 Then it's resent and it's none-cookie alone. 519 00:29:47,100 --> 00:29:47,933 So... 520 00:29:53,190 --> 00:29:56,790 Then let's look at the Workbox example number one, again, 521 00:29:56,790 --> 00:29:59,580 the developer's intention was simply 522 00:29:59,580 --> 00:30:01,198 to cache all image assets, 523 00:30:01,198 --> 00:30:03,510 and then for all the other requests, 524 00:30:03,510 --> 00:30:05,368 to go over the network only. 525 00:30:05,368 --> 00:30:08,910 And then we will add an attacker to the mix. 526 00:30:08,910 --> 00:30:10,740 The attacker has two elements, 527 00:30:10,740 --> 00:30:14,493 a link and a form to the endpoint/transfer. 528 00:30:17,640 --> 00:30:19,050 We have the victim page here 529 00:30:19,050 --> 00:30:21,873 with login and log out functionality. 530 00:30:22,920 --> 00:30:25,950 Clicking the login button would set a session cookie 531 00:30:25,950 --> 00:30:28,350 with SameSite strict. 532 00:30:28,350 --> 00:30:31,680 You can see the page shows we are authorized. 533 00:30:31,680 --> 00:30:33,977 Let's navigate to the attacker page 534 00:30:33,977 --> 00:30:36,796 and navigate back to the victim with link. 535 00:30:36,796 --> 00:30:41,796 As per the SameSite policy, the strict cookie is not sent, 536 00:30:42,180 --> 00:30:44,040 so we are unauthorized. 537 00:30:44,040 --> 00:30:45,993 Trying again with the form. 538 00:30:46,980 --> 00:30:48,483 Still unauthorized. 539 00:30:49,650 --> 00:30:54,650 So let's go back and let's register the service worker. 540 00:30:56,790 --> 00:31:01,790 It's listening for fetch events and the code looks, 541 00:31:02,190 --> 00:31:03,303 as we discussed. 542 00:31:06,030 --> 00:31:07,580 Let's try... 543 00:31:09,930 --> 00:31:14,820 Let's try the same and click on the cross-site request. 544 00:31:14,820 --> 00:31:17,010 And we are now authorized. 545 00:31:17,010 --> 00:31:20,520 However, submitting the form 546 00:31:20,520 --> 00:31:22,323 does not get us authorized. 547 00:31:23,790 --> 00:31:28,170 So what happens is that... 548 00:31:28,170 --> 00:31:29,003 Go. 549 00:31:30,630 --> 00:31:35,630 What happens is that setting the DefaultHandler itself 550 00:31:35,940 --> 00:31:39,900 makes the service worker passthrough all the requests. 551 00:31:39,900 --> 00:31:44,250 Doing so only applies to HTTP GET requests, 552 00:31:44,250 --> 00:31:47,223 hence only affecting the link, not the form. 553 00:31:51,480 --> 00:31:55,410 However, Workbox example number two can make things worse. 554 00:31:55,410 --> 00:31:58,650 The intention was to simply change the timeout setting. 555 00:31:58,650 --> 00:32:01,173 Let's add the same attacker to the mix. 556 00:32:03,840 --> 00:32:05,973 We have the same victim here, 557 00:32:07,080 --> 00:32:10,380 but there is an additional logic in the service worker, 558 00:32:10,380 --> 00:32:14,043 a prolonged network timeout for POST request transfer. 559 00:32:15,420 --> 00:32:19,650 Let's try the form on the attacker page, 560 00:32:19,650 --> 00:32:21,483 and now we are authorized. 561 00:32:23,009 --> 00:32:26,249 (audience applauds) 562 00:32:26,249 --> 00:32:27,993 - [Dongsung Kim] Thank you. 563 00:32:30,690 --> 00:32:33,750 Let's revisit the Create React App example. 564 00:32:33,750 --> 00:32:36,150 The attacker has one element, 565 00:32:36,150 --> 00:32:39,513 a link to the victim's secret image. 566 00:32:42,930 --> 00:32:47,760 We navigate to the victim like so. 567 00:32:47,760 --> 00:32:49,650 Immediately, there is a service worker 568 00:32:49,650 --> 00:32:51,000 registered to the browser, 569 00:32:51,000 --> 00:32:53,610 listening for fetch events. 570 00:32:53,610 --> 00:32:55,120 Clicking the login button 571 00:32:57,121 --> 00:33:00,750 would set a strict session cookie. 572 00:33:00,750 --> 00:33:02,403 You can see, we are logged in. 573 00:33:03,870 --> 00:33:05,830 Let's navigate to the attacker page 574 00:33:07,080 --> 00:33:08,973 and navigate back to the victim page. 575 00:33:09,870 --> 00:33:13,470 You can see the image here despite the SameSite policy. 576 00:33:13,470 --> 00:33:16,530 Just to be sure, let's deregister the service worker 577 00:33:16,530 --> 00:33:17,433 and try again. 578 00:33:20,940 --> 00:33:23,223 Now it returns forbidden as intended. 579 00:33:26,928 --> 00:33:29,610 And there is one more thing here, 580 00:33:29,610 --> 00:33:31,953 we are using this first example again. 581 00:33:35,970 --> 00:33:37,830 We are doing the same demo one more time, 582 00:33:37,830 --> 00:33:40,860 but this time with the Firefox Developer Tools 583 00:33:40,860 --> 00:33:43,167 opened on the network tab on the right. 584 00:33:43,167 --> 00:33:44,700 (keyboard clacking) 585 00:33:44,700 --> 00:33:47,250 So register a service worker, 586 00:33:47,250 --> 00:33:48,780 listening for fetch events, 587 00:33:48,780 --> 00:33:52,290 navigate to the attacker. 588 00:33:52,290 --> 00:33:55,560 Then the client wrongly sends all three cookies, right? 589 00:33:55,560 --> 00:33:58,230 So it's the same. 590 00:33:58,230 --> 00:34:01,187 But when we examine that specific request 591 00:34:01,187 --> 00:34:02,943 in the Developer Tools, 592 00:34:05,340 --> 00:34:10,080 and the request, it says only none-cookie was sent. 593 00:34:10,080 --> 00:34:12,330 This was what's supposed to happen, 594 00:34:12,330 --> 00:34:15,933 but what actually happened is quite opposite of this. 595 00:34:20,443 --> 00:34:22,440 (keyboard clacking) 596 00:34:22,440 --> 00:34:26,220 Okay, let's talk about patches and updates, 597 00:34:26,220 --> 00:34:28,530 yet issues still remain. 598 00:34:28,530 --> 00:34:33,530 So I reported this problem in the August of 2020. 599 00:34:34,140 --> 00:34:37,003 As it impacted both Firefox and Chrome, 600 00:34:37,003 --> 00:34:39,213 two separate reports were sent. 601 00:34:40,320 --> 00:34:42,480 And then in October, 602 00:34:42,480 --> 00:34:44,790 an issue on the Cookie specification 603 00:34:44,790 --> 00:34:46,470 was independently opened. 604 00:34:46,470 --> 00:34:48,900 It was about the "site for cookies" problem 605 00:34:48,900 --> 00:34:50,643 that we previously discussed. 606 00:34:53,070 --> 00:34:55,860 Then in the August of 2021, 607 00:34:55,860 --> 00:34:58,140 a security bug on the origin header 608 00:34:58,140 --> 00:35:00,720 was independently reported. 609 00:35:00,720 --> 00:35:02,723 It was related to the origin problem 610 00:35:02,723 --> 00:35:04,773 we previously discussed. 611 00:35:07,800 --> 00:35:08,790 In September, 612 00:35:08,790 --> 00:35:11,550 other researchers started noticing the same problem. 613 00:35:11,550 --> 00:35:14,583 So duplicate bugs were independently reported. 614 00:35:17,370 --> 00:35:18,570 In October, 615 00:35:18,570 --> 00:35:23,430 a service worker spec meeting on the CSRF issue was held. 616 00:35:23,430 --> 00:35:27,810 It spawned about 14 separate issues in different specs, 617 00:35:27,810 --> 00:35:32,013 including service worker fetch and storage partitioning. 618 00:35:35,610 --> 00:35:38,583 Three weeks later, Chromium patched both bugs. 619 00:35:40,920 --> 00:35:44,463 And in December, the fetch spec was amended. 620 00:35:45,990 --> 00:35:47,272 As we discussed, 621 00:35:47,272 --> 00:35:50,970 the problem was that the origin of the new request 622 00:35:50,970 --> 00:35:54,982 was client, and the client was pointing to this, 623 00:35:54,982 --> 00:35:57,933 which was the service worker itself. 624 00:35:59,700 --> 00:36:02,640 Now, the amended spec properly propagates 625 00:36:02,640 --> 00:36:06,693 the original request's origin information. 626 00:36:09,540 --> 00:36:11,820 In the January of 2022, 627 00:36:11,820 --> 00:36:14,040 finally Chrome 97 was released 628 00:36:14,040 --> 00:36:15,963 to the stable channel with the fix. 629 00:36:18,570 --> 00:36:20,733 And the next day, Google assigned a CVE. 630 00:36:23,490 --> 00:36:25,050 On July 27th, 631 00:36:25,050 --> 00:36:27,060 the Cookie spec was amended 632 00:36:27,060 --> 00:36:29,190 so that the site for cookies logic 633 00:36:29,190 --> 00:36:31,473 is handled by the service worker spec. 634 00:36:34,200 --> 00:36:37,800 So no update for Firefox is available as of now. 635 00:36:37,800 --> 00:36:40,560 The affected versions are Google Chrome 636 00:36:40,560 --> 00:36:44,700 from 51 up to 97, and Mozilla Firefox from 60, 637 00:36:44,700 --> 00:36:49,603 and for the Developer Tools bug is from 74. 638 00:36:53,910 --> 00:36:56,190 There still is one remaining issue, 639 00:36:56,190 --> 00:36:58,470 and that is a nested frame. 640 00:36:58,470 --> 00:37:00,360 In case of victim one, 641 00:37:00,360 --> 00:37:04,468 let's say news.com, and embeds an attacker ad.com, 642 00:37:04,468 --> 00:37:07,893 which also embeds victim two, news.com. 643 00:37:12,120 --> 00:37:15,128 Since the nested frame and its parent, 644 00:37:15,128 --> 00:37:19,563 the nested attacker frame, are cross-site, 645 00:37:20,850 --> 00:37:23,763 you cannot set nor send a strict cookie. 646 00:37:26,730 --> 00:37:31,170 But if we register the passthrough service worker, 647 00:37:31,170 --> 00:37:34,653 listening to fetch events, now access is possible. 648 00:37:38,365 --> 00:37:41,448 (audience applauds) 649 00:37:45,240 --> 00:37:47,700 This particular problem is to be addressed 650 00:37:47,700 --> 00:37:50,373 with the Client-Side Storage Partitioning spec. 651 00:37:51,810 --> 00:37:53,343 So then conclusions. 652 00:37:54,600 --> 00:37:56,610 To recap, 653 00:37:56,610 --> 00:37:59,705 in this talk, we discussed SameSite of HTTP cookie 654 00:37:59,705 --> 00:38:03,300 centered around cross-site request and CSRF. 655 00:38:03,300 --> 00:38:06,570 We discussed SameSite attribute and Lax by default 656 00:38:06,570 --> 00:38:08,880 as a defense against CSRF. 657 00:38:08,880 --> 00:38:11,880 Next, we discussed service worker of PWA. 658 00:38:11,880 --> 00:38:14,340 We discussed the caching flow with service worker 659 00:38:14,340 --> 00:38:15,930 and code examples. 660 00:38:15,930 --> 00:38:18,810 Then we moved on to the CSRF Resurrections. 661 00:38:18,810 --> 00:38:21,446 We took a deep dive into the related web specs 662 00:38:21,446 --> 00:38:24,345 and how SameSite defense gets bypassed 663 00:38:24,345 --> 00:38:27,060 when a service worker is involved. 664 00:38:27,060 --> 00:38:28,680 Using this code examples, 665 00:38:28,680 --> 00:38:32,730 I showed how a developer can easily introduce this problem. 666 00:38:32,730 --> 00:38:35,340 Finally, we talked about the aftermath. 667 00:38:35,340 --> 00:38:37,320 The disclosure timeline was mentioned, 668 00:38:37,320 --> 00:38:41,103 and we discussed the remaining issue of a nested frame. 669 00:38:43,650 --> 00:38:46,290 Let's finish up with takeaways. 670 00:38:46,290 --> 00:38:48,900 Firstly, do not use SameSite cookies 671 00:38:48,900 --> 00:38:52,470 as the sole defense mechanism against CSRF. 672 00:38:52,470 --> 00:38:56,760 They should be considered as an additional layer of defense. 673 00:38:56,760 --> 00:39:01,593 As plainly written in the Cookie specification, quote: 674 00:39:01,593 --> 00:39:04,980 Developers are strongly encouraged to deploy the usual 675 00:39:04,980 --> 00:39:07,080 server-side defenses to mitigate 676 00:39:07,080 --> 00:39:09,064 the risk more fully, unquote. 677 00:39:09,064 --> 00:39:12,000 Also, double-check network interactions 678 00:39:12,000 --> 00:39:14,370 with other tools when they're possible. 679 00:39:14,370 --> 00:39:18,510 The browsers' Developer Tools might not actually depict 680 00:39:18,510 --> 00:39:21,873 the reality in some cases. 681 00:39:22,800 --> 00:39:26,310 Since it is still an ongoing problem with Firefox 682 00:39:26,310 --> 00:39:27,395 and the nested frame, 683 00:39:27,395 --> 00:39:29,774 this is a new attack vector until 684 00:39:29,774 --> 00:39:32,733 the issues are fully resolved. 685 00:39:33,570 --> 00:39:34,403 Finally, 686 00:39:34,403 --> 00:39:38,520 is there any other subtle complex specification level 687 00:39:38,520 --> 00:39:42,093 problem that has been overlooked and how do we find it? 688 00:39:44,100 --> 00:39:45,300 And that's it. 689 00:39:45,300 --> 00:39:47,730 I'd like to thank Oscar and Louis for their feedback 690 00:39:47,730 --> 00:39:49,410 and Betty for proofreading. 691 00:39:49,410 --> 00:39:51,435 Thank you all very much for listening. 692 00:39:51,435 --> 00:39:54,435 (audience applauds)