Cross site request forgery (CSRF/XSRF)

A browser typically sends requests to web applications in one of two ways. It either sends data via URL parameters where a HTTP GET request is used or sends data via forms where HTTP POST is used. The application typically performs some action as a result, for example, inserting of a new user into a table, deleting a file attachment, etc. A problem occurs if the web application does not check if the requests are generated by the application itself (a user clicks a link or submits a filled in form). An attacker can create a link for a certain action and send it to the user. The user then clicks the link and the action is performed without the user even noticing. This is called Cross Site Request Forgery.

So a user needs to click an attacker’s link or fill in an attacker’s form. Another condition is that the user must be signed in to a vulnerable website. These days, almost every application provides “keep me signed in” functionality, so this condition is easily met.

CSRF tokens for the administration

The Xperience administration application provides a security token mechanism for additional protection against forged POST requests:

  1. Whenever a user initiates a new session, a session cookie (HTTP only) is saved to the browser. The cookie stores a randomly generated token.
  2. When the user loads a page containing an HTML form, Xperience automatically adds a hidden field to the form data, which contains an encrypted value matching the user’s token.
  3. After the form data is submitted via POST, the system validates the hidden field’s value against the user’s token.

If an attacker attempts to forge a form, they cannot generate a valid value for the hidden token field. If the tokens do not match when the form is submitted, the system raises an error and the attack is blocked.

Using custom security tokens against CSRF

If you have your own security token implementation, you can disable the default tokens by adding the following key to the appSettings section of your web.config file:




<add key="CMSEnableCsrfProtection" value="false" />


CSRF protection on MVC sites

The default CSRF security token mechanism only protects the Xperience administration interface. For MVC sites with pages handled by controllers and views, you need to:

  1. Add the ValidateAntiForgeryToken attribute to action methods that handle POST requests.
  2. Generate security tokens by calling the @Html.AntiForgeryToken() method in your MVC views that post to the action methods.

Examples of CSRF

Let’s assume that a simple Web Forms page without any content has the following code in the code behind:




if (!string.IsNullOrEmpty(Request.Form["UserID"]))
{
    DoSomeAction(Request.Form["UserID"]) ;
} 


It does not matter what the DoSomeAction() method does. The important thing is that in this case, the action is performed with the value specified in the UserID field. If security tokens are not used, 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 and the following code behind:




using CMS.Membership;
using CMS.Helpers;

...

if (MembershipContext.AuthenticatedUser.CheckPrivilegeLevel(UserPrivilegeLevelEnum.GlobalAdmin))
{
    int userID = QueryHelper.GetInteger("UserID", 0);
    if (userID != 0)
    {
        Response.Write("I just deleted a user with id: " + userID);
    }
}
else
{
    Response.Write("You don't have sufficient permissions to delete the user");
} 


This code is similar to the previous example. The only difference is that now, the UserID is taken from a query string (via the GET method).

What can CSRF attacks do?

Vulnerability to CSRF attacks depends on individual applications and on the security of the web server. For example, if the application is poorly implemented, then attackers can do anything that the victims of the attack could normally do.

Summary

  • For MVC pages and components, add the ValidateAntiForgeryToken attribute to your POST actions, and generate security tokens by calling the @Html.AntiForgeryToken() method in your views that post to the action methods.
  • Leave the default CSRF security tokens enabled for the Xperience administration, unless you have a custom mechanism that protects against CSRF.
  • If developing custom functionality for the Xperience administration:
    • Do not use GET requests to perform actions, always use POST.
    • If you create a custom administration page, always make it inherit from one of the Xperience base pages.
    • If you create a new Xperience page class, check that it directly or indirectly inherits from AbstractCMSPage.