一、文件包含漏洞產生的原因
1.什麼是文件包含?
爲了更好的使用代碼的重用性,引入了文件包含函數,可以通過文件包含函數將文件包含進來, 直接使用包含文件的代碼。
2.什麼是文件包含漏洞?
在包含文件時候,爲了靈活包含文件,將被包含文件設置爲變量,通過動態變量來引入需要包含的文件時,用戶可以對變量的值可控而服務器端未對變量值進行合理地校驗或者校驗被繞過,這樣就導致了文件包含漏洞。通常文件包含漏洞出現在PHP語言中。
<?php
$file = $_GET['file']; //從GET方法裏獲取參數file的值,將它賦值給定義的變量file
include($file): //調用include函數去查看變量file對應的文件的內容
3.函數
這裏的函數說的是PHP中的函數。
1.文件包含函數:
include() 、include_once()、require()、require_once():包含並運行指定文件。
include和require的區別:
兩者在包含文件的結構上完全一樣,唯一的區別是對於錯誤的處理。
當在遇到包含文件不存在,或是出錯的時候,include會繼續向下執行,而require會立即停止執行,並報錯。
once的作用:
在腳本執行期間同一個文件有可能被包含超過一次的情況下,使用once就的話就只會包含一次,以避免函數重定義、變量重新賦值等問題。
2.文件讀取函數:
highlight_file、show_source:讀取文件並進行語法高亮顯示。
readfile:讀入一個文件並寫入到輸出緩衝。
file_get_contents:將文件的內容讀入到一個字符串中,可以讀取遠程文件。
fopen() :打開文件或者 URL。
file() :把整個文件讀入一個數組中。
4.文件包含漏洞分類
1.本地文件包含
2.遠程文件包含(允許將URL (如http: //或ftp: //)作爲文件處理)
在php.ini配置文件中有兩個設置與文件包含漏洞有關,需要了解一下:
- allow_url_fopen:
爲ON時,能讀取遠程文件,例如file_get_contents()就能讀遠程文件 - allow_url_include:
爲ON時,就可使用include和require等方式包含遠程文件,爲OFF時只能包含本地文件
注意:
從PHP5.2開始allow_url_include就默認爲OFF了,而allow_url_fopen直是ON的。
文件包含漏洞利用方式
1.僞協議
在PHP中經常使用僞協議進行文件包含。
1.file://:讀取本地文件,後面可以跟絕對路徑和相對路徑。
2.php://filter:是一種元封裝器, 設計用於數據流打開時的篩選過濾應用。
- 這裏的用法舉例裏面是將源文件index.php轉換成base64後讀取出來。
2.php://input:可以訪問請求的原始數據的只讀流,將post請求的數據當作php代碼執行。
3.zip://:想要訪問壓縮包裏的文件,文件名前必須用“#”而不是“/”。
- “#”的URL編碼是%23。
4.compress.bzip2://、compress.zlib://:都是讀取壓縮包的,它們有兩種語法,一種是相對路徑、一種是絕對路徑。
5.data:// 同樣類似與php://input,可以讓用戶來控制輸入流。
6.phar://:解壓縮包的一個函數,不管後綴是什麼,都會當做壓縮包來解壓。
- 例如:phar://xxx.png/shell.php
2.繞過方式
1.00截斷:
Windows在讀文件名時,當遇到ASCII碼0時會判斷爲讀取結束,會自動停止對後面內容的讀取。
在URL中的形式是%00,在十六進制中是0x00。
2.長度截斷:
也是利用操作系統對文件名讀取的特性進行繞過。
Windows最大讀取長度:256;
Linux最大讀取長度:4096。
3.包含日誌文件:
我們使用瀏覽器對URL請求時都會存儲在日誌裏,如果我們在請求地址裏寫上一句話木馬,那麼當我們請求的時候就會把這個一句話木馬寫入日誌文件。
如果我們知道日誌文件的路徑,那我們就可以包含這個日誌文件,從而獲得webshell。
4.包含session:
用法和包含日誌差不多,往session裏寫入一句話木馬,然後知道session路徑以後就可以做文件包含。
文件漏洞的防禦
1.PHP 中使用 open_basedir 配置限制訪問在指定的區域
2.過濾.(點)/(反斜槓)\(反斜槓)
3.禁止服務器遠程文件包含
4.儘量不要使用動態包含,可以在需要包含的頁面固定寫好