How to prevent CSRF attacks
This post is part of the series 'Vulnerabilities'. Be sure to check out the rest of the blog posts of the series!
- Impersonation and security
- SQL injections
- How to prevent CSRF attacks (this post)
- ASP MVC and XSRF
- Cross-site scripting (XSS)
- ASP MVC: Mass Assignment
- Regex - Deny of Service (ReDoS)
- Deserialization can be dangerous
- Prevent Zip bombs in a .NET application
- Prevent Zip Slip in .NET
- How to protect against XML vulnerabilities in .NET
#What's XSRF?
CSRF, Cross-Site Request Forgery, vulnerabilities allow us to impersonate a user to make a query on a website. This happens when a website allows an authenticated user to do a sensitive action but the website does not verify that the user triggered this action. Instead, they only check that the query comes from the browser of an authorized user.
The attacker aims to use our authentication cookie already stored by the browser for the targeted website. To do this, it is enough for them to make the browser request the target site. There are several possibilities for this:
- Convincing the user to click on a link,
- Inserting HTML/JavaScript code into a website that the user visits. One can for example find an image whose link is a link executing an action on the targeted site. Example
<img src="https://example.com/delete/1">
. When the browser receives animg
tag, it retrieves the image specified in the source using aGET
request and therefore requests the desired site.
One can say that to avoid this kind of attack it is enough to replace all the actions realizable by the method GET
in POST
. Well, that's not enough. Indeed, the attacker can use JavaScript:
<body onload="document.getElementById('form').submit()">
<form id="form" action="https://example.com/delete/1" method="post">
<input name="delete" value="Delete" />
</form>
</body>
The form will be submitted automatically using the POST
method. It's better than using GET
, but it doesn't solve the problem.
#How to guard against it?
- Check the
HTTP referrer
. Basically, if it's not our domain there's a problem. However this method can be annoying to the user. Indeed some enterprise proxy removes the referrer from all HTTP requests. So we will find ourselves blocking legitimate requests. Moreover, it is possible to forge its request and thus define the referrer. This method is therefore fickle. - Add an invisible field in the form. The concept is to generate a string of random characters and add it to the form. When the client sends the form, the server verifies that the value of the hidden field is the same as what was generated. Example:
<input id="a" name="a" type="hidden" value="hjkguyez721g45654gfd12cwx400huiyu" />
a bit like the captcha. - Add a cookie. When the page is created, the server sends a cookie. When submitting the client returns it and the server checks that the content of the cookie is identical to what it generated.
Here you have all the cards in hand to protect your websites from this type of attack.
Do you have a question or a suggestion about this post? Contact me!