Uncategorized

How to Prevent Cross-Site Request Forgery (CSRF) Attacks 

Cross-Site Request Forgery (CSRF) Attacks

Cross-Site Request Forgery (CSRF) is a serious cyberattack that tricks users into unknowingly performing actions on websites where they are already logged in. Attackers exploit this by forcing a user’s browser to send a malicious request to another site, leveraging the user’s authenticated session. This can result in unauthorized actions like changing account details, transferring funds, or modifying user data. For web developers, understanding how CSRF works and applying strong protection measures is crucial to safeguarding user information. 

How CSRF works? 

At the core of CSRF attacks is the trust a website places in the user’s browser. When a user logs onto a website, their browser automatically stores a session cookie to authenticate future requests. Attackers exploit this by creating malicious links or forms that, when clicked, send requests using the victim’s authenticated session. 

For example: 

  • A user is logged into their banking application.
  • The attacker sends an email with a link that performs a transaction using the bank’s authenticated session. 
  • When the user clicks the link, their browser sends a request to the banking site, executing the attacker’s intended action without the user’s knowledge. 

Preventing CSRF Attacks: 

There are multiple ways to protect your applications against CSRF. Let’s dive into some of the most effective techniques: 

1. Use CSRF Tokens 

The most common and effective method to prevent CSRF attacks is using anti-CSRF tokens. These tokens are unique, unpredictable values generated by the server and included in forms or AJAX requests. When the server receives a request, it checks if the CSRF token matches the expected value. 

How it works: 

  1. The server generates a CSRF token when the user accesses a form. 
  2. This token is embedded in the form as a hidden input. 
  3. When the form is submitted, the token is sent back to the server. 
  4. If the token in the request matches the one stored on the server, the request is considered valid. 

Implementation Example in Express (Node.js): 

const csrf = require('csurf'); 

const csrfProtection = csrf({ cookie: true });

app.use(csrfProtection);

app.get('/form', (req, res) => {

res.render('form', { csrfToken: req.csrfToken() });

});

The CSRF token ensures that the request originates from the same site, preventing unauthorized actions from external sources. 

2. SameSite Cookie Attribute 

Another modern technique is using the SameSite cookie attribute. This attribute restricts how cookies are sent with requests, depending on where the request originates. 

How it works: 

  1. SameSite=Lax: Cookies are not sent with cross-origin requests, except for top-level navigation GET requests. This is a good default setting for most use cases. 
  2. SameSite=Strict: Cookies are only sent if the request originates from the same site. This is the most secure setting but can impact user experience. 
  3. SameSite=None: Cookies are sent with all requests, including cross-origin. However, it must be used with the Secure attribute (only transmitted over HTTPS).

This approach mitigates CSRF attacks by ensuring cookies are only included in requests that originate from the same site. 

Implementation Example (Set-Cookie header): 

Set-Cookie: sessionId=abc123; SameSite=Lax; Secure 

3. Double Submit Cookies 

In the Double Submit Cookie method, the server sets a cookie with a random CSRF token and expects that token to be included both in the request body (or headers) and the cookie. When a request is received, the server verifies that the token from the body matches the token from the cookie. 

Here’s how it works: 

  1. The server sends the CSRF token in two places: a cookie and a hidden field (or header). 
  2. The client sends both tokens in the next request. 
  3. The server checks if the values match. If they do, the request is valid. 

This method adds an extra layer of protection by decoupling the CSRF token from the session management. 

4. Implement CORS Policies 

Cross-Origin Resource Sharing (CORS) is a security feature that controls how resources can be shared between different domains. To prevent CSRF, it’s important to implement strict CORS policies: 

  1. Restrict access to trusted origins. For example, only allow requests from your own domain or a set of trusted subdomains. 
  2. Deny unsafe methods (like PUT, DELETE, or POST) from being executed cross-origin unless it’s explicitly allowed by your CORS policy. 

Implementation Example in Express (Node.js): 

const cors = require('cors'); 
app.use(cors({ 
origin: 'https://trusted-origin.com', 
methods: ['GET', 'POST'], 
credentials: true, 
})); 

5. Enforce Multi-Factor Authentication (MFA) 

While MFA is not a direct solution for CSRF, it adds an extra layer of protection for sensitive actions. By requiring users to verify their identity using a secondary factor (like an SMS code or authenticator app), it becomes significantly harder for attackers to execute malicious actions. 

6. Secure HTTP Methods 

Wherever possible, restrict CSRF-sensitive actions (such as data modifications) to non-idempotent HTTP methods like POST or PUT. Avoid using GET requests for actions that cause side effects, as GET is more susceptible to CSRF exploitation. 

Conclusion 

Preventing Cross-Site Request Forgery (CSRF) is key to protecting the integrity and security of web applications. Using CSRF tokens, setting up SameSite cookie attributes, enabling CORS, and enforcing multi-factor authentication can significantly lower the risk of these attacks. It’s important to regularly update your security practices and stay informed about new threats to keep your users safe.

akshata-kulkarni

Software Engineer