什么导致请求中的空字节值被过滤掉?

在试图强化PHP web应用程序以防止空字节中毒时,我注意到在我的请求中,我实际上正在发送一个空字节。

使用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
)

同样的事情发生,如果我修改我的脚本和cURL请求使用$_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

先禁用Suhosin。 它已经处理好了。

只要你启用了它,你就不能轻易地注入NUL字节。


我指向你的PHP源代码的/main/SAPI.c的第1010行。

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()被定义为位于/Zend/zend_alloc.c的第396行的_estrdup(),并且使用标准库函数strlen()和memcpy()来执行其出价。 基本上estrdup()只会复制到一个空字节。


在很多语言中,空字节表示字符串的结尾。 我会发送数据作为十六进制并重新解释它的服务器端。 我不认为GET支持二进制。

链接地址: http://www.djcxy.com/p/11165.html

上一篇: What is causing null byte values in request to get filtered out?

下一篇: pjax or client side MVC?