27

We've recently had one of our webapps pentested. All went well, except for a CSRF vulnerability, and it is this finding I have a bone to pick with.

Some background: we're using ASP.NET MVC and, among other things, we do use the CSRF protection functionality built into it. The way it works is strictly in accordance with what OWASP recommends: by including so-called "synchronizer tokens", one in a HTTP cookie, and another in a hidden input named __RequestVerificationToken:

<form action="/Home/Test" method="post">
  <input name="__RequestVerificationToken" type="hidden" 
    value="6fGBtLZmVBZ59oUad1Fr33BuPxANKY9q3Srr5y[...]" />    
  <input type="submit" value="Submit" />
</form>

We also do regular Acunetix scans, and said scans never found any CSRF-unprotected forms.

Now, what the pentesters claim is that they were able to "breach" our CSRF protection with the following code:

<html>
  <body>
    <form action="https://our.site/support/discussions/new" method="POST">
      <input type="hidden" name="subject" value="Subject" />
      <input type="hidden" name="content" value="Content" />

      <input type="hidden" name="__RequestVerificationToken" 
        value="_e-upIZFx7i0YyzrVd[...]" />

      <input type="submit" value="Submit Request" />
    </form>
  </body>
</html>

The inclusion of the __RequestVerificationToken field is what bothers me the most: to me, it is akin to claiming that an attacker has transferred gazillion dollars from my bank account because I voluntarily gave him my iPhone to fiddle with, and he saw the one-time password that my bank sent in an SMS.

I imagine that the only way this attack could potentially work is if we were not using HTTPS, were vulnerable to XSS, were using non-HTTP-only cookies and were negligent with a Same Origin Policy. None of which is true, since none of these vulnerabilities were reported by either pentesters or Acunetix.

So the question is: am I wrong and this is a legit CSRF vulnerability or is it not?

Tobias Kienzler
  • 7,578
  • 10
  • 43
  • 66
Anton Gogolev
  • 371
  • 3
  • 5
  • 1
    This happened at my company recently as well. Their recommended solution was to 'include a unique token in each request'... – Alex Logan Nov 23 '16 at 16:06
  • @AlexLogan - was the same token value being used for every request in your case? – R15 Nov 23 '16 at 16:12
  • @R15 Yep. The `__RequestVerificationToken` was in the test form they made, which they could only have got by logging in. – Alex Logan Nov 23 '16 at 16:15
  • 3
    Looks like a false positive to me. Get in touch with the testing company. Judge them on the quality of their response. Odd mistakes and false positives happen, but if their response to your query is poor, I wouldn't use them again. – paj28 Nov 24 '16 at 13:39

3 Answers3

46

This does not seem to be a CSRF vulnerability.

If an attacker needs to know a CSRF Token, then it's not an attack. And your approach to CSRf does seem to be correct.

Issues which leak the CSRF Token can indeed result in a CSRF attack, but then the problem isn't incorrect CSRF protection, but those issues (XSS, encryption, CSRF Token in URL, and so on).

Still, I would ask the tester for clarification. Who knows, maybe the attack always works with that specific token, because it is hardcoded somewhere, or because the special characters are causing some sort of problem for your application. Or maybe it is possible to use a token from a different user, or maybe the token check just doesn't work at all and it accepts arbitrary tokens. The report should have contained more details, so I would check back with the tester about this.

tim
  • 29,018
  • 7
  • 95
  • 119
  • 1
    I find the characters highly suspect, and my first impression is that the OP is being too defensive without messing around with it. – Kenyon Nov 23 '16 at 17:57
  • 2
    @Kenyon What is it about the characters that bothers you? We use ever-so-standard CSRF protection, built by Microsoft. If there were bugs in ASP.NET anti-CSRF support, they would have already been known by now. – Anton Gogolev Nov 24 '16 at 05:17
12

It is indeed strange that the __RequestVerificationToken is included in the proof of concept, since normally an attacker would not know the value of this token.

However, the page can still be vulnerable to CSRF if the __RequestVerificationToken is not correctly bound to the session. If the value in the proof of concept, _e-upIZFx7i0YyzrVd[...], works for everyone, you are vulnerable to CSRF. If it only works for the user the pentester was logged in as, you are not vulnerable to CSRF.

Since you are using the default .NET CRSF protection I would assume this is implemented correctly and the pentester has made a mistake.

sigy
  • 103
  • 4
Sjoerd
  • 28,707
  • 12
  • 74
  • 102
  • 9
    When it comes to security, I find it hard to upvote any answer that says "I would assume you're secure". This is definitely something to check with the tester; there may be a flaw in the CSRF protection. – anaximander Nov 23 '16 at 09:31
  • 2
    Is "If it only works for the user the pentester was logged in as, you are not vulnerable to CSRF." correct? My understanding is that the token should be different for every single request, but that sentence implies that the token remains the same within a session (or even for all of one user their sessions). – Jory Geerts Nov 23 '16 at 15:02
  • 1
    @JoryGeerts While it's a pretty typical implementation for the token to be different for every request, I don't think that's strictly required to prevent CSRF. In order for CSRF to occur the attacker needs to send the verification token along with the cross-site request. I don't see how not changing the token every time makes that significantly easier, unless maybe you're using a token that's short enough for the attacker to brute-force... – Ajedi32 Nov 23 '16 at 21:18
  • To protect against CSRF the token does not have to change. However, to [protect against guessing the token using BREACH](http://security.stackexchange.com/questions/43669/with-breach-attack-is-session-based-csrf-token-still-secure/143455) the token needs to be different for each request. – Sjoerd Nov 24 '16 at 09:25
2

If __RequestVerificationToken is not validated on the server side and if it works for every single request and different user than yes your application is vulnerable to CSRF.

Michal Koczwara
  • 1,580
  • 3
  • 15
  • 27