Example of CSRF
Let's have a simple page without any content and this code in code behind:
It does not matter what the DoSomeAction() method does. The important thing is that, in this case (if a machine key is not used to encode ViewState), the action is performed with the UserID specified in the UserID field. Anyone who is authorized and sends a form with this field can perform the action. And there is no way to check if the actual user really wants to do this action.
Let's have another page without content with this code behind:
This code is similar to the previous example. The only difference is that now, UserID is taken from a query string (by the GET method).
The third example shows a one-click attack. Let's have a simple page with a textbox and a button. This code handles the Onclick action of the button:
Users typically insert a value into the txtUserID textbox and click the button. But the attacker can forge a link to the user:
The attacker can change the <anything> macro to anything else. ViewState is taken from the page that can be generated after postback on that page and the validation is successful.
What can CSRF attack do
It depends on the application and on the security of the web server. For example, if the application is poorly implemented and encoding of ViewState based on machine key is turned off on the server, then the attacker can do anything that the victim of the attack could normally do.
Finding CSRF vulnerabilities in Kentico CMS
If you find any page/control/etc., that does an action on GET request, there is a possibility of a CSRF vulnerability. For example, try to find the following and similar strings in your source code:
If you find any of these strings in the <%@ page directive, it means that a developer turned off ViewState validation (first case) or machine keys for ViewState encoding (second and third case).
The ViewState validation helps a lot to avoid POST CSRF, so globally, it must always be turned on. Also, if you find any page that does not inherit from a Kentico class, it means that there is a possibility of CSRF.
Of course, if a page doesn't have these features and the page does not do any actions, it also does not have to be protected from CSRF.
Even if your application encodes ViewState properly, a special case of CSRF, a one click attack, is still possible. The problem is simple – ViewState is the same for all users. However, you can specify a key corresponding to the current user by the ViewStateUserKey page property. The recommended value is a user's session ID. All CMS pages must inherit from CMSAbstractPage (the base page for all CMS pages). CMSAbstractPage page sets ViewStateUserKey to a unique value for every user and thus avoids one click attacks.
Because ASP.NET partially secures web applications from POST CSRF and we add the least needed functionality to protect all POST requests by default, use POST requests only for actions. To enable machine key encoding or ViewState validation, you do not need to perform any actions.
By default (on the level of the global web.config file), ASP.NET is set to:
It means that machineKey is generated automatically, ViewState is validated and encoding of ViewState based on machineKeys is also enabled. If a control requests it, ViewState is encrypted by SHA1.
- Do not use GET requests to perform actions, always use POST.
- Never turn off validation of ViewState on a page (key EnableViewState) globally.
- Never turn off encoding of ViewState based on machineKey (EnableViewStateMac) on a page globally.
- Do not set the CMSUseViewStateUserKey key to false (it is an internal key which can cause insertion of the current user's key to ViewState encoding).
- If you insert a new page, always make it inherit from some of the CMS pages.
- If you create a new CMS page class, check that your page directly or indirectly inherits from CMSAbstractPage.