Reducing your bandwidth for benchmarking purposes

In the last few days I’ve been busy doing allot of web application performance benchmarks. For some of these benchmarks, it was important to simulate a real end-user’s average effective bandwidth (real-world download / upload speed from the end user’s perspective).

Since we used a fast, clean LAN for our benchmarks (you can’t get consistent numbers otherwise), we had to find a way to somehow limit the bandwidth of our LAN so that it would resemble “real Internet” throughputs. Since it took some research and reading to find the best way to do that, I’ve decided to write a quick HOWTO to describe what we’ve done.

[more...]

Creating magic_quotes_gpc portable apps with Zend Framework

I've been working on a small ZF based application for work in the last few days, and it was running quite well on my local machine. But when time came to deploy - alas, we discovered that slashes are magically added before single quotes to all data. The dreaded magic_quotes_gpc "feature" was apparently on on that server - so instead of turning it off, I decided to make my application more portable by making it work regardless of magic_quotes_gpc's status.

Since my application was based on Zend Framework (as most of the stuff I write for work these days), I decided to do it in a reusable "Zend Way". So I created a Zend Controller Plugin to reverse the effects of magic_quotes_gpc:

PHP:
  1. <?php
  2.  
  3. /**
  4. * A Zend Controller Plugin dedicated to undoing the damage of magic_quotes_gpc
  5. * in systems where it is on.
  6. *
  7. * @author  Shahar Evron
  8. * @version $Id$
  9. */
  10.  
  11. require_once 'Zend/Controller/Plugin/Abstract.php';
  12.  
  13. class MyApp_StripMagicQuotesPlugin extends Zend_Controller_Plugin_Abstract
  14. {
  15.     /**
  16.      * Called before the action loop is started. Will internally strip all
  17.      * slashes off $request parameters
  18.      *
  19.      * @param Zend_Controller_Request_Abstract $request
  20.      */
  21.     public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
  22.     {
  23.         $params = $request->getParams();
  24.         array_walk_recursive($params, array($this, 'stripSlashes'));
  25.         $request->setParams($params);
  26.     }
  27.  
  28.     /**
  29.      * Strip the slashes off an item in the Params array
  30.      *
  31.      * @param string $value
  32.      * @param string $key
  33.      */
  34.     protected function stripSlashes(&$value, $key)
  35.     {
  36.         $value = stripslashes($value);
  37.     }
  38. }

You place this plugin under your application library directory. Then, in your index.php bootstrap file, check if magic_quotes_gpc is enabled, at load and register the plugin:

PHP:
  1. /**
  2. * Setup controller
  3. */
  4. $controller = Zend_Controller_Front::getInstance()
  5.     ->setControllerDirectory('../application/controllers');
  6.  
  7. /**
  8. * Load the magic_quotes_gpc undoing plugin if needed
  9. */
  10.     require_once 'MyApp/StripMagicQuotesPlugin.php';
  11.     $controller->registerPlugin(new MyApp_StripMagicQuotesPlugin());
  12. }
  13.  
  14. // run!
  15. $controller->dispatch();

Now, this is only loaded and executed in systems where magic_quotes_gpc is enabled. It probably has quite allot of overhead - so a best solution in production environments would be to turn magic_quotes_gpc off (consider the fact that PHP works hard to escape the input, and then works hard to undo it... what a waste!), but if you want to produce a portable application that can be installed anywhere (including on shared hosting environments), this is a good solution.

BTW I'm not really sure if this handles cookies - so there might be a more "correct" way to do this. If you have any suggestions, I'd be happy to hear them!

XSRF and session.referer_check

I was giving Zend's on-line "security for developers" course to some customers last week, and as usual Cross-Site Request Forgeries (XSRF) was one of the hardest topics for me to explain and for other people to understand. This made me spend some time thinking about XSRF again, coming up with code demos and such to make it more clear.

Incidentally, I came across a php.ini directive today, which I've never noticed before: "session.referer_check". According to the docs, you can set the value of this directive to a substring of the domain name you're using. PHP will then check every HTTP_REFERER, if set, to contain this substring. If the referring address exists but does not contain the value of session.referer_check, the embedded session ID will be marked as invalid.

I didn't test this - but if it works as it's supposed to, it might be a good quick-and-dirty defense against XSRF - because it will not allow you to continue your session if the requested URL was referred from another domain (through an IMG tag, link, form submission and such).

There are several reasons why I think it's quick-and-dirty, to name a few:

  • It will not help you if the XSRF was launched from your own domain - for example through exploiting an XSS vulnerability in your site
  • Not all requests referred to your site from other domains are malicious - for example, I might want to have a "Digg This" or "Add to Facebook Profile" button on my site - if you click those, you'll be referred to Digg / Facebook from my site. In most cases you'd want your sessions to stay active on those sites, handling the request properly, and not treating it as XSRF
  • As the experience of magic_quotes_gpc taught us, trying to solve code-level problems in the engine level will probably end up in a half-baked solution, providing mostly the false sense of security

On the other hand, it's nice to know PHP has that option (and that it's turned off by default) - if you've just found out your site is full of XSRF vulnerabilities, and you know it will take you a while to fix them, you might just want to turn in on as a temporary solution.

Be careful though - it might break some of your functionalities. Also, there's a popular Hebrew saying that "nothing is more permanent than temporary solutions" (my own translation here..) - so FIX YOUR CODE if you can.