﻿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)


