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

时间:2012-09-07 22:21:44

标签: php curl security

在尝试强化PHP网络应用程序null byte poisoning时,我注意到我在请求中实际发送一个空字节时有一段时间。

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

4 个答案:

答案 0 :(得分:3)

我指出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()#defined为_estrdup(),位于/Zend/zend_alloc.c的第396行,并使用标准库函数strlen()和memcpy()进行出价。基本上estrdup()只会复制到空字节。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

首先禁用Suhosin。它已经照顾好了。

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

答案 3 :(得分:0)

<强> var_dump($your_url);
如果它包含UGLY / NULL字符,那么首先尝试 TRIM()