显然,这位开发者是为了方便使用类似 #!/usr/local/bin/php-cgi -d include_path=/path 的写法来进行测试,认为不应该限制php-cgi接受命令行参数,而且这个功能不和其他代码有任何冲突。
于是, if(!cgi) getopt(...) 被删掉了。
但显然,根据RFC中对于command line的说明,命令行参数不光可以通过 #!/usr/local/bin/php-cgi -d include_path=/path 的方式传入php-cgi,更可以通过querystring的方式传入。
这就是本漏洞的历史成因。
那么,可控命令行参数,能做些什么事。
通过阅读源码,我发现cgi模式下有如下一些参数可用:
-c 指定php.ini文件的位置
-n 不要加载php.ini文件
-d 指定配置项
-b 启动fastcgi进程
-s 显示文件源码
-T 执行指定次该文件
-h 和 -? 显示帮助
最简单的利用方式,当然就是 -s ,可以直接显示源码:

但阅读过我写的fastcgi那篇文章的同学应该很快就想到了一个更好的利用方法:通过使用 -d 指定 auto_prepend_file 来制造任意文件读取漏洞,执行任意代码:

注意,空格用 + 或 %20 代替, = 用url编码代替。
这个漏洞被爆出来以后,PHP官方对其进行了修补,发布了新版本5.4.2及5.3.12,但这个修复是不完全的,可以被绕过,进而衍生出CVE-2012-2311漏洞。
PHP的修复方法是对 - 进行了检查:
if(query_string = getenv("QUERY_STRING")) {
decoded_query_string = strdup(query_string);
php_url_decode(decoded_query_string, strlen(decoded_query_string));
if(*decoded_query_string == '-' && strchr(decoded_query_string, '=') == NULL) {
skip_getopt = 1;
}
free(decoded_query_string);
}
可见,获取querystring后进行解码,如果第一个字符是 - 则设置skip_getopt,也就是不要获取命令行参数。
这个修复方法不安全的地方在于,如果运维对php-cgi进行了一层封装的情况下:
#!/bin/sh exec /usr/local/bin/php-cgi $*
通过使用空白符加 - 的方式,也能传入参数。这时候querystring的第一个字符就是空白符而不是 - 了,绕过了上述检查。
于是,php5.4.3和php5.3.13中继续进行修改:
if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
/* we've got query string that has no = - apache CGI will pass it to command line */
unsigned char *p;
decoded_query_string = strdup(query_string);
php_url_decode(decoded_query_string, strlen(decoded_query_string));
for (p = decoded_query_string; *p && *p <= ' '; p++) {
/* skip all leading spaces */
}
if(*p == '-') {
skip_getopt = 1;
}
free(decoded_query_string);
}
先跳过所有空白符(小于等于空格的所有字符),再判断第一个字符是否是 - 。
这个漏洞在当年的影响应该说中等。因为PHP-CGI这个SAPI在漏洞出现的时间点,因为其性能等问题,已经在慢慢退出历史舞台了。但考虑到PHP这个在Web领域举足轻重的语言,跨越多年,用量巨大,很多老的设备、服务器仍在运行有漏洞的版本和PHP-CGI,所以影响也不能低估。
不过,在2017年的今天,我分析这个漏洞当然已经不能谈影响了,只是其思路确实比较有意思,又让我领会了一次阅读RFC的重要性。
PHP有序表查找之插值查找算法示例这篇文章主要介绍了PHP有序表查找之插值查找算法,简单分析了插值查找算法的概念、原理并结合实例形式分析了php实
ThinkPHP整合datatables实现服务端分页的示例代码下面小编就为大家分享一篇ThinkPHP整合datatables实现服务端分页的示例代码,具有很好的参考价值,希望对大家有所帮
PHP实现APP微信支付的实例讲解下面小编就为大家分享一篇PHP实现APP微信支付的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小
PHP实现的多维数组排序算法分析这篇文章主要介绍了PHP实现的多维数组排序算法,结合实例形式对比分析了php针对多维数组及带有键名的多维数组进行
php+ajax实现无刷新文件上传功能(ajaxuploadfile)这篇文章主要为大家详细介绍了php结合ajaxuploadfile实现无刷新文件上传功能,具有一定的参考价值,感兴趣的小伙伴们
PHP的RSA加密解密方法以及开发接口使用本篇文章给大家详细介绍了PHP开发接口使用RSA进行加密解密方法,对此有兴趣的朋友可以学习下。