• Jul 25th 2011
  • No Comments

If you have a PHP Problem, do you cross check it in another browser usually? Well I’ll do in the future.. ;)

This morning I implemented a XSS/CSRF protection into a newsletter subscription form. Usually I do it with a token, that will be generated during the frontend page load, and will be written in the php session. The form content is submitted via AJAX to a PHP script, that handles the complete newsletter opt-in process. This script cross-checks the current token in the session with the submitted one.

So, inside the form page, there is something like this:

<?php
    $token = uniqid('token_newsletter_', true);
    $_SESSION['newsletter_token'] = $token;
?>
<input type="hidden" id="newsletter_token" value="<?=$token?>"/>

The security check is in the processing php script:

//$data is the via AJAX submited, json decoded data
if ($data['token'] !== $_SESSION['newsletter_token']) {
    die();
}

So far so good. But it was not working – so I started to debug. On the form page I checked the values of the generated token and the one in the session:

Session-Token: token_newsletter_4e2d5dd92732e4.19727735

Token: token_newsletter_4e2d5dd92732e4.19727735

Of course identical, so I checked the vars in the processing script:

string(46) “data: token_newsletter_4e2d5dd92732e4.19727735″
string(49) “session: token_newsletter_4e2d5eab38b752.61124898″

different! :-S – now how could that be?

First instant thought: “There must be a Problem with the AJAX call, so there is a different session generated or something”.. short after that I realized, that the server handles “normal” and ajax browser calls the same way. So they share the same PHP Session.

After a tipp from a friend I decided to write a quick debug script that writes debug output into a text file. This way its possible to see if the writer is called more than once.


$token = uniqid('token_newsletter_', true);
$_SESSION['newsletter_token'] = $token;
//debug write to text file
$file = 'debug.txt';
$fh = fopen($file, 'a');
$stringData = $token.PHP_EOL;
fwrite($fh, $stringData);
fclose($fh);

Now on every page reload, two new entries where written in the file, with different tokens of course! So my next idea was, there must be a problem with the CMS so the form code gets executed twice. Step, by step I broke it down, at the end I putted the code above right on top to the index.php and now what? Still two entries in the text file where generated..

I am using the Chrome Browser for Web Development usually, so I tried the same thing with Firefox -> badam only one entry!

“No way!” – so I disabled all Chrome addons but still the same problem.

After some googling I found this:

http://code.google.com/p/chromium/issues/detail?id=39402

Know what? Chrome is sending a request for a favicon on every page reload. As, is likely, you aren’t sending a favicon back, it requests one after every legitimate request.

This causes this weird problem.. in the background the favicon call seems to trigger a new execution of the php script, so a new token will be generated and stored into the session, the html output of this will not be transfered back to the client.. Very annoying but interesting problem – 3 hours waste so far.

But the story goes on, after a quick check in all other browsers I realized, Safari has the same problem.. argh!
What now? Both browsers seems to do a second request 1-2 seconds after the page load. The request dosen’t show up in the Chrome Networking Monitor. So I just created a favicon.ico file on: http://www.favicon.cc/. -> Problem gone in both Browsers! Aha!

I realized that probably this second favicon request will be translated from the .htaccess file (we have url rewriting in our CMS) and redirected to the home.php script. The Server parses the PHP, then he responds with the html output. Because this is no favicon, both browsers ignore the response. But at this time, a new token was allready generated on the server and saved into the session…

After some more tests I got to the real source of the problem in the .htaccess file. “ErrorDocument 404 /error ” – we use a custom page of our cms as 404 Error Document, so if the favicon is not found the page from the cms will be rendered and returned.. fewwww… what a way to start the week. But – I learned a lot! ;)

Now the best solution for this seems to just allways use a favicon. Not sure if there would be a fix to exclude the favicon from the error redirect – if you know something, please let me know!


This post is tagged , , , , ,

Leave a Reply

Categories