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