什么导致请求中的空字节值被过滤掉?
在试图强化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?