This commit is contained in:
Ilya Kantor 2019-07-29 00:12:34 +03:00
parent 3ba28aa104
commit 34e9cdca36
10 changed files with 55 additions and 62 deletions

View file

@ -55,7 +55,7 @@ If you run it, then probably you'll see multiple cookies. That's because `docume
Technically, name and value can have any characters, to keep the valid formatting they should be escaped using a built-in `encodeURIComponent` function:
```js run
// special values, need encoding
// special characters (spaces), need encoding
let name = "my name";
let value = "John Smith"
@ -192,17 +192,17 @@ To understand how it works and when it's useful, let's take a look at XSRF attac
Imagine, you are logged into the site `bank.com`. That is: you have an authentication cookie from that site. Your browser sends it to `bank.com` with every request, so that it recognizes you and performs all sensitive financial operations.
Now, while browsing the web in another window, you occasionally come to another site `evil.com`, that automatically submits a form `<form action="https://bank.com/pay">` to `bank.com` with input fields that initiate a transaction to the hacker's account.
Now, while browsing the web in another window, you occasionally come to another site `evil.com`. That site has JavaScript code that submits a form `<form action="https://bank.com/pay">` to `bank.com` with fields that initiate a transaction to the hacker's account.
The form is submitted from `evil.com` directly to the bank site, and your cookie is also sent, just because it's sent every time you visit `bank.com`. So the bank recognizes you and actually performs the payment.
The browser sends cookies every time you visit the site `bank.com`, even if the form was submitted from `evil.com`. So the bank recognizes you and actually performs the payment.
![](cookie-xsrf.svg)
That's called a cross-site request forgery (or XSRF) attack.
That's called a "Cross-Site Request Forgery" (in short, XSRF) attack.
Real banks are protected from it of course. All forms generated by `bank.com` have a special field, so called "xsrf protection token", that an evil page can't neither generate, nor somehow extract from a remote page (it can submit a form there, but can't get the data back).
Real banks are protected from it of course. All forms generated by `bank.com` have a special field, so called "XSRF protection token", that an evil page can't generate or extract from a remote page (it can submit a form there, but can't get the data back). And the site `bank.com` checks for such token in every form it receives.
But that takes time to implement: we need to ensure that every form has the token field, and we must also check all requests.
But such protection takes time to implement: we need to ensure that every form has the token field, and we must also check all requests.
### Enter cookie samesite option
@ -212,19 +212,19 @@ It has two possible values:
- **`samesite=strict` (same as `samesite` without value)**
A cookie with `samesite=strict` is never sent if the user comes from outside the site.
A cookie with `samesite=strict` is never sent if the user comes from outside the same site.
In other words, whether a user follows a link from their mail or submits a form from `evil.com`, or does any operation that originates from another domain, the cookie is not sent.
If authentication cookies have `samesite` option, then XSRF attack has no chances to succeed, because a submission from `evil.com` comes without cookies. So `bank.com` will not recognize the user and will not proceed with the payment.
The protection is quite reliable. Only operations that come from `bank.com` will send the `samesite` cookie.
The protection is quite reliable. Only operations that come from `bank.com` will send the `samesite` cookie, e.g. a form submission from another page at `bank.com`.
Although, there's a small inconvenience.
When a user follows a legitimate link to `bank.com`, like from their own notes, they'll be surprised that `bank.com` does not recognize them. Indeed, `samesite=strict` cookies are not sent in that case.
We could work around that by using two cookies: one for "general recognition", only for the purposes of saying: "Hello, John", and the other one for data-changing operations with `samesite=strict`. Then a person coming from outside of the site will see a welcome, but payments must be initiated from the bank website.
We could work around that by using two cookies: one for "general recognition", only for the purposes of saying: "Hello, John", and the other one for data-changing operations with `samesite=strict`. Then a person coming from outside of the site will see a welcome, but payments must be initiated from the bank website, for the second cookie to be sent.
- **`samesite=lax`**
@ -239,11 +239,11 @@ A `samesite=lax` cookie is sent if both of these conditions are true:
2. The operation performs top-level navigation (changes URL in the browser address bar).
That's usually true, but if the navigation is performed in an `<iframe>`, then it's not top-level. Also, AJAX requests do not perform any navigation, hence they don't fit.
That's usually true, but if the navigation is performed in an `<iframe>`, then it's not top-level. Also, JavaScript methods for network requests do not perform any navigation, hence they don't fit.
So, what `samesite=lax` does is basically allows a most common "go to URL" operation to have cookies. E.g. opening a website link from notes satisfies these conditions.
But anything more complicated, like AJAX request from another site or a form submittion loses cookies.
But anything more complicated, like a network request from another site or a form submittion loses cookies.
If that's fine for you, then adding `samesite=lax` will probably not break the user experience and add protection.
@ -265,7 +265,7 @@ This option forbids any JavaScript access to the cookie. We can't see such cooki
That's used as a precaution measure, to protect from certain attacks when a hacker injects his own JavaScript code into a page and waits for a user to visit that page. That shouldn't be possible at all, a hacker should not be able to inject their code into our site, but there may be bugs that let hackers do it.
Normally, if such thing happens, and a user visits a web-page with hacker's code, then that code executes and gains access to `document.cookie` with user cookies containing authentication information. That's bad.
Normally, if such thing happens, and a user visits a web-page with hacker's JavaScript code, then that code executes and gains access to `document.cookie` with user cookies containing authentication information. That's bad.
But if a cookie is `httpOnly`, then `document.cookie` doesn't see it, so it is protected.
@ -352,7 +352,7 @@ Together: [cookie.js](cookie.js).
## Appendix: Third-party cookies
A cookie is called "third-party" if it's placed by domain other than the user is visiting.
A cookie is called "third-party" if it's placed by domain other than the page user is visiting.
For instance:
1. A page at `site.com` loads a banner from another site: `<img src="https://ads.com/banner.png">`.
@ -381,7 +381,7 @@ Also, some modern browsers employ special policies for such cookies:
```smart
If we load a script from a third-party domain, like `<script src="https://google-analytics.com/analytics.js">`, and that script uses `document.cookie` to set a cookie, then such cookie is not third-party.
If a script sets a cookie, then no matter where the script came from -- it belongs to the domain of the current webpage.
If a script sets a cookie, then no matter where the script came from -- the cookie belongs to the domain of the current webpage.
```
## Appendix: GDPR
@ -390,7 +390,7 @@ This topic is not related to JavaScript at all, just something to keep in mind w
There's a legislation in Europe called GDPR, that enforces a set of rules for websites to respect users' privacy. And one of such rules is to require an explicit permission for tracking cookies from a user.
Please note, that's only about tracking/identifying cookies.
Please note, that's only about tracking/identifying/authorizing cookies.
So, if we set a cookie that just saves some information, but neither tracks nor identifies the user, then we are free to do it.
@ -400,7 +400,7 @@ Websites generally have two variants of following GDPR. You must have seen them
1. If a website wants to set tracking cookies only for authenticated users.
To do so, the registration form should have a checkbox like "accept the privacy policy", the user must check it, and then the website is free to set auth cookies.
To do so, the registration form should have a checkbox like "accept the privacy policy" (that describes how cookies are used), the user must check it, and then the website is free to set auth cookies.
2. If a website wants to set tracking cookies for everyone.