AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 627903
Accepted
Totor
Totor
Asked: 2014-09-12 09:35:27 +0800 CST2014-09-12 09:35:27 +0800 CST 2014-09-12 09:35:27 +0800 CST

PHP 选项“cgi.fix_pathinfo”对于 Nginx + PHP-FPM 真的很危险吗?

  • 772

关于与Nginx 使用的 PHP 选项(通常是 PHP-FPM,快速 CGI)相关的安全问题已经有 很多 讨论。 cgi.fix_pathinfo

结果,默认的nginx配置文件习惯说:

# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

但是,现在,“官方”Nginx wiki声明PATH_INFO 可以在不禁用上述 PHP 选项的情况下正确处理。所以呢?

问题

  • 你能清楚地解释一下是做什么的cgi.fix_pathinfo吗?(官方文档只是说:“有关 PATH_INFO 的更多信息,请参阅 CGI 规范”)
  • PHP 将如何处理这些PATH_INFO和SCRIPT_FILENAME变量?
  • Nginx 为什么以及如何危险?(详细例子)
  • 这些程序的最新版本中是否仍然存在该问题?
  • Apache易受攻击吗?

我试图了解每一步的问题。例如,我不明白为什么使用 php-fpm Unix 套接字可以避免这个问题。

nginx
  • 3 3 个回答
  • 68962 Views

3 个回答

  • Voted
  1. Best Answer
    user109322
    2015-06-25T20:09:34+08:002015-06-25T20:09:34+08:00

    TL; DR - 修复(您甚至可能不需要)非常简单,并且在此答案的末尾。

    我将尝试解决您的具体问题,但是您对 PATH_INFO 是什么的误解使问题本身有点错误。

    • 第一个问题应该是“这个路径信息业务是什么?”

      • 路径信息是 URI 中脚本之后的内容(应以正斜杠开头,但在以 a 开头的查询参数之前结束?)。维基百科关于 CGI的文章概述部分的最后一段很好地总结了它。下面PATH_INFO是“/THIS/IS/PATH/INFO”:

        http://example.com/path/to/script.php/THIS/IS/PATH/INFO?query_args=foo

    • 您的下一个问题应该是:“PHP 如何确定什么PATH_INFO和SCRIPT_FILENAME是什么?”

      • 早期版本的 PHP 很幼稚,从技术上讲甚至不支持PATH_INFO.,所以应该是PATH_INFO的SCRIPT_FILENAME,是的,在很多情况下都被破坏了。我没有足够旧的 PHP 版本来测试,但我相信它SCRIPT_FILENAME在上面的示例中被视为整个 shebang:“/path/to/script.php/THIS/IS/PATH/INFO”(前缀为docroot 像往常一样)。
      • 启用 cgi.fix_pathinfo 后,PHP 现在可以正确找到上述示例的“/THIS/IS/PATH/INFO”,并将其放入PATH_INFO并SCRIPT_FILENAME获取指向所请求脚本的部分(当然,以 docroot 为前缀)。
      • 注意:当 PHP 开始真正支持PATH_INFO时,他们必须为新功能添加配置设置,以便运行依赖于旧行为的脚本的人可以运行新的 PHP 版本。这就是为什么它甚至有一个配置开关。它应该从一开始就内置(具有“危险”行为)。
    • 但是 PHP 怎么知道脚本的哪一部分以及它的路径信息呢?如果 URI 类似于:

      http://example.com/path/to/script.php/THIS/IS/PATH/INFO.php?q=foo

      • 在某些环境中,这可能是一个复杂的问题。在 PHP 中发生的情况是,它会找到与服务器 docroot 下的任何内容都不对应的 URI 路径的第一部分。对于这个例子,它发现在你的服务器上你没有“/docroot/path/to/script.php/THIS”但是你肯定有“/docroot/path/to/script.php”所以现在SCRIPT_FILENAME已经下定决心,PATH_INFO得到剩下的。
      • 因此,现在 Nginx 文档和Hrvoje Špoljar 的回答(你不能对这样一个清晰的例子过于挑剔)中详细描述的危险的好例子变得更加清楚:鉴于 Hrvoje 的例子(“ http://example. com/foo.jpg/nonexistent.php "),PHP 在你的 docroot "/foo.jpg" 上看到一个文件,但它没有看到任何名为 "/foo.jpg/nonexistent.php" 的文件,所以SCRIPT_FILENAME得到 "/foo.jpg" (同样,以 docroot 为前缀)并PATH_INFO获得“/nonexistent.php”。
    • 现在应该清楚它为什么以及如何造成危险:

      • Web 服务器确实没有错 - 它只是将 URI 代理到 PHP,它无辜地发现“foo.jpg”实际上包含 PHP 内容,所以它执行它(现在你已经被 pwned 了!)。这并不是Nginx 本身所特有的。
    • 真正的问题是你让不受信任的内容上传到某个地方而不进行清理,并且你允许其他任意请求到同一位置,PHP 会在可能的情况下愉快地执行。
    • 可以构建或配置 Nginx 和 Apache 以防止使用此技巧的请求,并且有很多示例说明如何做到这一点,包括在user2372674 的答案中。这篇博客文章很好地解释了这个问题,但它缺少正确的解决方案。

    • 但是,最好的解决方案是确保 PHP-FPM 配置正确,这样它就永远不会执行文件,除非它以“.php”结尾。值得注意的是,最新版本的 PHP-FPM (~5.3.9+?) 将其作为默认设置,因此这种危险不再是太大的问题。

    解决方案

    如果您有最新版本的 PHP-FPM(~5.3.9+?),那么您无需执行任何操作,因为下面的安全行为已经是默认设置。

    否则,找到 php-fpm 的www.conf文件(也许/etc/php-fpm.d/www.conf,取决于你的系统)。确保你有这个:

    security.limit_extensions = .php
    

    同样,这在当今许多地方都是默认设置。

    请注意,这并不能阻止攻击者将“.php”文件上传到 WordPress 上传文件夹并使用相同的技术执行该文件。您仍然需要为您的应用程序提供良好的安全性。

    • 94
  2. Hrvoje Špoljar
    2014-09-13T02:04:04+08:002014-09-13T02:04:04+08:00

    本质上,如果没有这个,您可以将名为 'foo.jpg' 的 php 代码的文件上传到 Web 服务器;然后像http://domain.tld/foo.jpg/nonexistent.php一样请求它,Web 服务器堆栈会错误地说哦;这是一个PHP;我需要处理这个,它会找不到 foo.jpg/nonexistent.php 所以它会回退到 foo.jpg 并将 foo.jpg 作为 php 代码处理。这很危险,因为它使系统很容易被入侵;例如,任何允许上传图片的 Web 应用程序都会成为上传后门的工具。

    关于使用 php-fpm 和 unix socket 来避免它;IMO 它不会解决问题。

    • 15
  3. user2372674
    2015-06-25T05:47:30+08:002015-06-25T05:47:30+08:00

    在Nginx wiki作为安全措施

    if (!-f $document_root$fastcgi_script_name) {
        return 404;
    }
    

    包含在位置块中。在其他教程中

    try_files $uri =404;
    

    使用,它应该做同样的事情,但可以根据 Nginx wiki 给出问题。有了这些选项,cgi.fix_pathinfo=1应该不再是问题了。更多信息可以在这里找到。

    • 3

相关问题

  • Gzip 与反向代理缓存

  • nginx 作为代理的行为

  • Nginx 学习资源 [关闭]

  • 提供 70,000 个静态文件 (jpg) 的最佳方式?

  • 在 Apache、LightTPD 和 Nginx Web 服务器上提供 PHP 5.x 应用程序的现状?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve