Preventing Cross-Site Request Forgery (CSRF) Attacks in WebAPI
CSRF is an attack which forces an end user to execute unwanted actions on a web application in which he/she is currently authenticated. With a little help of social engineering (like sending a link via email/chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing. A successful CSRF exploit can compromise end user data and operation in case of normal user. If the targeted end user is the administrator account, this can compromise the entire web application.
Here is an example of CSRF attack.
- User requesting a page - with Forms authentication enabled and Anonymous authentication disabled. Server is checking for Forms authentication cookie. And responding with a 302 status code, as the request doesn’t contains the cookie.
- Browser is redirecting to the login page, and gets the login page.
- User authenticating with the credentials, sending a POST request.
- Server authenticates the user and Forms authentication cookie is set.
- User sending a Ajax POST request to WebAPI. And resource created, server responded with status 201. Here is the controller action.
Here is the request
The controller action contains an Authorize attribute, which means only Authorized request will be accepted.
- From another web page, user sending another POST request, without logged in.
Here is the request. Please not the URL, in previous request it was /api/Employee, but in this request, it is absolute url.
And here is the server response.
It is also created the resource, and server responded with status 201. As the request comes to an authenticated web page, the browser will automatically send the cookie with the request.
Anti-Forgery Tokens - To prevent CSRF attacks ASP.NET MVC uses Anti-Forgery Tokens or request verification tokens. If you enable this, server will includes two tokens with the response. One token is sent as a cookie. The other is placed in a hidden form field. When data is posted, the Cookie and the Hidden Field are both sent back and if they are missing or they donâ€™t match, the POST is rejected. In MVC this happens automatically when you request for an AntiForgeryToken. In Web API, we have to do this check manually.
Here is the Anti-Forgery Token implementation for Ajax requests, this function will generate the cookie token and form token, and returns as string.
And you can use this in Ajax requests like this.
And in server side, I created an Action Filter, which will validate the request.
AntiForgery.Validate method to validate the tokens. The Validate method throws an exception if the tokens are not valid.
And here is the server response with and without AntiForgery implementation.
POST request with RequestVerification header
And POST request without RequestVerification header - Server response is 500, Internal server error, ActionFilter attribute is throwing exception.
You can also prevent CSRF attacks by verifying the request referrer too, to a certain extend.