1

I would like to create a new token for each request and would like to us the following template-

 <script>
        var current_token=<?php echo $_SESSION['csrf_token']; ?>

            $.ajax({ 
                type: "POST",
                url:"script.php",
                data: {'token':current_token},
                success: function(data) {
                                var result=JSON.parse(data);
                                current_token=result.token;
                            },
                error:function(error){
                                console.log(error);
                }
          });
  </script>

here is script.php

 <?php

     if($_POST['current_token']==$_SESSION['csrf_token']){

          //do your thing 
          $token="new token" //generate new token here
          $_SESSION['token']=$token;
          $response['token']=$token;
          $out=json_encode($response);
          die ($out);       
    }else{ 
         //request failed - handle as error and ask to re-login or whatever 
    }
?>

explanation-

  • You send your AJAX, validate the session token and post token
  • If successful, generate new token
  • Update the token in $_SESSION['token'] and also send the new token back
  • Use the success function retrieve the token and update in your JavaScript

It this a good idea? Or does this create a new vulnerability like an XSS spoof ?

1

Before I answer this, I should ask: is there a reason you think changing the anti-CSRF token on every request is necessary, or even beneficial? I don't want to say that there categorically cannot be a good reason, but I can't think of one. The rest of the answer is based on that.

Is this a good idea?

Not really. There's no need, and no good reason, to change the CSRF token on every request. In fact, this is likely to break stuff. For example, if your user has two or more tabs open to your site, they'll have the same session and thus the same server-side anti-CSRF token, but each will run their own javascript with their own local variables. You could get around this by using something cross-page, like client-side session or local storage, but why bother? The whole exercise is almost certainly pointless overcomplication for no gain.

Additionally, if you're performing your state-changing requests via AJAX rather than via HTML forms or similar, there's an easier way to prevent CSRF. Just add any non-standard header name to the request (for example, X-CSRF: very bad!) and on the server, make sure that non-standard header is present before processing the request. Cross-origin requests can't add non-standard headers without a CORS preflight; if you don't implement CORS support, or you do implement CORS but don't ever allow another origin to add that header, you're done. This has all sorts of advantages: no need to securely generate unpredictable tokens, no need to store extra state on the server, no need to synchronize server-side state across a cluster, no risk of side-channel timing attacks or similar, no worrying that the client might be using an outdated anti-CSRF token...

Does this create a new vulnerability like an XSS spoof?

I have no real idea what an "XSS spoof" is supposed to be. Your scheme, as described, does not introduce an XSS vulnerability unless the attacker can somehow control the value of the anti-CSRF token, and your client=side script does something more exciting with it than just stick it in a variable, and add it to AJAX request bodies.

There are some weaknesses of the proposed scheme, such as the risk of a timing attack due to the early-exit string comparison (on the server). Realistically, that's probably not a meaningful risk (in fact, the rapidly changing value of the token would in fact make this already-low-risk threat even less of an issue), but why take the chance? Besides, the much likelier issue would be in how the anti-CSRF token is generated and stored on the server.

0

For most up-to-date recommendations on CSRF tokens, take a look at the OWASP document "Cross-Site Request Forgery Prevention Cheat Sheet".

OWASP also has a good article on XSS, which is a separate issue but can potentially defeat CSRF protection. Take a look at their "Cross Site Scripting Prevention Cheat Sheet", also linked in the document on CSRF.

Other than that your approach seems good - I'm using a similar code in the web apps I develop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.