Nginx+PHP 配置漏洞

lrenwang發表於2010-05-21

這個漏洞嚴格上說並不是 Nginx 和 PHP 本身的漏洞造成的,而是由配置造成的。在我之前寫的許多配置中,都普遍存在這個漏洞。
簡易檢測方法:
開啟 Nginx + PHP 伺服器上的任意一張圖片,如:
http://blog.lrenwang.com/test.png
如果在圖片連結後加一串 /xxx.php (xxx為任意字元)後,如:
http://blog.lrenwang.com/test.png/xxx.php
圖片還能訪問並且輸出的 Content-Type 為 text/html 的話,說明你的配置存在漏洞。


分析原因
Nginx 傳給 PHP 的值為 /var/www/lrenwang/test.png/xxx.php,即 $_SERVER 中 ORIG_SCRIPT_FILENAME 的值,但是 $_SERVER 中 SCRIPT_FILENAME 卻是 /var/www/test/test.png。

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

解決方法:

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

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

;cgi.fix_pathinfo=1
cgi.fix_pathinfo=0

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

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

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

相關文章