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
Disable Suhosin first. It takes care of that already.
As long as you have enabled it, you can not inject NUL bytes that easily.