Nginx + PHP CGI的一个可能的安全漏洞

现在普遍的Nginx + PHP cgi的做法是在配置文件中, 通过正则匹配(Nginx(PHP/fastcgi)的PATH_INFO问题)设置SCRIPT_FILENAME, 今天小顿发现了一个这种方式的安全漏洞.

比如, 有http://www.laruence.com/fake.jpg, 那么通过构造如下的URL, 就可以看到fake.jpg的二进制内容:

  1. http://www.laruence.com/fake.jpg/foo.ph

为什么会这样呢?

比如, 如下的nginx conf:

  1. location ~ \.php($|/) {
  2.      fastcgi_pass 127.0.0.1:9000;
  3.      fastcgi_index index.php;
  4.  
  5.      set $script $uri;
  6.      set $path_info "";
  7.      if ($uri ~ "^(.+\.php)(/.*)") {
  8.           set $script $1;
  9.           set $path_info $2;
  10.      }
  11.  
  12.      include fastcgi_params;
  13.      fastcgi_param SCRIPT_FILENAME $document_root$script;
  14.      fastcgi_param SCRIPT_NAME $script;
  15.      fastcgi_param PATH_INFO $path_info;
  16.  

通过正则匹配以后, SCRIPT_NAME会被设置为”fake.jpg/foo.php”, 继而构造成SCRIPT_FILENAME传递个PHP CGI, 但是PHP又为什么会接受这样的参数, 并且把a.jpg解析呢?

这就要说到PHP的cgi SAPI中的参数, fix_pathinfo了:

  1. ; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's
  2. ; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
  3. ; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting
  4. ; this to 1 will cause PHP CGI to fix it's paths to conform to the spec. A setting
  5. ; of zero causes PHP to behave as before. Default is 1. You should fix your scripts
  6. ; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
  7. cgi.fix_pathinfo=

如果开启了这个选项, 那么就会触发在PHP中的如下逻辑:

  1. /*
  2. * if the file doesn't exist, try to extract PATH_INFO out
  3. * of it by stat'ing back through the '/'
  4. * this fixes url's like /info.php/test
  5. */
  6. if (script_path_translated &&
  7.      (script_path_translated_len = strlen(script_path_translated)) > 0 &&
  8.      (script_path_translated[script_path_translated_len-1] == '/' ||
  9. ....//以下省略.

到这里, PHP会认为SCRIPT_FILENAME是fake.jpg, 而foo.php是PATH_INFO, 然后PHP就把fake.jpg当作一个PHP文件来解释执行… So…

这个隐患的危害用小顿的话来说, 是巨大的.

对于一些论坛来说, 如果上传一个图片(实际上是恶意的PHP脚本), 继而构造这样的访问请求…

所以, 大家如果有用这种服务器搭配的, 请排查(可以用网页的方式查看phpinfo();看一下 fix_pathinfo的值是0还是1  ), 如果有隐患, 请关闭fix_pathinfo(默认是开启的) 然后重启PHP.

原文地址:http://www.laruence.com/



如果我的文章能帮助到你我会非常高兴。你的支持是对我的认可,将会大大地鼓励我写更多的文章,哪怕只给我一毛钱:-)

期待您的捐赠
Thanks for donation

咦?还没有评论,抢沙发!

发表评论

带 * 的是必填项目,电子邮件地址不会被公开。
文字的交流也是情感的交流,技能的交流也是学术的交流。

无觅相关文章插件,快速提升流量