天天看點

php cgi路徑解析,php.ini中的cgi.fix_pathinfo選項

PHP裡經常要擷取目前請求的URL路徑資訊。一般可以通過環境變量$_SERVER[‘PATH_INFO’]擷取,而配置檔案中的cgi.fix_pathinifo選項則與這個值的擷取相關。而$_SERVER[‘PATH_INFO’]中的key PATH_INFO是一個CGI 1.1的标準,經常用來做為傳遞參數給後端的CGI伺服器。

被很多系統用來優化url路徑格式,比如對于很多架構,下面這個網址:

http://www.test.com/index.php/test/my.html?c=index&m=search

我們可以得到

$_SERVER[‘PATH_INFO’] = ‘/test/my.html’

$_SERVER[‘QUERY_STRING’] = ‘c=index&m=search’;

我們再說下php.ini中的配置參數cgi.fix_pathinfo,它是用來對設定cgi模式下為php是否提供絕對路徑資訊或PATH_INFO資訊。沒有這個參數之前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。cgi.fix_pathinfo的預設值是1。

nginx預設是不會設定PATH_INFO環境變量的的值,需要通過正則比對設定SCRIPT_FILENAME,但這樣會帶來安全隐患,需要把cgi.fix_pathinfo=0設定為0。但是一旦關閉這個這場,PHP就擷取不到PATH_INFO資訊,那些依賴PATH_INFO進行URL美化的程式就失效了。

網上給出了一些方案,在關閉cgi.fix_pathinfo時使依賴PATH_INFO美化url的程式能夠正常工作。

1.可以通過rewrite方式代替php中的PATH_INFO

執行個體:thinkphp的pathinfo解決方案

設定URL_MODEL=2

location / {

if (!-e $request_filename){

rewrite ^/(.*)$ /index.php?s=/$1 last;

}

}

2.nginx配置檔案中設定PATH_INFO值

請求的網址是/abc/index.php/abc

PATH_INFO的值是/abc

SCRIPT_FILENAME的值是$doucment_root/abc/index.php

SCRIPT_NAME /abc/index.php

舊版本的nginx使用如下方式配置

location ~ .php($|/) {

set $script $uri;

set $path_info “”;

if ($uri ~ “^(.+.php)(/.+)”) {

set $script $1;

set $path_info $2;

}

fastcgi_pass 127.0.0.1:9000;

fastcgi_index index.php;

fastcgi_param SCRIPT_FILENAME $document_root$script;

fastcgi_param SCRIPT_NAME $script;

fastcgi_param PATH_INFO $path_info;

}

新版本的nginx也可以使用fastcgi_split_path_info指令來設定PATH_INFO,舊的方式不再推薦使用,在location段添加如下配置。

location ~ ^.+.php {

fastcgi_split_path_info ^((?U).+.php)(/?.+)$;

fastcgi_param SCRIPT_FILENAME /path/to/php$fastcgi_script_name;

fastcgi_param PATH_INFO $fastcgi_path_info;

fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;

}

通過上面的描述,我們似乎得出了一個結論:為了安全要關閉掉cgi.fix_pathinfo設定。

但是我們來看看php.ini的配置及說明

; cgi.fix_pathinfo provides real PATH_INFO/PATH_TRANSLATED support for CGI. PHP’s

; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok

; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting

; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting

; of zero causes PHP to behave as before. Default is 1. You should fix your scripts

; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.

; http://php.net/cgi.fix-pathinfo

cgi.fix_pathinfo=1

設定cgi.fix_pathinfo=1才符合cgi标準。那麼有什麼辦法可以在保持cgi.fx_pathinfo預設設定的情況下,保證系統安全嗎?

好消息,新版本PHP(我驗證至少PHP5已經有了這個參數)的fpm配置裡新增了一個額外參數(php-fpm.d/www.conf),

security.limit_extensions = .php .php3 .php4 .php5 .php7

專門用來限制PHP腳本引擎隻支援解析哪些擴充名的檔案

; Limits the extensions of the main script FPM will allow to parse. This can

; prevent configuration mistakes on the web server side. You should only limit

; FPM to .php extensions to prevent malicious users to use other extensions to

; execute php code.

; Note: set an empty value to allow all extensions.

; Default Value: .php

;security.limit_extensions = .php .php3 .php4 .php5 .php7

是以在使用nginx+php-fpm時,可以不用修改系統預設的cgi. fix_pathinfo=1設定了。