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