文件包含漏洞就是使用函數去包含任意文件的時候,當包含的文件來源過濾不嚴謹的時候,當存在包含惡意文件后,就可以通過這個惡意的文件來達到相應的目的。
1.2. 文件包含漏洞原理其實原理就是由于在代碼開發的過程中,有時候會遇到相同的代碼,不想重復輸入,就將代碼單獨寫在一個文件里面,當遇到的時候就直接調用該文件進行運行,而這種方式就會導致客戶端可以調用其他的惡意文件,通過惡意文件造成文件包含漏洞。
但是前提也是當文件包含的代碼文件被當作一個變量來使用,并且能夠被用戶傳入參數,如果沒有對該變量做相應的安全防護,就可能會引發出文件包含漏洞。
(資料圖片僅供參考)
PHP:include() 、include_once()、require()、require_once()JSP/Servlet:ava.io.file()、java.io.filereader()ASP:include file、include virtual1.3.2. PHP函數區別:
文件包含漏洞在PHP中是比較多的,像JSP、ASP這方面的漏洞是比較少的,但這并不是說就不存在。
include:包含并運行指定的文件,包含文件發生錯誤時,程序警告,但會繼續執行。
include_once:和 include 類似,不同處在于 include_once 會檢查這個文件是否已經被導入,如果已導入,下文便不會再導入,直面 once 理解就是只導入一次。
require:包含并運行指定的文件,包含文件發生錯誤時,程序直接終止執行。
require_once:和 require 類似,不同處在于 require_once 只導入一次。
1.4. 文件包含漏洞特征其實在文件包含在URL中能夠明顯的看出來,但是不代表含有這些特征就一定有文件包含漏洞。只不過有這些特征可以進行判斷是存在文件包含的,但是能不能利用是另一方面。
比如:
http://www.xxx.com/index.php/?name=x.phphttp://www.xxx.com/index.php/?file=index21.5. 文件包含漏洞分類1.5.1. 本地文件包含漏洞
本地文件包含,通過意思就能夠理解,就是在條件允許的情況下,所謂的條件允許也就是安全防護沒做到位,通過這個條件對文件路徑加載文件,就形成了本地文件包含。
1.5.1.1. 本地文件包含漏洞案例例如php代碼:
在我網站根目錄下面有一個index.php,通過文件包含進行執行,就形成了本地文件包含,若這個name參數能夠被用戶控制,那么就形成了本地文件包含漏洞。
1.5.2. 遠程文件包含漏洞遠程文件包含漏洞導致的原因和本地文件包含漏洞造成的原因是一樣的,只不過遠程文件包含漏洞是利用外部的服務器中的文件進行執行,就形成了遠程文件包含漏洞。
但是前提是需要在php.ini中的配置選項中allow_url_fopen和allow_url_include為ON。
1.5.2.1. 遠程文件包含漏洞案例準備兩臺虛擬機,一臺做網站服務器,另外一臺做攻擊者主機。
網站服務器:192.168.10.150
攻擊者主機:192.168.10.50
網站服務器php代碼:
攻擊者主機php代碼:
攻擊者訪問服務器網站,并把主機上的本地文件進行遠程文件包含。
1.6. 文件包含漏洞危害讀取WEB服務器上的配置文件以及WEB服務器上的敏感文件,并且若和webshell聯動,并將惡意代碼執行將造成更大的危害,通常來說遠程文件包含漏洞危害更大。
1.7. 文件包含漏洞特點1.7.1. 無視文件擴展名在PHP中當使用上面的一些函數的時候,這個文件就會被當作PHP代碼進行執行,PHP內核并不會在意包含的文件是什么類型的,也就是說當發過來的是.png的文件也會被當作PHP執行。
1.7.1.1. 無視文件擴展名案例例如這里將原來含有代碼的php文件后綴名修改為jpg的時候,依舊執行了php代碼。
1.7.2. 無條件解析PHP代碼文件包含漏洞在讀取源碼的時候,若遇到符合PHP語法規范的代碼,將會無條件執行。
2. 文件包含漏洞利用方式2.1. 判斷服務器類型其實判斷服務器類型還是很好判斷的,當我們讀取一個文件的時候在linux系統該然后讀取?
在linux系統當存在1.php的時候讀取就是cat 1.php,而且讀取的內容假如是:"I Love You",若是讀取1.Php那么還能夠顯示"I Love You"嗎?結果肯定是不行的,由于在linux中是嚴格區分大小寫的。而在windows中是不區分大小寫的,這里就可以使用windows進行測試。
通過上面的圖片能夠看出來,我在URL中讀取的是1.phP,但文件夾中只有2.php,但依舊顯示PHP的默認文件。這就驗證了我上面提到的Windows是不區分大小寫的。
2.2. 敏感文件讀取所謂讀取敏感文件,就是將WEB服務器上一些其他文件讀取出來,這些其他文件中可能包含一些敏感文件,私密文件或者是一些數據、表格等。
2.2.1. 絕對路徑讀取絕對路徑是指目錄下的絕對位置,直接到達目標位置,通常是從盤符開始的路徑,絕對路徑讀取就是通過明確的路徑進行讀取文件,比如windows或者linxu中的一些日志文件存在的路徑,或者一些配置文件存放的路徑。
2.2.1.1. windows敏感文件絕對路徑c:\boot.ini #查看系統版本c:\windows\system32\inetsrv\MetaBase.xml #IIS配置文件c:\windows\repair\sam #存儲Windows的密碼c:\programFiles\mysql\my.ini #mysql配置文件,里面可能有密碼c:\programFiles\mysql\data\mysql\user.MYD #mysql root密碼c:\windows\php.ini #php配置文件2.2.1.2. linux敏感文件絕對路徑
/etc/passwd #用戶密碼/usr/local/app/apache2/conf/httpd.conf #apache2默認配置文件/usr/local/app/apache2/conf/extra/httpd-vhosts.conf #虛擬網站設置/usr/local/app/php5/lib/php.ini #php相關設置 /etc/httpd/conf/httpd.conf #apache配置文件 /etc/my.cnf #mysql配置文件/etc/sysconfig/iptables #查看防火墻策略2.2.1.3. 絕對路徑讀取案例
通過URL看到我這里是直接讀取我C:\tool\PHPTutorial\1.txt的文件。
2.2.2. 相對路徑讀取相對路徑就是指由這個文件所在的路徑引起的跟其它文件(或文件夾)的路徑關系。相對路徑讀取就是當我們不知道某個文件具體路徑的時候,使用相對路徑以當前位置作為參看向后退,逐次訪問。
2.2.2.1. 相對路徑讀取方式相對利用讀取方式就需要使用"../"來進行讀取,一次"../"向后退一次。
例如:當我們在C:\tool\PHPTutorial\www的時候,那么我們使用"../"的時候我們就退到C:\tool\PHPTutorial,若使用兩次"../"的時候就會退到C:\tool,兩次"../"也就是"../../"就可以了。
2.2.2.2. 相對路徑讀取案例1這里我把1.txt創建在C:\tool\PHPTutorial目錄下,而現在這個文件包含漏洞放在www下也就是C:\tool\PHPTutorial\www,所以這里我只需要輸入一次"../"就可以讀取到1.txt了。
2.2.2.3. 相對路徑讀取案例2這里我們思考一下若我們要訪問C:\windows\win.ini,該怎么讀取呢?其實這里可以先退到根目錄下也就是C盤下,然后在訪問windows中的win.ini。
目前我們在C:\tool\PHPTutorial\www下面,那么可以算一下我們要退幾次?這里通過目錄也能夠看出來,這里只需要退三次就可以到C盤下了。
這里由于無法在C盤中創建文件,就無法演示了,那么這里我們直接讀取C:\windows\win.ini吧。
2.2.2.4. 相對路徑讀取案例3這里又出現一個問題,若我們并不知道我們存在那個目錄下,更不知道該退幾級怎么辦?其實這里通過"../"退可以多退幾次,因為最終只能夠退到C盤,所以在不知道幾級的情況下,可以多輸入幾個"../"。
可以看我下面的圖片,我原本只需要退三次就可以了,而我這里退八次依舊能讀取到,所以就能證明剛剛我所解釋的,不管輸入多少個"../"最終只會退到C盤。
2.3. 遠程文件讀取遠程文件包含大概意思在之前已經提過了,這里就演示一下案例。
前提條件:目標服務器的allow_url_fopen選項是on。只有當這個選項是on的時候就能夠使用遠程文件包含一句話木馬。
2.3.1. 遠程文件配合一句話木馬案例網站服務器:192.168.10.150
攻擊者主機:192.168.10.50
攻擊者php代碼:
")?>
這句話的意思就是當訪問這個php代碼后就會在當前目錄生成一個shell.php文件,并且這個文件中含有一句話木馬。
通過查看服務器網站根目錄,可以看到這里已經創建了一個名為shell.php的文件。那么我們通過這個文件使用蟻劍進行連接。
通過上面的圖片可以看到,我們已經成功連接了。這里需要注意的是,我們這個地址是知道的,若在實際環境中操作的時候可能需要注意查找路徑。
2.4. 偽協議讀取2.4.1. PHP偽協議介紹file:// #訪問本地文件系統http:// #訪問HTTPs網址ftp:// #訪問ftp URLphp:// #訪問輸入輸出流zlib:// #壓縮流data:// #數據ssh2:// #security shell2expect:// #處理交互式的流glob:// #查找匹配的文件路徑2.4.2. PHP偽協議利用方式
這里舉幾個例子進行演示一下,由于部分偽協議需要且版本并且需要調配置,這里就不來回切換了。
2.4.2.1. file利用方式file其實和絕對路徑讀取差不多。
URL:http://192.168.10.150/1.php/?name=file://C:/Windows/win.ini2.4.2.2. http利用方式
其實http這里的利用方式,除了能夠跳轉,還能進行遠程包含進行漏洞執行。
URL:http://192.168.10.150/1.php/?name=http://www.baidu.com2.4.2.3. data利用方式
從php5.2.0起,數據流封裝器開始有效,主要用于數據流的讀取。如果傳入的數據是php代碼,就會執行任意代碼。
這里需要注意若使用data的話需要allow_url_include 和allow_url_fopen為on。
URL:http://192.168.10.150/1.php/?name=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4="PD9waHAgcGhwaW5mbygpPz4="是通過base64加密的\2.4.2.4. php利用方式
1)php://filter
php://filter可以在執行代碼前將代碼換個方式讀取出來,只是讀取,不需要開啟,讀取源代碼并進行 base64 編碼輸出,不然會直接當做 php 代碼執行就看不到源代碼內容了
用法:php://filter/read=convert.base64-encode/resource=要讀取的文件URL:http://192.168.10.150/1.php/?name=php://filter/read=convert.base64-encode/resource=2.php解密:
當然里不單單只能讀取當前目錄下的文件,這里就演示一下另外一種讀取方式,我將文件放在上一級目錄中,通過php進行讀取。
URL:http://192.168.10.150/1.php/?name=php://filter/read=convert.base64-encode/resource=../2.php
仔細看URL連接就能看出來,這里使用了之前提到的相對路徑讀取。
2)php://input
php://input主要是用來執行php代碼的,不過php://input需要以POST提交,這里我們先在URL中添加php://input然后抓包把GET修改為POST,最后在數據包的最后輸入想要執行的代碼就可以實現代碼執行。
URL:http://192.168.10.150/1.php/?name=php://input2.5. 文件包含日志讀取
日志會記錄客戶端請求及服務器響應的信息,訪問http://www.xx.com/時,也會被記錄在日志里,也可以插入到User-Agent,但是請求的信息有可能被url編碼之后記錄日志,這里可以通過burp來發送請求包來防止被編碼,通過相對路徑找到日志文件,利用包含漏洞執行。
2.5.1. 各類日志存在位置2.5.1.1. Apacheapache存在兩個文件日志文件,access.log是記錄登錄等信息的日志文件,而error.log是錯誤文件。
Windows系統:apache安裝目錄/logs/access.log或者error.loglinux系統:/var/log/apache/access.log或者error.log/var/log/apache2/access.log或者error.log/etc/httpd/logs/access_log或者error.log2.5.1.2. Nginx
nginx存在兩個文件日志文件,access.log是記錄登錄等信息的日志文件,而error.log是錯誤文件。
Windows系統:nginx安裝目錄/logs/access.log或者error.log2)linux系統:/var/log/nginx/access.log或者error.log2.5.1.3. IIS
iis6.0版本C:\windows\system32\LogFilesiis7.5版本%SystemDrive%\inetpub\logs\LogFiles2.5.2. 包含Apache日志案例
Apache運行后一般默認會生成兩個日志文件,access.log(訪問日志),error.log(錯誤日志)。
下圖就是被轉碼的,只需要手動修改一下重新發送即可。
URL:http://192.168.10.150/
在apache/logs/access.log中就能夠看到我們植入的惡意代碼。編號①是沒使用burp修改前的,編號②是使用burp修改后的。
通過對本地的日志文件進行包含讀取,輸入123=phpinfo();。
URL:http://192.168.10.150/1.php/?name=../Apache/logs/error.log
當然也可以使用蟻劍來進行連接。
URL:http://192.168.10.150/1.php/?name=../Apache/logs/error.log連接密碼:1233. 文件包含漏洞繞過方式3.1. 本地文件包含繞過3.1.1. 空字符繞過
空字符繞過是存在PHP小于5.3.4版本的一個漏洞,這個漏洞就是用于接收來自路徑中的空字符,這樣在部分需求下攻擊者可以利用將此字符放置安全文件后面來繞過訪問限制。
前提條件就是需要PHP版本小于5.3.4,并且關閉PHP魔術引導。
3.1.1.1. PHP魔術引導介紹當sql句中含有單引號,雙引號,反斜杠和NUL時,這時候如果不對這些符號進行轉義,寫入數據庫時就會出錯,而魔術引號magic_quotes_gpc()就是對這些符號進行轉義以便能把數據正確寫入數據庫。不過該參數在php.ini文件中修改。
PHP魔術引號特性已自 PHP5.3.0起廢棄并將自PHP5.4.0起移除。也就是說在本實驗環境的PHP版本中仍是存在的
3.1.1.2. 前提準備靶機版本切換至php-5.2.17+apache,并且把魔術引導關閉。
新建PHP代碼:
3.1.1.3. 空字符繞過案例
在正常訪問的時候可以發現訪問的文件后面被添加了.html。
若這里沒有關閉魔術引導而直接通過空字符繞過就會變成2.php\0.html。但是這里關閉魔術引導后再使用空字符繞過就能夠顯示正常了。
URL:http://192.168.10.150/1.php/?name=2.php%003.1.2. 超長字符繞過
超長字符截斷就是利用操作系統對目錄最大長度的限制,在Windows中目錄長度不可以超過256字節,linux中目錄長度不可以超過4096字節。超過的部分會被丟棄。
可以使用"./"進行填充,當然不單單"./"可以填充,使用"."也可以,至于還有那些可以繞過,可以自己去試試。
3.1.2.1. 超長字符繞過案例正常訪問的我們就不去嘗試了,直接使用超長字符繞過吧,這里在測試的時候發現,在使用"./"進行繞過的時候不能全部使用"./"需要參合點"/",不過測試后發現,只需要在讀取的本地文件后面多添加幾個"/"。
3.2. 遠程文件包含繞過3.2.1. 空字符繞過這里的繞過和本地文件包含繞過一樣。
3.2.2. 超長字符繞過這里我測試后發現,遠程文件包含好像只能使用"./",其它的像"."",""。"":"都不能繞過。
3.2.3. ?繞過3.2.4. 常見特殊字符編碼3.2.5. #繞過這里我使了一下直接使用#并不能繞過,需要輸入編碼%23才能夠生效,在繞過的時候需要注意一下。
3.2.6. 空格繞過這里也是一樣需要使用編碼%20進行繞過,不能直接輸入空格。
4. 文件包含漏洞防御設置白名單:若是在編寫代碼的時候能夠確定文件包含的文件名的時候,那么最好使用白名單進行參數傳入。過濾危險字符:由于Incbude/Require可以對PHP Wrapper形式的地址進行包含執行(需要配置php.ini), 在Linux環境中可以通過"../../"的形式進行目錄繞過,所以需要判斷文件名稱是否為合法的PHP文件。設置文件目錄:PHP配置文件中有open_basedir選項可以設置用戶需要執行的文件目錄,如果設置目錄的話,PHP僅僅在該目錄內搜索文件。關閉危險配置:PHP配置中的allow_url_include選項如果打開,PHP會通過Include/Require進行遠程文件包含,由于遠程文件的不可信任性及不確定性,在開發中禁止打開此選項,PHP默認是關閉的。標簽: