Hashing Redirect Params in Craft

Protect your form redirect in Craft 2 and Craft 3 by hashing your redirect form data.


Back in ver­sion 2.6.2945 of Craft 2, Pix­el & Ton­ic intro­duced the abil­i­ty to require hash­ing of the redi­rect para­me­ters that are set in forms (like when you sign in or sign up).

They intro­duced this enhance­ment to make Craft more secure. There is a poten­tial Denial of Ser­vice (DoS) secu­ri­ty issue with in-the-clear form data. In the exam­ple of a redi­rect para­me­ter, this could allow some­one to redi­rect the user to some­thing oth­er than what is spec­i­fied in the hid­den form element.

We need to pro­tect our form data. Let’s learn how to do that, start­ing with Craft 2.

Pro­tect­ing Return Para­me­ters in Craft 2

The solu­tion to pro­tect­ing the redi­rect para­me­ter in Craft 2 is two-fold:

  • In Craft 2.5.2750, the devel­op­ers intro­duced the hash fil­ter, which takes the input and hash­es it using a HMAC (Hashed Mes­sage Authen­ti­ca­tion Code). On the back-end, while pro­cess­ing the request, the devel­op­er can val­i­date the hash using a validateData method.
  • In Craft 2.6.2945. the devel­op­ers intro­duced a con­fig­u­ra­tion set­ting that forced each request with a redirect para­me­ter to be hashed. This new con­fig set­ting is called validateUnsafeRequestParams and it takes a boolean val­ue. When set to true then the unsafe para­me­ters (which is just the redirect para­me­ter and per­haps some third par­ty plu­g­in parameters). 

Togeth­er, these will pro­tect your form redi­rect para­me­ter from any secu­ri­ty issues.

Let’s use the login form as an example:

<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/login">
    <input type="hidden" name="redirect" value="{{ '/profile' | hash}}">
    <h3><label for="loginName">Username or email</label></h3>
    <input id="loginName" type="text" name="loginName"
        value="{{ craft.session.rememberedUsername }}">

    <h3><label for="password">Password</label></h3>
    <input id="password" type="password" name="password">

        <input type="checkbox" name="rememberMe" value="1">
        Remember me

    <input type="submit" value="Login">

We have our stan­dard hid­den field with the redirect name and the val­ue is pop­u­lat­ed with a Twig out­put tag, a string for our redi­rect loca­tion. We use the hash fil­ter on the string to hash it. 

If we load this in the brows­er we should see that the string is hashed:

<input type="hidden" name="redirect" value="58c6ace5c2af26ac04772d20aea67659590b9441/profile">

Now, we need to require all redi­rect para­me­ters to be hashed using the con­fig option.

In our craft/config/general.php file we add the fol­low­ing item:

'validateUnsafeRequestParams' => true,

And now when we go to sub­mit our form, it’ll val­i­date the hash we pass as the redi­rect para­me­ter and process the request.

If for some rea­son we have this enabled but we don’t hash our redi­rect para­me­ter, Craft will return a error.

Pro­tect­ing Redi­rect Para­me­ters in Craft 3

Pro­tect the redi­rect para­me­ter in Craft 3 is a sim­pler process because Craft 3 requires hash­ing of all redi­rect para­me­ters. The validateUnsafeRequestParams con­fig set­ting we have in Craft 2 is gone. You can’t opt in (and you can’t opt out).

The only step we need to do in Craft 3 is to set our redirect hid­den field in the form we’re using and pass it through the hash filter.

<input type="hidden" name="redirect" value="{{ '/profile' |  hash}}">

And what hap­pens in Craft 3 if don’t hash the redi­rect parameter?

In the case of the login form, the login rou­tine will pro­ceed (suc­cess­ful if the user­name and pass­word are cor­rect) but the redi­rect will fail. The val­ue of the redi­rect para­me­ter will not be honored.

The Take­away

Whether we are using Craft 2 or 3, we should be hash­ing the redi­rect para­me­ters. It’s a good secu­ri­ty prac­tice in Craft 2 and by doing so you’ll be mak­ing your sites even more ready for a Craft 3 upgrade.