Nginx+PHP 配置漏洞:靜態檔案都可以當作 PHP 解析

來源:互聯網
上載者:User

這個漏洞嚴格上說並不是 Nginx 和 PHP 本身的漏洞造成的,而是由配置造成的。在我之前寫的許多配置中,都普遍存在這個漏洞。

簡易檢測方法:
開啟 Nginx + PHP 伺服器上的任意一張圖片,如:

http://hily.me/test.png

如果在圖片連結後加一串 /xxx.php (xxx為任一字元)後,如:

http://hily.me/test.png/xxx.php

圖片還能訪問的話,說明你的配置存在漏洞。

漏洞分析:

下面通過分析一個很常見的 Nginx 配置來解釋下漏洞的成因:

server {    listen       80;    server_name  test.local;    access_log  /work/www/logs/test.access.log  main;    error_log  /work/www/logs/test.error.log;    location / {        root   /work/www/test;        index  index.html index.htm index.php;    }    location ~ \.php$ {        root           /work/www/test;        fastcgi_index  index.php;        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;        include        fastcgi_params;        fastcgi_pass   unix:/tmp/php-fpm.sock;    }}

我們在 /work/www/test/ 目錄下建立一個檔案 test.png,內容如下:

那麼訪問 http://test.local/test.png 時,輸出為常值內容:

但是當在後面加上 /xxx.php 時,即 http://test.local/test.png/xxx.php,可怕的事情發生了:

Array(    [HOSTNAME] =>    [PATH] => /usr/local/bin:/usr/bin:/bin    [TMP] => /tmp    [TMPDIR] => /tmp    [TEMP] => /tmp    [OSTYPE] =>    [MACHTYPE] =>    [MALLOC_CHECK_] => 2    [USER] => www    [HOME] => /home/www    [FCGI_ROLE] => RESPONDER    [SCRIPT_FILENAME] => /work/www/test/test.png    [QUERY_STRING] =>    [REQUEST_METHOD] => GET    [CONTENT_TYPE] =>    [CONTENT_LENGTH] =>    [SCRIPT_NAME] => /test.png/xxx.php    [REQUEST_URI] => /test.png/xxx.php    [DOCUMENT_URI] => /test.png/xxx.php    [DOCUMENT_ROOT] => /work/www/test    [SERVER_PROTOCOL] => HTTP/1.1    [GATEWAY_INTERFACE] => CGI/1.1    [SERVER_SOFTWARE] => nginx/0.7.62    [REMOTE_ADDR] => 192.168.1.163    [REMOTE_PORT] => 4080    [SERVER_ADDR] => 192.168.1.12    [SERVER_PORT] => 80    [SERVER_NAME] => test.local    [REDIRECT_STATUS] => 200    [HTTP_ACCEPT] => image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/QVOD, application/QVOD, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*    [HTTP_ACCEPT_LANGUAGE] => zh-cn    [HTTP_ACCEPT_ENCODING] => gzip, deflate    [HTTP_USER_AGENT] => Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQPinyin 689; QQDownload 627; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.2; TheWorld)    [HTTP_HOST] => test.local    [HTTP_CONNECTION] => Keep-Alive    [ORIG_SCRIPT_FILENAME] => /work/www/test/test.png/xxx.php    [PATH_TRANSLATED] => /work/www/test    [PHP_SELF] => /test.png/xxx.php    [REQUEST_TIME] => 1274125615)

環境變數中,SCRIPT_FILENAME 是 Nginx 傳過來的:

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

$fastcgi_script_name 變數說明請參考:
http://wiki.nginx.org/NginxHttpFcgiModule

Nginx 傳給 PHP 的值為 /work/www/test/test.png/xxx.php,即 $_SERVER 中 ORIG_SCRIPT_FILENAME 的值,但是 $_SERVER 中 SCRIPT_FILENAME 卻是 /work/www/test/test.png。

原因是,/work/www/test/test.png/xxx.php 並不存在,對於這些不存在的路徑,PHP 會檢查路徑中存在的檔案,並將多餘的部分當作 PATH_INFO。
這裡,/work/www/test/test.png 被 PHP 解析為 SCRIPT_FILENAME,/xxx.php 被 PHP 解析為 PATH_INFO 後被丟棄,因此並沒有在 $_SERVER 中出現。

解決方案:

解決這個漏洞的方法很顯然:關閉上面所述的解析即可。

這個解析可以在 PHP 的設定檔中設定,預設為開啟。在這裡我們需要將它關閉:

; 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=0

其中 cgi.fix_pathinfo=0 為新增的配置行,表示關閉 PHP 的自動 PATH_INFO 檢測。關閉後,該配置漏洞即可消除。

更好的解決方案?
以上方案並不是最完美的,如果你先前有用到 cgi.fix_pathinfo 這個特性,影響會很大,比如關閉後,我的 Blog(Wordpress)文章的 URL 目錄形式就得用 rewrite 來實現了。
如果可以將 PHP 設定成只解析 .php 為副檔名的檔案,那麼這個問題解決起來會更合理。
不過我沒找到相關的設定項,或許今後應該出現在 php-fpm 的設定檔中?

總結:
這類問題基本上是無法預料的,但是如果架構設計良好的話,即使存在這個問題,也不會影響安全性。這裡給出架構上的安全建議:
* 儘可能使動靜內容分離,所有的靜態內容存在於靜態內容伺服器,靜態內容伺服器上不解析PHP,這樣靜態檔案就永遠不能被解析了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.