Safety Cribs: CSRF

image



Despite the fact that in the last published list of vulnerabilities of OWASP Top 10 2017 CSRF attacks are classified as “Deleted, but not forgotten”, we decided that it would not be superfluous to once again recall how to defend against CSRF attacks, relying on those the same rules provided by OWASP.



Using CSRF Token



Using a token (both stateless and statefull methods) is the primary and most popular way of protection. The token must be unique for each user session, generated by a cryptographically robust pseudo random number generator. OWASP also recommends using the AES256-GCM and SHA256 / 512 algorithms for encryption using HMAC.



There are several approaches to working with tokens: Synchronizer Token, Encryption based Token Pattern, HMAC Based Token



Synchronizer token



When using the Synchronizer Token approach (statefull method), it means sending a token on every request, implying some changes on the server side. If the token is not valid, then the server rejects the request.

When sending a request to the server, it is recommended to add a token to the request parameters rather than to the header. If you nevertheless insert the token in the request header, then make sure that it is not logged on the server. The received token can be stored on the client side in a hidden field:



<form action="/post.php" method="post"> <input type="hidden" name="CSRFToken" value="l5824xNMAYFesBxing975yR8HPJlHZ"> ... </form>
      
      







in the headers:



 POST /page HTTP/1.1 Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36 Content-Type: application/json Host: example.com X-CSRF-TOKEN: l5824xNMAYFesBxing975yR8HPJlHZ
      
      







or in cookies



 POST /page HTTP/1.1 Host: example.com Set-Cookie: CSRFToken=l5824xNMAYFesBxing975yR8HPJlHZ; Content-Type: application/x-www-form-urlencoded
      
      







OWASP recommends storing the token in the headers, explaining that even if the token is opened or has expired, the attacker will still not be able to fake the request, due to the browsers.



Also, to increase the security level of the proposed method, it is proposed to generate a random token parameter name and / or token for each request. With this approach, the time during which the attacker can use the stolen token is minimal. However, this can lead to usability issues. For example, clicking on the “Back” button may lead to the sending of an invalid token to the server, which was contained on the previous page.



Sending a token using a GET request is not recommended, since with this approach the token can be revealed: in the browser history, log files, referrer headers.



Encryption based token



This approach is stateless, as it uses encryption / decryption to validate the token, and therefore does not require storage of the token on the server side.



The server generates a token consisting of a session identifier and a timestamp (to prevent a replay attack). For encryption, it is recommended to use the AES256 encryption algorithm in the GSM / GSM-SIV block encryption mode. Using ECB mode is strongly discouraged. The token encrypted by the server is returned to the client in the same way as in the case of “Synchronizer Token” in the hidden form field or in the response header / parameter. Upon receipt of the token, the server must decrypt it, after which check the session identifier, and also check the timestamp with the current time and make sure that it does not exceed the set token lifetime.

If the verification of the session identifier is successful, but timesmap is not, then the request can be considered valid. In all other cases, it is recommended to reject the request and register it in order to further understand how to respond to such requests.



HMAC Based Token



It also does not require storage of the token, the principle of operation is similar to Encryption based Token, except that instead of encrypting the token, the HMAC (hash-based message authentication code) function is used to generate the token (it is recommended to use SHA256 or a stronger algorithm). In this case, the token is the result of the HMAC function of the user session identifier + timestamp.



Token Automation



The main problem in counteracting CSRF attacks is that developers often simply forget to add functionality to work with tokens. To avoid such problems, it is worth automating this process:



• write a wrapper that automatically adds a token to requests via the form tag or when using ajax. For example, Spring Security takes a similar approach every time the <form: form> tag is used.



• write a hook that intercepts traffic and adds tokens to all vulnerable resources. Since it is quite difficult to analyze which request the state change is performing, requiring a token, it is recommended to include tokens in all POST responses, but it is worth considering the cost of performance



• automatically add a token when rendering a page. This approach is used by CSRF Guard: tokens are added to all href and src attributes, hidden fields and in all forms



Before trying to write your own system of automatic token generation, it is recommended to clarify whether your framework has the ability to provide protection against CSRF attacks by default. For example, the same Django framework implements protection against CSRF.





Login CSRF



Using CSRF in the login form, an attacker can log in,

disguised as a victim. Such a vulnerability was faced by such giants as PayPal and Google.

You can deal with CSRF in the login form by creating pre-sessions that are created before the user is authenticated, and by including tokens in the login form.





Samesite cookie



SameSite Cookie is an attribute described in RFC6265bis whose purpose is to counteract CSRF attacks. It works as follows. One of the methods of protection is checking the origin and referer headers, by which you can understand where the request came from, but this approach requires the implementation of a verification mechanism. Using the SameSite attribute, we restrict the sending of cookies with a request from extraneous resources. This attribute has several possible values: Strict, Lax, and None.

Using the strict value implies that the browser will not send cookies from any sources that do not match the domain name of the current resource.

The value lax makes it possible not to block cookies from external resources, the transition from which was carried out in a safe way - using the HTTPS protocol. Lax strikes a balance between usability and security.



Setting an attribute is pretty simple:



 Set-Cookie: JSESSIONID=xxxxx; SameSite=Strict Set-Cookie: JSESSIONID=xxxxx; SameSite=Lax
      
      







At the time of this writing, attribute support for browsers looks like this:



image





It is important to remember that this attribute should be used as an additional measure of protection, and not as a way to do without using the CSRF token.



Checking Headers



As mentioned above, one of the protection methods is checking the referrer and origin values ​​of the request header.

The essence of this check is to check the values ​​of the headers on the server side. If they match the resource, then the request is considered correct; otherwise, it is rejected. If the Origin header is missing, you need to make sure that the Referrer value matches the current resource. OWASP recommends rejecting requests that do not contain Origin or Referrer headers. You can also log all such requests in order to then analyze them and decide on how to deal with them.



However, things get complicated if your application is behind a proxy server, since the URL in the header will be different. In this case, there are several options:

• Configure your application so that you always know the origin of the request. The problem with this approach is to set the correct value if your application is deployed in several environments (for example, dev, QA, production), which leads to a support problem

• use the Host header. This header will allow you to determine the source of the request, regardless of the environment.

• use the X-Forwarded-Host header, the purpose of which is to store the original headers received by the proxy server



All described methods work only when origin and referer headers are present. But there are cases when these headers are missing. Here are a few cases where these headers are not included in the request:

• IE 11 does not include the Origin header for trusted sites. It remains to rely only on the Referer header.

• in the case of a redirect, Origin is not included in the request, as it is believed that it may contain confidential information that should not be sent to another source

• Origin header is included for all cross-site requests, but most browsers add it only for POST / DELETE / PUT requests



As a rule, a small amount of traffic falls into the described categories, but often you do not want to lose even this small part of users, so it is considered valid to request with a null value for origin / referrer or with a value corresponding to the list of trusted domains.



Double Submit Cookie



This approach is quite simple to implement and does not require storage of the token on the server side (stateless). The essence of the method is to send the token in the request parameter and in cookies by the user. Each request that requires a state change, we verify the value of the token in cookies and in the request. If the verification of the session identifier is successful, but timesmap is not, then the request may be considered valid




All Articles