Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

CSRF error on form submission: "There seems to have been a technical problem. Please click the back button refresh your browser, and try again."


Reply


7 Posts   1279 Views

Avatar
vwd

Community Member, 160 Posts

5 February 2014 at 1:04pm

Edited: 07/02/2014 5:58pm

Hi,

A large form on a SS 3.1 site has been working without hiccup. Lately though, I regularly get the following error when submitting forms from Safari:


"There seems to have been a technical problem. Please click the back button refresh your browser, and try again."

Doing the following did not make a difference:

  • Clearing the browser cache
  • Flushing SilverStripe cache (or manually deleting cache folder contents)
  • Restarting the browser (Restarting the browser makes the form work again but as soon as another 400 error occurs the problem resurfaces)
  • Restarting the web server

It has occurred more frequently on my dev machine (MAMP Pro) and now has occurred on the production server (Linux) (haven't been able to easily reproduce on Linux easily). And strangely it only seems to be occurring on Safari (able to replicate error on desktop [Mavericks/Lion] / iPad [iOS7] ). It has only started to occur recently. Some recent changes made include adding more fields to the form, changing the system temp directory and php session folder. I can confirm that the sessions folder is where I want it to be because of the newly written session files. If I open the form up, sleep the computer / device,

Just as quickly as it occurs, it stops - and I have no idea why! Everything starts out fine, but when a PHP session timeout occurs and after I get the genuine SecurityToken error, it seems to get itself into a cycle where every subsequent attempt to submit the form (from Safari) results in the same error. I've put in debug statements that show that upon submission, when the form is submitted, the Form object is created (again) and thus a new SecurityToken is generated causing the mismatch.

The following CSRF protection code in Form.php (~ line 280) is where the error is thrown:

      // Protection against CSRF attacks
      $token = $this->getSecurityToken();
      if(!$token->checkRequest($request)) {
         $this->httpError(400, _t("Form.CSRF_FAILED_MESSAGE",
            "There seems to have been a technical problem. Please click the back button,"
            . " refresh your browser, and try again."));
      }

Debugging and stepping through the code confirms that there is a mismatch in the tokens. But why? Any idea why this could be occurring?

Many thanks,
VWD.

Avatar
vwd

Community Member, 160 Posts

6 February 2014 at 9:26pm

A few updates and clarifications:

  • - The issue isn't intermittent - it's quite repeatable now.
  • - It seems to start when the PHP session expires. Then after that, gets itself in a strange cycle of SecurityToken mismatches (for some reason - I can't see any sense in it - only happens when submitting the form from Safari.)
  • - When I debug & step through the code, I see that a new SecurityToken is created when the form page is created. And when the form is submitted and the submission handler is called, the form object is recreated, and another SecurityToken is generated which then obviously mismatches the one that was embedded in the form.

Avatar
vwd

Community Member, 160 Posts

7 February 2014 at 2:13pm

Edited: 07/02/2014 2:13pm

Further findings:

  • - It only happens with Safari (both desktop & iOS). Doesn't happen with Opera, Firefox & Chrome.
  • - The site is full https (set up both in .htaccess and with forceSSL()) but the problem goes away when it's straight http (i.e. non SSL)
  • - When I refresh / reload the form page using Safari a new SecurityID is generated each time, whereas when I refresh / reload from the other browsers, the same SecurityID is present for the length of the PHP session.

The strange behaviour of the SecurityID refreshing each time upon reloading the form page on Safari seems suspicious. I'm not sure how the browser reload can have an effect on the PHP Session / SecurityID - seems like it should make a difference but it does. I have debug statements in Form.php showing that each time the following line in Form::__construct() is called, a new SecurityID is generated:

$this->securityToken = ($securityEnabled) ? new SecurityToken() : new NullSecurityToken();

Avatar
vwd

Community Member, 160 Posts

7 February 2014 at 6:06pm

Interestingly, examining the session files reveals that after the CSRF mismatch error, that the SessionID stops getting written into the session file:

Session file with a clean session and Safari restarted:

SecurityID|s:40:"60bdeaf698fc23edac12fe78ec42b25e2a3b20a4";HTTP_USER_AGENT|s:119:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/6.1.1 Safari/537.73.11";

But after the 400 Error / CSRF SecurityID Mismatch:

SecurityID|N;HTTP_USER_AGENT|s:88:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.73.11 (KHTML, like Gecko)";

Cookies are enabled and 'Do not track' is disabled.

Avatar
Devlin

Community Member, 225 Posts

7 February 2014 at 9:54pm

SecurityToken->getValue() generates a new token if the session is empty...

public function getValue() {
   $value = Session::get($this->getName());

   // only regenerate if the token isn't already set in the session
   if(!$value) {
      $value = $this->generate();
      $this->setValue($value);
   }

   return $value;
}

Did you tried to run the SessionTest in Safari?

Avatar
vwd

Community Member, 160 Posts

8 February 2014 at 1:51am

Hi Devlin,

Thanks for that suggestion. Just ran it and all tests passed.

I guess that's what's perplexing…

  • 1) Why only from Safari?
  • 2) Why does it get itself in this strange state of generating a new SecurityID on each refresh / reload?
  • 3) Why isn't it or why isn't it able to write the SecurityID to the session file?

Thanks for that good suggestion.
VWD

Avatar
vwd

Community Member, 160 Posts

17 February 2014 at 4:58pm

Edited: 18/02/2014 3:22pm

With the recent [url=https://github.com/silverstripe/silverstripe-framework/pull/2835]PR-2835[/url] this no longer is an issue.

For some reason, it still occasionally gets into this strange state when using Safari. Now I get a more pleasant error message with the form preloaded with the submitted values but it's still not possible to submit the form because of the SecurityID being missing in the session file.

The only way to get it out of this state is to restart the browser. And it still only happens in Safari.