1

This question already has an answer here:

Say I have a user with an associated session token. This user wants to delete his account, and so he goes to its associated link. I, trying to protect my users and myself from CSRF attacks, have it so when the user clicks a link and makes the DELETE request, I send that user's session token in the request body. Any other sites couldn't possibly know the session cookie, and therefore couldn't send it in the request body. On the receiving end, the server checks to make sure that the session cookie and the session token in the body are the same.

Why doesn't this work? The explanations I've heard have been way more intricate and I just can't see why the aforementioned process wouldn't work. I know I must be overlooking something!

marked as duplicate by Sjoerd, Tobi Nary, AndrolGenhald, Royce Williams, ThoriumBR Sep 10 '18 at 21:03

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Welcome to sec.SE. It would be good if you can add more information about the resources you referred. This would give more context to the question. – Shurmajee Sep 6 '18 at 3:51
2

Basics of CSRF protection

Most CSRF protection mechanisms work on a basic principle that the HTML form being submitted and the server should have shared secret between them. When the form is submitted to the server, this shared secret is used to identify if the request originated from a legitimate page. There is no way for malicious sites to access this shared secret if it is present in the request body. (Obviously cookies cant be used to store this secret as browsers transmit them to the target domain irrespective of the origin of the page.)

Double submitted cookie

The prevention method that you have described is called double submitted cookie. In this the shared secret is sent using both the cookie and form parameter. The server only has to compare the two values to filter out forged requests.

Why does it not work?

It does work. The session token is indeed a shared secret between the browser and the server. However the session token's primary job is to track the user's authenticated session. A session token present in the cookie is protected by cookie flags such as HTTPonly. This prevents JavaScript from accessing the session cookie, which in turn prevents session ID theft in case of an XSS vulnerability.

Having the session token in the request body of every HTML form increases the attack surface as the session token can be extracted by exploiting a script injection vulnerability. Hence it is good practice to have a dedicated CSRF token do the job.

0

Here is a CSRF basic example.

<form name="Delete-account-confirmation" action="http://example.com/profile.php?action=deleteprofile" method="post" enctype="multipart/form-data">
<input type="hidden" name="Username" value="DonaldT">
<input type="hidden" name="Checkbox-confirmation" value="on">
</form>

<script>document.Delete-account-confirmation.submit()</script>

Note: Using a third party Website is not necessarily mandatory for CSRF Attacks, you can do some damage just with <img src="CSRF" />

why doesn't this work?

Let's state that example.com is a forum. This forum allows registered users to send pm to other registered users. So, as an attacker, I can try to obfuscate the CSRF and send it via PM to the user I want to harm, and make him run the malicious code independently of his will.

In the code above the Victim is DonaldT.

So I send this Malicious PM to DonaldT, he opens the Message and runs the code while logged in the example.com. The session cookie and the session token will be different? Yes, in this case, your prevention system should work.

But, depending on the implementation of your Anti-CSRF token, if poor implementation there is, it might be evaded by something like this:

Token evasion CSRF Attack

   <body onload="get()">

    <form name="Delete-account-confirmation" action="http://example.com/profile.php?action=deleteprofile" method="post" enctype="multipart/form-data">
      <input type="hidden" name="Username" value="DonaldT">
      <input type="hidden" name="Checkbox-confirmation" value="on">
      <input type="hidden" id="forged-token" name="token" value=""/>
      <input type="submit" value="go"/>
    </form>

   <script>
    var x = new XMLHttpRequest();
    function get() {
      x.open("GET","?action=deleteprofile",true);
      x.send(null); 
    }
    x.onreadystatechange = function() {
      if (x.readyState == XMLHttpRequest.DONE) {
        var token = x.responseText.match(/name="token" value="(.+)"/)[1];
        document.getElementById("forged-token").value = token;
        document.getElementById("Delete-account-confirmation").submit();
      }
    }
   </script>

External source I recommend you to read.

owasp

Remember that all cookies, even the secret ones, will be submitted with every request. All authentication tokens will be submitted regardless of whether or not the end-user was tricked into submitting the request. Furthermore, session identifiers are simply used by the application container to associate the request with a specific session object. The session identifier does not verify that the end-user intended to submit the request.

  • This answer is incorrect in a number of ways. The example in "Token evasion CSRF Attack" won't work because you can't perform authenticated cross-site requests. The second example is nonsensical: the XSS runs on the same site so it isn't cross-site request forgery. – Sjoerd Sep 6 '18 at 6:53
  • I'm not sure what you mean by authenticated cross-site request. Can you give further details ? – Baptiste Sep 6 '18 at 7:11
  • Where cookies are send along with the request. This can be enabled with XHR.withCredentials. – Sjoerd Sep 6 '18 at 7:30

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