Question

I'm using tokens to prevent CSRF attacks in my application. But this application is single page and heavily AJAX based, so I need to find a way to provide a valid token for N actions in a single page:

e.g. A document fragment loads with 3 possible actions, each action needs a token to work properly but server side has just one valid token at time...

Since each token is just a encrypted nonce (the value isn't based in a specific form), I came with the idea of automatize the token assignation for each action with something like this:

  1. The App intercepts an AJAX call, and check if it's a sensitive action (i.e. delete a user)
  2. A token is requested to the server before the action proceed
  3. The token is generated and then added to the action request
  4. The action in executed since the request included a valid token
  5. Do the same for any subsequent actions executed via AJAX

I believe that method isn't effective enough because the attacker can use a script that does exactly the same my App does (retrieve token and append to the request).

How can I improve my method to be effective against CSRF attacks?

Additional info: My backend environment is PHP/Phalcon and the tokens are generated using Phalcon.

Was it helpful?

Solution

A simpler method than using tokens for an AJAX only might be to check headers that can only be present in an AJAX request from your own domain.

Two options are:

The Origin header can also be used for normal HTML form submissions, and you would verify that this contains the URL of your own site before the form submission does its processing.

If you decide to check the X-Requested-With header, you will need to make sure it is added to each AJAX request client side (JQuery will do this by default). As this header cannot be sent cross domain (without your server's consent to the browser first), checking that this is present and set to your own value (e.g. "XMLHttpRequest") will verify that the request is not a CSRF attack.

OTHER TIPS

I had to deal with something similar awhile ago. Requesting nonces with ajax is a super bad idea – IMHO, it invalidates the whole point of having them if the attacker can simply generate it without reloading the page. I ended up implementing the following:

  1. Nonce module (the brain of the operation) that handles creation, destruction, validation and hierarchy of nonces (e.g., child nonces for one page with multiple inputs).
  2. Whenever a form / certain input is rendered, nonce is generated and stored in a session with expire timestamp.
  3. When the user is done with an action / form / page, the nonce with it's hierarchy is destroyed. Request may return a new nonce if the action is repetitive.
  4. Upon generating a new nonce old ones are checked and expired ones are removed.

The major trouble with it is deciding when the nonce expires and cleaning them up, because they grow like bacteria on steroids. You don't want a user to submit a form that was open for an hour and get stuck because the nonce is expired / deleted. In those situations you can return 'time out, please try again' message with the regenerated nonce, so upon the following request everything would pass.

As already suggested, nothing is 100% bullet proof and in most cases is an overkill. I think this approach is a good balance between being paranoid and not wasting days of time on it. Did it help me a lot? It did more with being paranoid about it compared to improving the security dramatically.

Logically thinking, the best thing you could do in those situations is to analyse the behaviour behind the requests and time them out if they get suspicious. For example, 20 requests per minute from one ip, track mouse / keyboard, make sure they are active between the requests. In other words ensure that requests are not automated, instead of ensuring they come with valid nonces.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top