关于与Nginx一起使用的cgi.fix_pathinfo
PHP选项(通常是PHP-FPM,快速CGI),已经有 很多关于安全问题的 讨论 。
因此,默认的nginxconfiguration文件用来说:
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
然而,现在,“官方”Nginx维基指出, PATH_INFO可以正确处理,而不禁用上述的PHP选项。 所以呢?
cgi.fix_pathinfo
做什么的? ( 官方文档只是说 :“有关PATH_INFO的更多信息,请参阅CGI规范”) PATH_INFO
和SCRIPT_FILENAME
variables? 我试图在每一步都了解这个问题。 例如,我不明白为什么使用php-fpm Unix套接字可以避免这个问题。
我会尽量解决你的具体问题,但是你对PATH_INFO的误解会使问题本身有点错误。
第一个问题应该是“这是什么path信息业务?”
path信息是在URI中的脚本之后的东西(应该以正斜杠开始,但是以查询参数开头,以?
开头)。 维基百科关于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版本来testing,但我相信它看到SCRIPT_FILENAME
作为整个版本:“/path/to/script.php/THIS/IS/PATH/INFO”在上面的例子(前缀与往常一样的文件根据)。 PATH_INFO
而SCRIPT_FILENAME
只获取指向所请求的脚本的部分(当然前缀为docroot) 。 PATH_INFO
,他们必须为新function添加一个configuration设置,以便运行依赖于旧行为的脚本的用户可以运行新的PHP版本。 这就是为什么甚至有一个configuration开关。 应该从一开始就内置(与“危险的”行为)。 但是PHP如何知道脚本的哪部分以及它的path信息呢? 如果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可以使用这个技巧来构build或者configuration为阻止请求,并且有很多例子可以解决这个问题,包括user2372674的答案 。 这篇博客文章很好地解释了这个问题,但是缺less正确的解决scheme。
但是,最好的解决scheme是确保PHP-FPMconfiguration正确,以便永远不会执行文件,除非以“.php”结尾。 值得注意的是,最近版本的PHP-FPM(〜5.3.9 +?)将其作为默认值,所以这个危险不再是那么严重了。
如果你有最新版本的PHP-FPM(〜5.3.9 +?),那么你不需要做任何事情,因为下面的安全行为已经是默认了。
否则,findphp-fpm的www.conf
文件(可能是/etc/php-fpm.d/www.conf
,取决于你的系统)。 确保你有这个:
security.limit_extensions = .php
再次,这是目前很多地方的默认设置。
请注意,这不会阻止攻击者将“.php”file upload到WordPress上传文件夹,并使用相同的技术执行该文件。 您仍然需要为您的应用程序提供良好的安全性。
本质上,如果没有这个,你可以上传一个名为“foo.jpg”的php代码到web服务器上; 然后请求它像http://domain.tld/foo.jpg/nonexistent.php和Web服务器堆栈将错误地说哦; 这是一个PHP; 我需要处理这个,它将无法findfoo.jpg / nonexistent.php,所以它会回落到foo.jpg并将foo.jpg处理为php代码。 这是非常危险的,因为它打开系统很容易入侵; 任何允许图像上传的networking应用程序成为上传后门的工具。
关于使用php-fpm和unix套接字来避免它; 海事组织不会解决问题。
在Nginx wiki中作为安全措施
if (!-f $document_root$fastcgi_script_name) { return 404; }
包含在位置块中。 在其他教程
try_files $uri =404;
被使用,这应该做同样的事情,但可以给根据Nginx维基的问题。 有了这些选项, cgi.fix_pathinfo=1
应该不再是问题了。 更多信息可以在这里find。