7

在尝试强化 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'
大批
(
    [foo] => 酒吧
)

> curl 'http://localhost/test.php?foo=bar&b%00az=null'
大批
(
    [foo] => 酒吧
    [b] => 空
)

如果我修改我的脚本和 cURL 请求以使用$_POST.

并不是我在抱怨,但我确实需要知道为什么会这样,这样我才能确保每个网络服务器都配置正确。

是什么导致了这种行为?

> php -v

PHP 5.3.3 (cli)(构建:2012 年 7 月 3 日 16:40:30)
版权所有 (c) 1997-2010 PHP 集团
Zend Engine v2.3.0,版权所有 (c) 1998-2010 Zend Technologies
    与 Suhosin v0.9.29,版权所有 (c) 2007,SektionEins GmbH
4

4 回答 4

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() 是在 /Zend/zend_alloc.c 的第 396 行的 _estrdup() 中#定义的,它使用标准库函数 strlen() 和 memcpy() 来完成它的竞标。基本上 estrdup() 只会复制一个空字节。

于 2012-09-08T02:58:32.977 回答
0

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

于 2012-09-07T22:31:24.553 回答
0

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

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

于 2012-10-12T18:50:26.197 回答
0

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

于 2015-05-11T13:48:06.373 回答