ASP.NET Core MVC Anti-Forgery System Opens Security Hole

ASP.NET Core MVC Anti-Forgery System Opens Security Hole

Recently I was adding Cache-Control headers to an ASP.NET Core MVC application to prevent other users from accessing restricted data after a user has logged out. However, it only seemed to fix the problem for some pages. On other pages, the the server was returning a Cache-Control header of no-cache instead of the required value of no-cache,no-store. A bit of research revealed that Microsoft’s anti-forgery system is clobbering the Cache-Control header on those pages.

Here is how it works: When you add a form to a page, the form tag helper automatically adds an anti-forgery token to the form to prevent Cross-Site Request Forgery attacks. For these tokens to work properly, they need to be “fresh.” If a user tries to submit a form with an old anti-forgery token he or she will get an error. So along with adding the token to the form, the form tag helper also sets the Cache-Control header to prevent the page from being cached. That is a great idea, but there is a problem with the current implementation. Right now it simply overwrites the header. If you have set the header to something more restrictive (like adding no-store), that value is lost and a potential security hole is opened in your application.

For the moment there is a simple workaround. Just add asp-antiforgery=”false” to your forms that are intended for authenticated users.

<form asp-controller="..." method="post" asp-antiforgery="false">
...
</form>

This skips the problem code and leaves your headers intact. Of course this means you lose the built-in CSRF protection, which might be an even bigger security problem. (If you choose to disable the antiforgery system, you should check request headers to mitigate against a CSRF attack.) You can subscribe to the issue on github to get notified of progress toward a fix for this problem.

Leave a Reply

Your email address will not be published. Required fields are marked *