关于与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 套接字可以避免这个问题。
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
是什么?”PATH_INFO
.,所以应该是PATH_INFO
的SCRIPT_FILENAME
,是的,在很多情况下都被破坏了。我没有足够旧的 PHP 版本来测试,但我相信它SCRIPT_FILENAME
在上面的示例中被视为整个 shebang:“/path/to/script.php/THIS/IS/PATH/INFO”(前缀为docroot 像往常一样)。PATH_INFO
并SCRIPT_FILENAME
获取指向所请求脚本的部分(当然,以 docroot 为前缀)。PATH_INFO
时,他们必须为新功能添加配置设置,以便运行依赖于旧行为的脚本的人可以运行新的 PHP 版本。这就是为什么它甚至有一个配置开关。它应该从一开始就内置(具有“危险”行为)。但是 PHP 怎么知道脚本的哪一部分以及它的路径信息呢?如果 URI 类似于:
http://example.com/path/to/script.php/THIS/IS/PATH/INFO.php?q=foo
SCRIPT_FILENAME
已经下定决心,PATH_INFO
得到剩下的。SCRIPT_FILENAME
得到 "/foo.jpg" (同样,以 docroot 为前缀)并PATH_INFO
获得“/nonexistent.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
,取决于你的系统)。确保你有这个:同样,这在当今许多地方都是默认设置。
请注意,这并不能阻止攻击者将“.php”文件上传到 WordPress 上传文件夹并使用相同的技术执行该文件。您仍然需要为您的应用程序提供良好的安全性。
本质上,如果没有这个,您可以将名为 '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 它不会解决问题。
在Nginx wiki作为安全措施
包含在位置块中。在其他教程中
使用,它应该做同样的事情,但可以根据 Nginx wiki 给出问题。有了这些选项,
cgi.fix_pathinfo=1
应该不再是问题了。更多信息可以在这里找到。