2012年5月3日
某些基于 CGI 的设置中存在一个漏洞,(Apache+mod_php 和 nginx+php-fpm 不受影响),至少 8 年来一直未被发现。 CGI 规范的第 7 节 中指出
某些系统支持一种向 CGI 脚本提供字符串数组的方法。这仅用于“索引”查询的情况。这是通过“GET”或“HEAD”HTTP 请求识别出来的,该请求的 URL 搜索字符串不包含任何未编码的“=”字符。
因此,在某些 CGI 实现中,不包含“=”的查询字符串的请求与包含“=”的请求的处理方式不同。对于 PHP 来说,这意味着包含 ?-s 的请求可能会转储页面的 PHP 源代码,但包含 ?-s&=1 的请求则没问题。
许多网站将 PHP 作为 Apache 模块通过 mod_php 运行,或者使用 nginx 下的 php-fpm 运行。这两种设置都不会受到此漏洞的影响。直接 shebang 样式的 CGI 似乎也不容易受到攻击。
如果您使用 Apache mod_cgi 运行 PHP,您可能会受到攻击。要查看是否受到攻击,只需在您任何 URL 的末尾添加 ?-s。如果您看到源代码,则表示您受到攻击。如果您的网站正常呈现,则表示您没有受到攻击。
要修复此问题,请升级到 PHP 5.3.12 或 PHP 5.4.2。
我们认识到,由于 CGI 是一种相当过时的运行 PHP 的方式,因此将这些网站升级到现代版本的 PHP 可能不可行。另一种方法是配置您的 Web 服务器,使其不允许使用以“-”开头且不包含“=”的查询字符串的这类请求。添加这样的规则应该不会破坏任何网站。对于使用 mod_rewrite 的 Apache 来说,它将如下所示
RewriteCond %{QUERY_STRING} ^(%2d|-)[^=]+$ [NC]
RewriteRule ^(.*) $1? [L]
如果您要编写自己的规则,请务必将 urlencoded ?%2ds 版本考虑在内。
更糟糕的是,我们的错误系统中存在一个错误,它在对错误报告进行评论时,将错误报告的私有标志切换为公开标志,导致此问题在我们在理想水平上测试解决方案之前就公开发布了。请通过 bugs.php.net 报告任何问题。
如需下载 PHP 5.3.12 和 PHP 5.4.2 源代码,请访问我们的 下载页面,Windows 版本可在 windows.php.net/download/ 找到。还提供 变更日志。