Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent CSRF in a RESTful application?

Cross Site Request Forgery (CSRF) is typically prevent with one of the following methods:

  • Check referer - RESTful but unreliable
  • insert token into form and store the token in the server session - not really RESTful
  • cryptic one time URIs - not RESTful for the same reason as tokens
  • send password manually for this request (not the cached password used with HTTP auth) - RESTful but not convenient

My idea is to use a user secret, a cryptic but static form id and JavaScript to generate tokens.

<form method="POST" action="/someresource" id="7099879082361234103">     <input type="hidden" name="token" value="generateToken(...)">     ... </form> 
  1. GET /usersecret/john_doe fetched by the JavaScript from the authenticated user.
  2. Response: OK 89070135420357234586534346 This secret is conceptionally static, but can be changed every day/hour ... to improve security. This is the only confidential thing.
  3. Read the cryptic (but static for all users!) form id with JavaScript, process it together with the user secret: generateToken(7099879082361234103, 89070135420357234586534346)
  4. Send the form along with the generated token to the server.
  5. Since the server knows the user secret and the form id, it is possible to run the same generateToken function as the client did before sending and compare both results. Only when both values are equal the action will be authorized.

Is something wrong with this approach, despite the fact that it doesn't work without JavaScript?

Addendum:

  • Stateless CSRF Protection
like image 636
deamon Avatar asked Mar 06 '10 10:03

deamon


People also ask

How do you prevent CSRF attacks in REST API?

Enable CSRF Protection With REST API If our project requires CSRF protection, we can send the CSRF token with a cookie by using CookieCsrfTokenRepository in a custom WebSecurityConfigurerAdapter. After restarting the app, our requests receive HTTP errors, which means that CSRF protection is enabled.

Do REST API need CSRF protection?

Enabling cross-site request forgery (CSRF) protection is recommended when using REST APIs with cookies for authentication. If your REST API uses the WCToken or WCTrustedToken tokens for authentication, then additional CSRF protection is not required.

How can CSRF attacks be prevented?

What Are CSRF Tokens. The most popular method to prevent Cross-site Request Forgery is to use a challenge token that is associated with a particular user and that is sent as a hidden value in every state-changing form in the web app.

How do I disable CSRF in application properties?

The CSRF feature can be disabled using the code “ http. csrf(). disable ()”.


2 Answers

There are a lot of answers here, and problems with quite a few of them.

Things you should NOT do:

  1. If you need to read the session token from JavaScript, you're doing something horribly wrong. Your session identifier cookie should ALWAYS have HTTPOnly set on it so its not available to scripts.

    This one protection makes it so that the impact of XSS is considerably reduced, since an attacker will no longer be able to get a logged in users session token, which for all intents and purposes are the equivalent of credentials in the application. You don't want one error to give keys to the kingdom.

  2. The session identifier should not be written to the contents of the page. This is for the same reasons you set HTTPOnly. This means that that your csrf token can not be your session id. They need to be different values.

Things you should do:

  1. Follow OWASP's guidance:

  2. Specifically, if this is a REST application you can require double-submission of CSRF tokens. If you do this, just be sure that you define it to a specific full-domain (www.mydomain.com) and not a parent domain (example.com), and that you also utilize the "samesite" cookie attribute which is gaining popularity.

Simply create something cryptographically random, store it in ASCII Hex or Base64 encode, and add it as a cookie and to your forms when the server returns the page. On the server side make sure that the cookie value matches the form value. Voila, you've killed CSRF, avoided extra prompts for your users, and not opened yourself up to more vulnerabilities.

NOTE: As @krubo states below the double-submission technique has been found to have some weaknesses (See Double-Submission). Since this weakness requires that:

  1. You define a cookie scoped to the parent domain.
  2. You fail to set HSTS.
  3. The attacker controls some network location inbetween the user and the server

I kind of think the weakness falls more in the category of a "Cool Defcon Talk" rather than a "Realworld Security Risk". In any case, if you are going to use double-submission it doesn't hurt to take a few extra steps to protect yourself fully.


New Update 07/06/2020

My new favorite way to do double-submission is to create and pass a cryptographic random string in the body of the request as before; but rather than have the cookie be the same exact value have the cookie be the encoded value of the string being signed by a certificate. This is still just as easy to validate on the server side, but is MUCH harder for an attacker to mimic. You should still use the samesite Cookie attribute and other protections outlined earlier in my post.

like image 146
Doug Avatar answered Oct 09 '22 08:10

Doug


Am I getting this right:

  • You want protection against CSRF for users logged in via cookies.
  • And at the same time you want RESTful interface for Basic, OAuth and Digest authenticated requests from apps.

So, why not check whether users is logged in via cookie and apply CSRF only then?

I'm not sure but is possible for another site to forge things like Basic auth or headers?

As far as I know , CSRF is all about cookies? RESTful auth doesn't happen with cookies.

like image 35
antitoxic Avatar answered Oct 09 '22 06:10

antitoxic