Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSRF tokens vs Nonce confusion - are they the same?

Tags:

php

csrf

nonce

In a attempt to make the current application I'm developing more secure, I've been reading about CSRF tokens and also Nonce.

My question simply is, Are CSRF tokens and Nonce the same thing? from what I could gather so far is that both these methods have different techniques to accomplish the same goal, or am I misunderstanding something?

If they are different, could you be nice enough to provide some example code or point me to some links where i can learn more about how to implementing nonces in PHP apps.

Thanks!

like image 327
Zubair1 Avatar asked Apr 17 '11 04:04

Zubair1


People also ask

Is CSRF token always same?

CSRF tokens are often bound to the user's session: while the user is logged in, they keep the same CSRF token. However, there are some security advantages to changing the CSRF token more often, or even on every request.

What is token nonce?

Nonce is a randomly generated, cryptographic token used to prevent the theft of user name tokens used with SOAP messages. Nonce is used with the basic authentication (BasicAuth) method.

What are CSRF tokens?

A CSRF token is a secure random token (e.g., synchronizer token or challenge token) that is used to prevent CSRF attacks. The token needs to be unique per user session and should be of large random value to make it difficult to guess. A CSRF secure application assigns a unique CSRF token for every user session.

Is CSRF and XSRF same?

Cross-site request forgery (also known as XSRF or CSRF) is an attack against web-hosted apps whereby a malicious web app can influence the interaction between a client browser and a web app that trusts that browser.


2 Answers

No, they're not the same.

Nonces prevent replay attacks (prevent eavesdropper from storing signed request and re-submitting it later, e.g. if Alice sends "Pay Bob $100", you don't want somebody to re-send that 100 times).

CSRF tokens patch HTML-specific weakness in authentication of users' action, where 3rd party website can submit forms with credentials of user viewing the site (e.g. JavaScript on evil.example.com submitting form to facebook.com using your browser, authenticated as you).

CSRF tokens need to be secret, otherwise attacker would have the missing piece required to forge a request.

Nonces don't have to be secret if they're signed with requester's secret (as long as attacker cannot replace one nonce with another).

You can allow replay of requests with CSRF tokens and still be secured against CSRF (you're interested whether that was intentional action by the user, but may not necessarily want to stop user from performing it many times).

In fact, that's very often useful property, e.g. allows users to use Back button and re-submit forms with corrected values. If you implement CSRF protection with Nonce-like mechanism, you'll get false alarms when users refresh submitted pages.

An easy way to prevent CSRF without Nonces is to put session ID in a hidden from field (not a value stored in the session, but ID of the session itself, the same that you store in the cookie [session_id() in PHP]). When the form is submitted check that form's session ID matches ID in the cookie. That is enough for CSRF, since attacker cannot know value of the cookie (CSRF only allows attackers to blindly send cookies).

like image 131
Kornel Avatar answered Oct 11 '22 07:10

Kornel


Nonce is usually some random string that is added to request just to change in unpredictable way the data, which is used to calculate the signature. So nonce usually is not used by any server-side business logic.

While CSRF-token is stored somewhere on server, passed to the client and need to be returned back to the server to compare. And if matches - then OK.

So in your case the better will be to save csrf token once in a session variable like

$_SESSION['csrf_token'] = bin2hex(random_bytes(16));

and use it unchanged during the session life in all forms you have in your application.

(If you don't have random_bytes(), use random_compat to polyfill it.)

like image 23
zerkms Avatar answered Oct 11 '22 08:10

zerkms