AI 摘要(由 ChatGPT 总结生成):
文章讲解了在PHP配置中,特别是`php.ini`中的`cgi.fix_pathinfo`参数对网站访问权限的影响。当将该参数设置为0时,可能导致网站出现Access denied错误。文章提到了该参数与`$SERVER['PATH_INFO']`的获取相关,以及`PATH_INFO`在CGI服务器中传递参数的作用。在Nginx中,默认不设置`PATH_INFO`,需要通过正则匹配设置`SCRIPT_FILENAME`,但这可能带来安全隐患,因此建议将`cgi.fix_pathinfo`设置为0。文章还给出了在Nginx中配置`cgi.fix_pathinfo=0`的解决方法,包括修改`location`配置以支持pathinfo。最后,强调了将`cgi.fix_pathinfo`设置为0的作用,即禁止解析非法PHP文件,以增强网站安全性。

今天在进行PHP相关参数配置优化时,将cgi.fix_pathinfo=0后网站出现的Access denied字样及排解方法。

参数说明

PHP里经常要获取当前请求的URL路径信息。一般可以通过环境变量$SERVER[‘PATH_INFO’]获取,而配置文件中的cgi.fix_pathinifo选项则与这个值的获取相关。而$SERVER[‘PATH_INFO’]中的key PATH_INFO是一个CGI 1.1的标准,经常用来做为传递参数给后端的CGI服务器。

PHP的以前的行为是将PATH_TRANSLATED设置为SCRIPT_FILENAME,并且不要弄清PATH_INFO是什么。设置cgi.fix_pathinfo=1后,cgi设置完整的路径信息PATH_TRANSLATED的值为SCRIPT_FILENAME,并且设置PATH_INFO信息;如果设为cgi.fix_pathinfo=0则只设置绝对路径PATH_TRANSLATED的值为SCRIPT_FILENAME。在php.ini文件中cgi.fix_pathinfo的默认值是1。

Nginx默认是不会设置PATH_INFO环境变量的的值,需要通过正则匹配设置SCRIPT_FILENAME,但这样会带来安全隐患,需要把cgi.fix_pathinfo设置为0。但是一旦关闭这个选项,PHP就获取不到PATH_INFO信息,那些依赖PATH_INFO的程序就失效了,甚至网站也会出现Access denied字样,如下:

[root@localhost ~]# curl -i http://192.168.17.130:8090/7.html
HTTP/1.1 403 Forbidden
Server: nginx/1.19.6
Date: Wed, 24 Feb 2021 12:16:30 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding

Access denied.
[root@localhost ~]# 

可造成的危害

我们配置php时将cgi.fix_pathinfo参数设置为0的主要作用是禁止解析非法php文件,如/a.jpg/1.php这样的图片下的一个php文件属于非法的,设置为0就是禁止执行。这种将木马伪装成图片上传的文件攻击方式存在已久,禁止这类文件运行,即使被上传了文件木马,由于设置了不允许运行,所以就没有用了。关于该安全隐患的问题,可参考这篇文章:https://www.laruence.com/2010/05/20/1495.html

Nginx支持pathinfo实现

在将cgi.fix_pathinfo参数设置为0后,为解决网站正常运作而不出现Access denied的问题,遂就在网上查阅了大量资料并结合自己所测试,现给出如下的nginx解析php的代码

location ~ [^/]\.php(/|$) {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    #增加 fastcgi_split_path_info指令,将URI匹配成PHP脚本的URI和pathinfo两个变量
    #即$fastcgi_script_name 和$fastcgi_path_info
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    fastcgi_param   PATH_INFO $fastcgi_path_info;

    # 正则解析路径,使用set指令产生nginx变量并赋值
    set $real_script_name $fastcgi_script_name;
    
    # 正则匹配URI,若能匹配将产生两个子组
    if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
        #将两个子组赋值给刚生成的nginx变量
        set $real_script_name $1;
        set $path_info $2;
     }
     
    # 将可能匹配到的$path_info值通过fastcgi_param指令设置进去
    fastcgi_param   PATH_INFO $path_info;
    
    # 覆盖fastcgi_params文件中默认的SCRIPT_NAME配置项
    fastcgi_param   SCRIPT_NAME $real_script_name;
    
    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    # 加载默认的fastcgi配置项
    include fastcgi_params;
}

这样cgi.fix_pathinfo参数为0也可以正常解析了,此处建议在cgi.fix_pathinfo=1时可将上述参数fastcgi_split_path_info ^(.+?\.php)(/.*)$;fastcgi_param PATH_INFO $fastcgi_path_info;将其注释,保留其它即可,可能此处也有自己理解错误的地方,若有错误,还望各位大佬指正!

End

本文标题:php.ini中的cgi.fix_pathinfo参数解析

本文链接:https://www.isisy.com/1124.html

除非另有说明,本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

声明:转载请注明文章来源。

如果觉得我的文章对你有用,请随意赞赏