While trying to harden a PHP web app against null byte poisoning, I noticed that I was having a heck of a time actually sending a null byte in my request.
Using cURL, I was finally able to find a way to send null bytes in my requests, but I noticed something very odd: No request parameters whose values include a null byte ever reach my PHP application.
As a proof of concept, I created a file named test.php
on my server:
<?php echo json_encode($_GET), PHP_EOL;
Here's the result of some requests to this script:
> curl 'http://localhost/test.php?foo=bar&baz=nu%00ll' {"foo":"bar"} > curl 'http://localhost/test.php?foo=bar&b%00az=null' {"foo":"bar","b":"null"}
It appears that keys are getting truncated at the null byte, and if the value contains a null byte, the parameter is removed from the request array entirely.
Using print_r()
yields similar results:
<?php print_r($_GET);
> curl 'http://localhost/test.php?foo=bar&baz=nu%00ll' Array ( [foo] => bar ) > curl 'http://localhost/test.php?foo=bar&b%00az=null' Array ( [foo] => bar [b] => null )
Same thing happens if I modify my script and cURL requests to use $_POST
.
Not that I'm complaining, but I do need to know why this is happening so that I can ensure that each webserver is configured correctly.
What is causing this behavior?
> php -v PHP 5.3.3 (cli) (built: Jul 3 2012 16:40:30) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies with Suhosin v0.9.29, Copyright (c) 2007, by SektionEins GmbH