Fixing a CSRF Vulnerability
Want to learn how to fix a cross-site request forgery? Check out this post where we explore how to fix a CSRF vulnerability on your website in this tutorial.
Join the DZone community and get the full member experience.
Join For FreeOne way that your website might be vulnerable to an attack is via a Cross-Site Request Forgery (CSRF or XSRF).
If you’ve ever been logged into a website — say Twitter, for example — and you open a separate tab and type in a Twitter account, for example, this Twitter feed: https://www.twitter.com/paul_michaels. You’ll notice that when the site opens, it opens already logged in for you, which can be very helpful. Imagine having to log in every single time that you wanted to view a Tweet or a profile.
Now, imagine that, instead of typing that into the browser, you click on the link above – try it! Wha? It didn’t take you to Twitter, but it took you to the home page of this blog? That’s exactly how a CSRF attack would work in practice! If you were already logged into that site, the link could have executed a CSRF attack.
Cross-Site Request Forgery works on the premise that the victim of the attack is actually logged into a given website with valid credentials, and the attacker knows the exact format of a valid request. So, for example, I can take you to my Twitter profile, because the format of that is well known. Nobody, least of all Twitter, wants you to have to mess around with logging in again.
But, what about if you want to actually post a Tweet? Here’s the URL that gets called:
It’s a little difficult to demonstrate, because Twitter operates over HTTPS, so the traffic is encrypted, but the gist is that, even if I managed to create a site that copied this message exactly, the Tweet would not get created. Let’s have a look at replicating such an attack.
Replicating a CSFR Attack
Your first step is to create a standard website — the default MVC template will do. It might also help to demonstrate if you don’t use HTTPS.
Launch the website with F12 tools and make a given request. For example, click the “Contact” link on the default site. Make a note of the URL and the form data for the request:
Leave the app running and logged in.
Now Attack
Create a new web app with the following code:
<h1>Run CSRF Attack on MyApp</h1>
<form action="https://localhost:12312/SendLoadsOfMoney" method="post">
<input type="hidden" name="values"
value="{'BankName': 'Big Bank', 'Amount': '1234.12' }">
<input type="submit" value="Attack Now!">
</form>
Obviously, don’t use that code – otherwise, you’ll cause over a thousand pounds to be transferred from my account to yours! Replace the URL with whatever the URL from the above site was and the values with whatever values were behind your grey box above. You can use POST or GET or whatever else you like. What you’ll notice is that by clicking your button, it interacts with the site you created in the same way it would if you were on your site. The “SendLoadsOfMoney” is obviously just an example that takes it to the extremes, but the principle is correct.
Fix
To fix this in MVC is very easy.
Add the following:
[ValidateAntiForgeryToken]
If you add this to the controller method, you should start seeing this error:
The required anti-forgery cookie “__RequestVerificationToken” is not present.
Your calling code might look like this:
<form action="Test" method="post">
<input type="submit" value="Test3">
</form>
The next step is to add a call into the client; for example:
<form action="Test" method="post">
@Html.AntiForgeryToken()
<input type="submit" value="Test3">
</form>
So far, so good. This works for the Asp.Net Mvc Core and framework, but not for ApiControllers! The decorator [ValidateAntiForgeryToken]
has no effect on an ApiController out of the box (and worse, you’ll never know it without launching a specific attack on your ApiController). So, what can you do?
One option is to implement a custom token as described here. I would treat this as a specific case for ApiControllers only, though.
References
https://github.com/zaproxy/zaproxy/wiki/Downloads
https://www.owasp.org/index.php/OWASP_Testing_Project
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.1
Published at DZone with permission of Paul Michaels, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments