New Csrf Token Per Request or Not

New CSRF token per request or NOT?

If you do it per form request - then you basically remove the ability for CSRF attacks to occur & you can solve another common issue: multiple form submission

In simple terms - your application will only accept form input if the user ASKED for the form prior to the submission.

Normal scenario:
User A goes to your website, and asks for Form A, is given Form A plus a unique code for Form A. When the user submits Form A, he/she must include the unique code which was only for Form A.

CSRF Attack scenario: User A goes to your website, and asks for Form A. Meanwhile they visit another "bad" site, which attempts a CSRF attack on them, getting them to submit for a fake Form B.

But your website knows that User A never asked for Form B - and therefore even though they have the unique code for Form A, Form B will be rejected, because they dont have a Form B unique Code, only a Form A code. Your user is safe, and you can sleep easy at night.

But if you do it as a generic token, lasting for an hour (like you posted above) - then the attack above might work, in which case you've not achieved much with your CSRF protection. This is because the application does not know that form B was never asked for in the first place. It is a generic token. The WHOLE POINT of CSRF prevention is to make each form token unique to that form

Edit: because you asked for more information:
1 - you dont have to do it per form request, you can do it per hour/session etc. The point is a secret value that is given to the user, and resubmiited on the return. This value is not known by another website, and thus cannot submit a false form.

So you either generate the token per request, or per session:

// Before rendering the page:
$data['my_token'] = md5(uniqid(rand(), true));
$_SESSION['my_token'] = $data['my_token'];

// During page rendering:
<input type="hidden" name="my_token" id="my_token" value="<? php echo $_SESSION['my_token']?>" />

// After they click submit, when checking form:
if ($_POST['my_token'] === $_SESSION['my_token'])
{
// was ok
}
else
{
// was bad!!!
}

and because it is "per form" - you wont get double form submissions - because you can wipe the token after the first form submission!

how does csrf token per request work

The following link might help, but I'll summarize here.

https://nirajrules.wordpress.com/2010/01/16/cross-site-scripting-xss-vs-cross-site-request-forgery/

CSRF is more about cross site requests. Somebody just finding your form actions and posting to them directly, for example. That is what a CSRF token helps to prevent. Imagine people making a fake website, a phishing site, that actually calls through to your form submit endpoints.

XSS is very different, and you are right that any malicious javascript that is able to be run within your page would be able to access and grab the token. But these are different things, and doesn't diminish the value of CSRF tokens.

Good luck.

CSRF token per request in spring security

You can change the default implementation of CsrfTokenRepository by providing your own implementation of this interface and configure it like:

<http>
<csrf token-repository-ref="myRequestCsrfTokenRepository"/>
</http>
<b:bean id="myRequestCsrfTokenRepository"
class="com.company.security.RequestCsrfTokenRepository"/>

But... although you wrote that this is a must requirement, you should really rethink it again. I would even advice to try convincing the other end that this change could bring more security to the app users but can also bring a lot of inconveniences, sometimes strange behaviors and in general decrease the usability and user experience. E.g. see Different csrf token per request in Spring security

CSRF protection: do we have to generate a token for every form?

In general, it suffices to have just one token per session, a so called per-session token:

In general, developers need only generate this token once for the current session. After initial generation of this token, the value is stored in the session and is utilized for each subsequent request until the session expires.

If you want to further enhance the security, you can use one token per each form/URL (per-form token) to mitigate the impact when one token leaks (e. g. XSS) as an attacker would only be able to successfully attack that specific form/URL.

But using per-request tokens, i. e. tokens that change with each request, rather cuts the usability of the website as it restricts parallel browsing:

To further enhance the security of this proposed design, consider randomizing the CSRF token […] for each request. Implementing this approach results in the generation of per-request tokens as opposed to per-session tokens. Note, however, that this may result in usability concerns. For example, the "Back" button browser capability is often hindered as the previous page may contain a token that is no longer valid. Interaction with this previous page will result in a CSRF false positive security event at the server.

So I recommend you to use either per-session tokens or per-form tokens.

Why does Express/Connect generate new CSRF token on each request?

CSRF tokens are nonces. They are supposed to be used only once (or safely after a long time). They are used to identify and authorize requests. Let us consider the two approaches to prevent CSRF:

  1. Single token fixed per session: The drawback with this is that the client can pass its token to others. This may not be due to sniffing or man-in-the-middle or some security lapse. This is betrayal on user's part. Multiple clients can use the same token. Sadly nothing can be done about it.

  2. Dynamic token: token is updated every time any interaction happens between server and client or whenever timeout occurs. It prevents use of older tokens and simultaneous use from multiple clients.

The drawback of the dynamic token is that it restricts going back and continuing from there. In some cases it could be desirable, like if implementing shopping cart, reload is must to check if in stock. CSRF will prevent resending the sent form or repeat buy/sell.

A fine-grained control would be better. For the scenario you mention you can do without CSRF validation. Then don't use CSRF for that particular page. In other words handle the CSRF (or its exceptions) per route.

Update

I can only think of two reasons why single dynamic token is better than multiple:

  1. Multiple tokens are indeed better but have at least one dynamic token like one above. This means designing a detailed workflow which may become complex. For example see here :

    1. https://developers.google.com/accounts/docs/OAuth2
    2. https://dev.twitter.com/docs/auth/implementing-sign-twitter
    3. https://developers.facebook.com/docs/facebook-login/access-tokens/

    These are tokens to access their API (form submission etc.) not just login. Each one implements them differently. Not worth doing unless have good use case. Your webpages will use it heavily. Not to mention form submission is not simple now.

  2. Dynamic single token is the easiest, and the readily available in library. So can use it on the go.

Advantages of multiple tokens:

  1. Can implement transactions. You can have ordering between requests.
  2. Can fallback from timeout and authentication errors (you must handle them now).
  3. Secure! More robust than single tokens. Can detect token misuse, blacklist user.

By the way if you want to use multiple tokens you have OAuth2 libraries now.



Related Topics



Leave a reply



Submit