You can get acquainted with the very idea of a CSRF attack on classic resources:
The reason for CSRF lies in the fact that browsers do not understand how to distinguish whether an action was explicitly performed by the user ( like, say, clicking a button on a form or following a link ) or the user unintentionally performed this action ( for example, when visiting bad.com
, A request was sent to good.com/some_action
, while the user was already logged in to good.com
).
An effective and generally accepted way to protect against CSRF-Attack is a token . A token means a random set of bytes that the server sends to the client, and the client returns to the server.
Protection comes down to verifying the token that the server generated and the token that the user sent.
If you write your Web-Service in accordance with the RFC7231 standard, then the GET
, HEAD
, OPTIONS
and TRACE
methods are safe: they are for information only and should not change the state of the server.
Thus, it is necessary to protect the unsafe methods, which include: POST
, PUT
, DELETE
, PATCH
.
On Habrahabr published an article from Yandex, which describes why you need to write your services, guided by the standard .
At the first PDU MeetUp meeting, Timur Yunusov ( head of banking security department
Systems Positive Technologies ) told why exactly such requirements are imposed on the CSRF-Token and what threatens to neglect them.
Lack of XSS vulnerabilities
Introduced by the attacker script has the ability to send a request to the server on behalf of the user and read it without any obstacles.
Thus, XSS vulnerabilities can be used to obtain the current token.
No malware on the client machine
If the attacker has the ability to run the software on the client’s machine, he can get any data that is available in the browser.
There are 3 methods of using tokens to protect web services from CSRF attacks:
A simple approach that is used everywhere. Requires server-side storage.
When the session starts , a token is generated on the server side.
The token is placed in the session data storage ( i.e. stored on the server side for subsequent verification )
In response to the request ( which started the session ), the client returns a token.
If rendering occurs on the server , then the token can be returned inside HTML, such as one of the form fields, or inside the <meta>
tag.
In case the answer is returned for the JS application , the token can be passed to the header ( often X-CSRF-Token
used for this )
In subsequent requests, the client is obliged to transfer the token to the server for verification.
When rendering the content by the server, the token is usually returned within the POST form data .
JS applications usually send XHR requests with a header ( X-CSRF-Token
) containing the token.
When receiving a request with an insecure method ( POST
, PUT
, DELETE
, PATCH
), the server must check the identity of the token from the session data and the token that the client sent .
If both tokens match, then the request has not been subjected to CSRF-Attack, otherwise we log the event and reject the request.
CSRF protection at a good level
The token is updated only when the session is re-created , and this happens when the session expires.
During the life of one session, all actions will be checked on one token .
If a token leaks, the attacker can perform a CSRF Attack on any request and for a long time . And this is not good.
Free multi-tab browser support.
The token is not disabled after the execution of the request, which allows the developer not to worry about synchronization of the token in different browser tabs, since the token is always the same.
This approach does not require server-side data storage, which means it is Stateless . Used if you want to be able to quickly and accurately scale your Web service horizontally.
The idea is to give the token to the client by two methods: in cookies and in one of the response parameters ( header or inside HTML ).
When a request is received from the client, a token is generated on the server side. In the response, the token is returned in the cookie (for example, X-CSRF-Token
) and in one of the response parameters ( in the header or inside HTML ).
In subsequent requests, the client must provide both tokens received earlier. One as a cookie, the other as either a header , or inside a POST form data .
When a request is received by an insecure method ( POST
, PUT
, DELETE
, PATCH
), the server must check the cookie token for identity and the token that the client has explicitly sent .
If both tokens match, then the request has not been subjected to CSRF-Attack, otherwise we log the event and reject the request.
Stateless CSRF protection.
It is necessary to take into account that subdomains can read cookies of the main domain, if this is not explicitly .site.ru
(that is, if the cookie is set on .site.ru
, then it can be read both by a.site.ru
and b.site.ru
).
Thus, if your service is available on the 3rd level domain, and the attacker has the opportunity to register his resource on your 2nd level domain, then set the cookie to your domain explicitly.
Just like Double Submit, is a stateless approach. The main thing is that if you encrypt any data with a reliable algorithm and transfer it to the client, the client will not be able to fake it without knowing the key. This approach does not require the use of cookies. The token is sent to the client only in the response parameters.
In this approach, tokens are facts encrypted with a key . The minimal necessary facts are the user ID and the timestamp of the token generation time. The key should not be known to the client.
When a request is received from the client, a token is generated on the server side.
Generation of the token consists in encrypting the facts necessary for validation of the token in the future.
The minimum required facts are the user ID and the timestamp . In response, the token is returned in one of the response parameters ( In the header or inside HTML ).
In subsequent requests, the client is obliged to provide the previously received token.
When receiving a request using an insecure method ( POST
, PUT
, DELETE
, PATCH
), the server must validate the token received from the client.
Validation of a token consists in deciphering it and comparing facts obtained after decryption with real ones. (The timestamp check is necessary to limit the lifetime of the token)
If it was not possible to decrypt or the facts do not match, it is considered that the request was subjected to CSRF-Attack.
Stateless CSRF protection
No need to store data in the cookie.
Let's generate a new token for each request, no matter what HTTP method and for what purpose this request is made.
Thus, we get a token that changes constantly.
Of course, the question arises of organizing multi-tab work.
Synchronization of tokens between tabs can be implemented using localStorage and its StorageEvent
We limit the lifetime of the cookie, which contains the token, to a reasonable value. For example, 30 minutes.
Making the cookie inaccessible from JS (set HTTPOnly = true )
Use TLS to prevent MITM
At the same time, we send cookies only over HTTPS (set Secure = true )
The size of the token is at least 32 bytes .
We generate a token with a cryptographically stable pseudo-random number generator.
To do this, you can use the system functions:
Linux => getrandom(2) , /dev/urandom OpenBSD => getentropy(2) Unix-like => /dev/urandom Windows => CryptGenRandom API
Tokens - mandatory protection against CSRF.
Check, but do not rely solely on X-Requested-With: XMLHttpRequest
Check, but do not rely only on the headers: Host
, Origin
, Referer
Do not pass tokens in URL
We are currently working on the specification of the "Same Site" attribute for cookies (the latest version at the time of this writing).
Such an attribute will enable developers to explicitly indicate that the cookie should not be sent if the request comes from a site other than the one on which the cookie was set. This means that we will have the opportunity to protect resources from CSRF without using additional tools.
Chrome browser now supports this feature.
A little more information on how and why is available on the Stack Exchange .
Source: https://habr.com/ru/post/318748/
All Articles