Что вызывает фильтрацию значений null byte в запросе?

при попытке укрепить веб-приложение PHP против отравление нулевым байтом, я заметил, что у меня было чертовски много времени на самом деле отправка нулевого байта в моем запросе.

используя cURL, я, наконец, смог найти способ отправить нулевые байты в моих запросах, но я заметил что-то очень странное: никакие параметры запроса, значения которых включают нулевой байт, никогда не достигают моего PHP-приложения.

в качестве доказательства концепции я создал файл с именем test.php на мой сервер:

<?php echo json_encode($_GET), PHP_EOL;

вот результат некоторых запросов к этому скрипту:

> 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"}

похоже, что ключи усекаются в нулевом байте, и если значение содержит нулевой байт, параметр полностью удаляется из массива запросов.

используя print_r() дает похожие результаты:

<?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
)

то же самое происходит, если я изменяю свой скрипт и скручиваю запросы на использование $_POST.

не то, чтобы я жалуюсь, но я делаю нужно знать, почему это происходит, чтобы я мог убедиться, что каждый веб-сервер настроен правильно.

что вызывает такое поведение?

> 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

4 ответов


сначала отключите Suhosin. Он уже позаботился об этом.

пока вы включили его, вы не можете вводить нулевые байты так легко.


Я указываю вам на строку 1010 из /main / SAPI.c исходного кода PHP.

SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC)
{
    if (sapi_module.getenv) { 
        char *value, *tmp = sapi_module.getenv(name, name_len TSRMLS_CC);
        if (tmp) {
            value = estrdup(tmp);
        } else {
            return NULL;
        }
        if (sapi_module.input_filter) {
            sapi_module.input_filter(PARSE_ENV, name, &value, strlen(value), NULL TSRMLS_CC);
        }
        return value;
    }
    return NULL;
}

estrdup () - #defined to _estrdup (), который находится в строке 396 /Zend/zend_alloc.c и использует как стандартные библиотечные функции strlen (), так и memcpy () для выполнения своих заявок. В основном estrdup () будет копировать только до нулевого байта.


во многих языках, нулевой байт символизирует конец строки. Я бы отправил данные как hex и переинтерпретировал их на стороне сервера. Я не думаю, что GET поддерживает binary.


var_dump($your_url);
если он содержит уродливые / нулевые символы, попробуйте TRIM() это на первый взгляд.