PHP檔案包含漏洞攻防實戰(allow_url_fopen、open_basedir)
摘要
PHP是一種非常流行的Web開發語言,網際網路上的許多Web應用都是利用PHP開發的。而在利用PHP開發的Web應用中,PHP檔案包含漏洞是一種常見的漏洞。利用PHP檔案包含漏洞入侵網站也是主流的一種攻擊手段。本文對PHP檔案包含漏洞的形成、利用技巧及防範進行了詳細的分析,並通過一個真實案例演示瞭如何利用PHP檔案包含漏洞對目標網站進行滲透測試,最終成功獲取到網站的WebShell。
1. PHP檔案包含漏洞介紹
首先,我們來介紹下何為檔案包含漏洞。嚴格來說,檔案包含漏洞是“程式碼注入”的一種。其原理就是注入一段使用者能控制的指令碼或程式碼,並讓服務端執行。“程式碼注入”的典型代表就是檔案包含。檔案包含漏洞可能出現在JSP、PHP、ASP等語言中,原理都是一樣的,本文只介紹PHP檔案包含漏洞。
要想成功利用檔案包含漏洞進行攻擊,需要滿足以下兩個條件:
1.1 Web應用採用include()等檔案包含函式通過動態變數的方式引入需要包含的檔案;
1.2 使用者能夠控制該動態變數。
在PHP中,有四個用於包含檔案的函式,當使用這些函式包含檔案時,檔案中包含的PHP程式碼會被執行。下面對它們之間的區別進行解釋:
include(): 當使用該函式包含檔案時,只有程式碼執行到include()函式時才將檔案包含進來,發生錯誤時只給出一個警告,繼續向下執行。
include_once(): 功能和include()相同,區別在於當重複呼叫同一檔案時,程式只調用一次。
require(): 1.require()與include()的區別在於require()執行如果發生錯誤,函式會輸出錯誤資訊,並終止指令碼的執行。2.使用require()函式包含檔案時,只要程式一執行,立即呼叫檔案,而include()只有程式執行到該函式時才呼叫。
require_once(): 它的功能與require()相同,區別在於當重複呼叫同一檔案時,程式只調用一次。
現在來看一段簡單的檔案包含程式碼,如下圖所示:
圖1
通過上面的程式碼可以看到,在得到變數$filename的值後沒有經過任何處理,直接帶入include()函式中。此處就存在一個檔案包含漏洞,利用該漏洞我們可以檢視系統中的任意檔案。
下面我們來實際測試一下,首先將該PHP頁面上傳到Web伺服器,先讓其包含一個正常的txt檔案,執行結果如下圖所示:
圖2
接著我們在該txt文字中插入php程式碼,看結果如何?這裡給其插入如下程式碼:
圖3
再次訪問,結果如下圖所示:
圖4
通過上圖我們可以看到文字中的PHP程式碼被成功執行了。
利用該漏洞我們可以檢視系統中的任意檔案,比如經常用到的“/etc/passwd”檔案。
圖5
PHP檔案包含漏洞分為本地檔案包含漏洞(LFI)和遠端檔案包含漏洞(RFI),能夠開啟幷包含本地檔案的漏洞,被稱為本地檔案包含漏洞。利用本地檔案包含漏洞可以檢視系統任意檔案內容,如果具備一些條件,也可以執行命令。在下面的漏洞利用技巧部分對這個有詳細的介紹。
如果php.ini的配置選項allow_url_fopen和allow_url_include為ON的話,則檔案包含函式是可以載入遠端檔案的,這種漏洞被稱為遠端檔案包含漏洞。利用遠端檔案包含漏洞可以直接執行任意命令。在實際滲透攻擊過程中,攻擊者可以在自己的Web伺服器上放一個可執行的惡意檔案,通過目標網站存在的遠端檔案包含漏洞來載入檔案,從而實現執行任意命令的目的。
2. 檔案包含漏洞利用技巧
遠端檔案包含漏洞之所以能夠執行命令,就是因為攻擊者可以自定義被包含的檔案內容。因此,本地檔案包含漏洞要想執行命令,也需要找一個攻擊者能夠控制內容的本地檔案。
目前主要有幾下幾種常見的技巧:
2.1 包含使用者上傳的檔案
這個很好理解,也是最簡單的一種辦法。如果使用者上傳的檔案內容中包含PHP程式碼,那麼這些程式碼被檔案包含函式載入後將會被執行。但能否攻擊成功,取決於上傳功能的設計,比如需要知道上傳檔案存放的物理路徑,還需要上傳的檔案有執行許可權。
2.2 包含data://或php://input等偽協議
這需要目標伺服器支援,同時要求allow_url_fopen為設定為ON。在PHP5.2.0之後的版本中支援data: 偽協議,可以很方便的執行程式碼。
2.3 包含Session檔案
這部分需要攻擊者能夠控制部分Session檔案的內容。PHP預設生成的Session檔案一般存放在/tmp目錄下。
2.4 包含日誌檔案
比如Web伺服器的訪問日誌檔案,這是一種通用的技巧。因為幾乎所有網站都會將使用者的訪問記錄到訪問日誌中。因此,攻擊者可以向Web日誌中插入PHP程式碼,通過檔案包含漏洞來執行包含在Web日誌中的PHP程式碼。下面的安例中就是利用該技巧成功獲取到目標網站的WebShell的。但需要注意的是,如果網站訪問量大的話,日誌檔案可能會非常大,這時如果包含一個這麼大的檔案時,PHP程序可能會卡死。一般網站通常會每天生成一個新的日誌檔案,因此在凌晨時進行攻擊相對來說容易成功。
2.5 包含/proc/self/environ檔案
這個也是一種通用的技巧。因為它根本不需要猜測被包含檔案的路徑,同時使用者也能控制它的內容。常見的做法是向User-Agent中注入PHP程式碼來完成攻擊。
3. 利用PHP檔案包含漏洞滲透某網站案例
上面我們詳細的介紹了PHP檔案包含漏洞的形成和測試,下面我們通過一個真實案例來講解下如何利用PHP檔案包含漏洞對目標網站進行滲透攻擊。
目標網站:中國電信某業務系統
目的:獲取到目標網站的WebShell
詳細滲透過程:
3.1 發現漏洞
我們先來開啟目標網站的一個URL看下,如下所示:
注意path=後面的內容,通過這個URL可以發現index.php呼叫檔案包含函式來包含網站目錄下的檔案,並展示給使用者。但這時我們並不能確定此URL存在檔案包含漏洞。下面我們來手工測試下是否存在檔案包含漏洞。因為該網站存在一個phpinfo.php的測試頁面,我們可以通過該頁面得到目標網站的很多有用資訊,不必進行模糊測試就可以獲取到Web目錄的絕對路徑,所以這裡可以直接構造已知檔案的路徑,讓其包含,快速確認是否存在檔案包含漏洞。
我們來通過包含一個已知的檔案”/etc/passwd”檔案來確認以上URL是否檔案包含漏洞。
圖6
OK,通過上面返回的結果可以確定網站存在檔案包含漏洞,下面我們來演示下如何利用該漏洞進行滲透測試。
3.2 漏洞利用
通過上面的測試,我們可以確定網站存在檔案包含漏洞。那麼這時問題來了,如何利用這個漏洞來達到我們的目的呢?其中一個思路就是將後門程式碼插入網站的Web日誌檔案中,利用目標網站存在的檔案包含漏洞包含此日誌檔案,這時Web日誌中的後門程式碼將會作為PHP程式碼執行,這樣我們就可以獲取到一個WebShell進行後續的攻擊。但這時面臨一個問題,我們需要知道Web日誌的存放路徑,否則無法實現目標。通常Web日誌存放路徑通過Web伺服器的配置檔案指定。通過上面獲取的資訊可以確定目標網站使用的是Nginx伺服器,因此我們可以先通過包含Web伺服器配置檔案(Nigix.conf)來獲取到Web日誌存放路徑。具體操作如下圖所示:
圖7
3.3 獲取到WebShell
上面我們通過Web伺服器配置檔案(Nginx.conf)獲取到了Web訪問日誌的存在路徑(/opt/nginx/logs/access.log),但因為該網站的日誌檔案很大,這時訪問WebShell程式會卡死,所以我們選擇凌晨的時候進行再次攻擊。因為一般的網站都是每天生成一個訪問日誌檔案,在凌晨的時候日誌檔案較小,容易成功。下圖展示瞭如下向Web訪問日誌中插入後門程式碼:
圖8
最終,我們成功獲取到了目標網站的WebShell。
圖9
4. PHP檔案包含漏洞防範
本部分主要從程式碼層和Web伺服器安全配置兩個方面來講解PHP檔案包含漏洞的防範。首先來從程式碼層來講,在開發過程中應該儘量避免動態的變數,尤其是使用者可以控制的變數。一種保險的做法是採用“白名單”的方式將允許包含的檔案列出來,只允許包含白名單中的檔案,這樣就可以避免任意檔案包含的風險。可參考下面的程式碼實現:
圖10
還有一種做法是將檔案包含漏洞利用過程中的一些特殊字元定義在黑名單中,對傳入的引數進行過濾,但這樣有時會因為過濾不全,導致被有經驗的攻擊者繞過。
在Web伺服器安全配置方面可以通過設定php.ini中open_basedir的值將允許包含的檔案限定在某一特定目錄內,這樣可以有效的避免利用檔案包含漏洞進行的攻擊。需要注意的是,open_basedir的值是目錄的字首,因此假設設定如下值:open_basedir=/var/www/test,那麼實際上以下目錄都是在允許範圍內的。
/var/www/test
/var/www/test123
/var/www/testabc
如果要限定一個指定的目錄,需要在最後加上”/“,這一點需要特別注意。
open_basedir=/var/www/test/
如果有多個目錄,在Windows下目錄間用分號隔開,在Linux下面則用冒號隔開。
5. 總結
上面我們通過文字和程式碼對PHP檔案包含漏洞的形成、利用技巧及防範都做了詳細的分析,並結一個真實案例講解了如何利用PHP檔案包含漏洞對目標網站進行滲透測試,最終獲取到一個WebShell許可權。通過這些內容,相信讀者對PHP檔案包含漏洞有了一個深入的認識。其實只要明白了漏洞的原理,對漏洞有一個深入的認識,加上安全意識,徹底解決PHP檔案包含漏洞並不是一件困難的事情。