cgi.fix_pathinfo
PHP选项(通常是PHP-FPM,快速CGI)有关的安全问题已经引起了很多讨论。结果,默认的nginx配置文件通常说:无需禁用上述PHP选项,即可正确处理PATH_INFO。那是什么?问题
您能清楚解释
cgi.fix_pathinfo
的作用吗? (官方文档只是说:“有关PATH_INFO的更多信息,请参见CGI规范。”)PHP会对这些
PATH_INFO
和SCRIPT_FILENAME
变量真正起作用吗? 为什么使用Nginx会有危险? (详细示例)
这些程序的最新版本是否仍然存在该问题?
Apache容易受到攻击吗?例如,我不明白为什么使用php-fpm Unix套接字可以避免此问题。
#1 楼
TL; DR-解决方案(您甚至可能不需要)非常简单,并且在此答案的结尾。使问题本身有点错误。第一个问题应该是“这是什么路径信息业务?”
路径信息是URI脚本之后的内容(应以正斜杠开头,但在查询参数之前以
?
开头)。 Wikipedia文章概述部分中有关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
视为整个示例:在上面的示例中为“ /path/to/script.php/THIS/IS/PATH/INFO”(前缀启用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中发生的事情是,它找到URI路径的第一部分,该部分与服务器docroot下的任何内容都不对应。对于此示例,它将看到您的服务器上没有“ /docroot/path/to/script.php/THIS”,但您肯定可以拥有“ /docroot/path/to/script.php”,因此现在已经确定了
SCRIPT_FILENAME
,剩下的就由PATH_INFO
组成。更清楚:给定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内容,因此它将执行它(现在已被伪装!)。这不是Nginx本身所特有的。
真正的问题是,您可以将未经信任的内容上传到某处而不进行消毒,并且允许将其他任意请求发送到同一位置,PHP会幸福地执行
可以构建或配置Nginx和Apache来阻止使用这种欺骗手段的请求,并且有很多示例说明如何做到这一点,包括在user2372674的答案中。这篇博客文章很好地解释了这个问题,但是缺少正确的解决方案。
但是,最好的解决方案是仅确保正确配置PHP-FPM,以便它永远不会执行文件,除非文件以“ .php”结尾。值得注意的是,最新版本的PHP-FPM(〜5.3.9 +?)将此默认设置为默认值,因此这种危险不再是太大的问题了。 br />如果您具有最新版本的PHP-FPM(〜5.3.9 +?),则无需执行任何操作,因为以下安全行为已是默认设置。 php-fpm的
www.conf
文件(也许是/etc/php-fpm.d/www.conf
,取决于您的系统)。请确保您具有以下内容:security.limit_extensions = .php
再次出现,这在很多地方都是默认设置。从将“ .php”文件上传到WordPress上载文件夹,然后使用相同的技术执行该文件。您仍然需要为应用程序提供良好的安全性。
评论
好答案!需要说明的是:如果您说的那样,PHP是否确定了SCRIPT_FILENAME是什么,为什么会有fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name;我的nginx conf中的行?它会否覆盖PHP自己发现SCRIPT_FILENAME值的工作?
– Tortor
16-11-5在1:09
是否有一个函数来获取security.limit_extensions的值?我尝试phpinfo(),ini_get(security.limit_extensions)和ini_get_all()没有成功。
–肘部龙虾
18年6月28日在13:31
谢谢,如果最新版本的PHP-FPM(〜5.3.9 +?)将此默认为默认值,为什么php7.1需要它?还是这篇文章错了?
–叶夫根尼·阿法纳舍夫(Yevgeniy Afanasyev)
18年11月27日在4:48
#2 楼
本质上,没有此功能,您可以将名为“ foo.jpg”的php代码文件上传到Web服务器。然后像http://domain.tld/foo.jpg/nonexistent.php那样请求它,Web服务器堆栈会错误地说哦;这是一个PHP;我需要处理此问题,它将找不到foo.jpg / nonexistent.php,因此它将退回到foo.jpg并将foo.jpg作为php代码进行处理。这很危险,因为它会使系统很容易受到入侵。关于将php-fpm与unix套接字一起使用以避免这种情况,例如,任何允许图像上传的Web应用程序都将成为上传后门的工具。 IMO不能解决问题。
评论
您只重复在我提供的链接上可以阅读的内容。您没有解释真正的机制。您的答案需要增值恕我直言。
– Tortor
2014-09-12 13:23
可能是正确的,但是您的标题中有问题,我的答复是对该问题的解答。如果您明确想要它;是的,这很危险;非常危险。
– HrvojeŠpoljar
2014年9月12日下午13:43
1 /我的答案不仅限于标题:它有一个主体。 2 / user109322已经证明您错了:用于cgi.fix_pathinfo的任何值都不危险,因为php-fpm的默认conf是安全的(它将仅执行扩展名为.php的文件)。
– Tortor
16年11月5日,0:56
#3 楼
在Nginx Wiki中,作为安全措施if (!-f $document_root$fastcgi_script_name) {
return 404;
}
包含在位置块中。在其他教程中,使用的是
try_files $uri =404;
,应该这样做,但根据Nginx Wiki可能会出现问题。使用这些选项,
cgi.fix_pathinfo=1
应该不再是问题。更多信息可以在这里找到。
评论
您可以通过了解PATH_INFO和PATH_TRANSLATED的区别来回答自己的问题:blogs.msdn.com/b/david.wang/archive/2005/08/04/…