TL; DR-解决方案(您甚至可能不需要)非常简单,并且在此答案的结尾。
我将尝试解决您的特定问题,但是您对PATH_INFO的误解会使问题本身有些错误。
第一个问题应该是“这条路径信息业务是什么?”
你的下一个问题应该是:“如何PHP确定什么PATH_INFO
和SCRIPT_FILENAME
是谁?”
- 早期版本的PHP天真,并且在技术上甚
PATH_INFO
至不支持,因此本来应该PATH_INFO
混用的东西SCRIPT_FILENAME
在很多情况下就被破坏了。我没有足够老的PHP版本可进行测试,但我认为它SCRIPT_FILENAME
的整体含义是:上例中的“ /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中发生的事情是,它找到URI路径的第一部分,该部分与服务器docroot下的任何内容都不对应。对于此示例,它看到您的服务器上没有“ /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在您的文档根目录“ /foo.jpg”上看到一个文件,但看不到任何名为“ /foo.jpg/nonexistent.php”的文件,因此
SCRIPT_FILENAME
获取了“ /foo.jpg” (再次,以docroot PATH_INFO
开头)并获得“ /nonexistent.php”。
现在应该清楚为什么以及如何可能造成危险:
- Web服务器确实没有错-只是将URI代理给PHP,PHP无辜地发现“ foo.jpg”实际上包含PHP内容,因此它将执行它(现在您已经被伪装了!)。这是不是特别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的上载文件夹并使用相同的技术执行该文件。您仍然需要为应用程序提供良好的安全性。