【问题标题】:What is causing null byte values in request to get filtered out?是什么导致请求中的空字节值被过滤掉?
【发布时间】:2012-09-01 19:30:19
【问题描述】:

在尝试针对 null byte poisoning 强化 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

【问题讨论】:

  • 您可能应该使用 var_dump 或 print_r 来显示 get/post 数组,以确保导致问题的不是 json_encode。
  • 这是一个公平的观点;我会在我的问题中说明这一点。
  • 首先禁用 Suhosin。它可能已经处理好了。
  • Hakre 指出它禁用了 Suhosin,但您可能想首先考虑 Suhosin 用于硬化,所以只需禁用以测试 Suhosin 是否已经为您执行此操作。
  • @hakre 你是对的。我禁用了 Suhosin,并且能够在传入请求中看到空字节。发布答案,以便我可以奖励您(:

标签: php curl security


【解决方案1】:

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

【讨论】:

  • 我不确定我是否正确理解了您的答案。我不想修改我的代码来处理特殊编码的空字符;我想模拟一个空字节中毒攻击,以确保我的代码受到保护。除非我弄错了,否则这种攻击是通过在请求 URL 或 POST 负载中包含百分比编码的 null (%00) 来执行的。
【解决方案2】:

我指给你看 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() 只会复制一个空字节。

【讨论】:

  • 这非常有用,谢谢,它很好地说明了为什么键名在包含 null 时会被截断。不过,我仍然不确定的是,为什么当值包含 null 时会跳过键和值。
  • 这很奇怪。如果不是完整的 5 个字符的字符串,至少可以预期 baz=nu
【解决方案3】:

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

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

【讨论】:

  • 就是这样。我禁用了 Suhosin,第一个 curl 请求现在返回 {"foo":"bar","baz":"nu\u0000ll"}。现在让 Suhosin 重新开启……但至少现在我知道原因是什么(:
  • @todofixthis:感谢您的赏金,很高兴它帮助您澄清了您的问题。
【解决方案4】:

var_dump($your_url);
如果包含 UGLY/NULL 字符,请先尝试TRIM()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-17
    • 2021-05-09
    • 1970-01-01
    • 2022-11-28
    • 2019-03-14
    • 2018-01-29
    • 2017-03-29
    • 1970-01-01
    相关资源
    最近更新 更多