溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

php://filter怎么用

發(fā)布時間:2021-08-09 09:53:18 來源:億速云 閱讀:153 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)php://filter怎么用的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

php://filter是PHP中獨(dú)有的協(xié)議,利用這個協(xié)議可以創(chuàng)造很多“妙用”,本文說幾個有意思的點(diǎn),剩下的大家自己下去體會。本來本文的思路我上半年就準(zhǔn)備拿來做XDCTF2016的題目的,沒想到被三個白帽的一題搶先用了,我也就只好提前分享一下。

XXE中的使用

php://filter之前最常出鏡的地方是XXE。由于XXE漏洞的特殊性,我們在讀取HTML、PHP等文件時可能會拋出此類錯誤parser error : StartTag: invalid element name 。其原因是,PHP是基于標(biāo)簽的腳本語言,<?php ... ?>這個語法也與XML相符合,所以在解析XML的時候會被誤認(rèn)為是XML,而其中內(nèi)容(比如特殊字符)又有可能和標(biāo)準(zhǔn)XML沖突,所以導(dǎo)致了出錯。

那么,為了讀取包含有敏感信息的PHP等源文件,我們就要先將“可能引發(fā)沖突的PHP代碼”編碼一遍,這里就會用到php://filter。

php://filter是PHP語言中特有的協(xié)議流,作用是作為一個“中間流”來處理其他流。比如,我們可以用如下一行代碼將POST內(nèi)容轉(zhuǎn)換成base64編碼并輸出:

readfile("php://filter/read=convert.base64-encode/resource=php://input");

如下:

php://filter怎么用

所以,在XXE中,我們也可以將PHP等容易引發(fā)沖突的文件流用php://filter協(xié)議流處理一遍,這樣就能有效規(guī)避特殊字符造成混亂。

如下,我們使用的是php://filter/read=convert.base64-encode/resource=./xxe.php

php://filter怎么用

巧用編碼與解碼

使用編碼不光可以幫助我們獲取文件,也可以幫我們?nèi)コ恍安槐匾穆闊薄?/p>

記得前段時間三個白帽有個比賽,其中有一部分代碼大概類似于以下:

<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);

 $content在開頭增加了exit過程,導(dǎo)致即使我們成功寫入一句話,也執(zhí)行不了(這個過程在實(shí)戰(zhàn)中十分常見,通常出現(xiàn)在緩存、配置文件等等地方,不允許用戶直接訪問的文件,都會被加上if(!defined(xxx))exit;之類的限制)。那么這種情況下,如何繞過這個“死亡exit”?

幸運(yùn)的是,這里的$_POST['filename']是可以控制協(xié)議的,我們即可使用 php://filter協(xié)議來施展魔法:使用php://filter流的base64-decode方法,將$content解碼,利用php base64_decode函數(shù)特性去除“死亡exit”。

眾所周知,base64編碼中只包含64個可打印字符,而PHP在解碼base64時,遇到不在其中的字符時,將會跳過這些字符,僅將合法字符組成一個新的字符串進(jìn)行解碼。

所以,一個正常的base64_decode實(shí)際上可以理解為如下兩個步驟:

<?php
$_GET['txt'] = preg_replace('|[^a-z0-9A-Z+/]|s', '', $_GET['txt']);
base64_decode($_GET['txt']);

所以,當(dāng)$content被加上了<?php exit; ?>以后,我們可以使用 php://filter/write=convert.base64-decode 來首先對其解碼。在解碼的過程中,字符<、?、;、>、空格等一共有7個字符不符合base64編碼的字符范圍將被忽略,所以最終被解碼的字符僅有“phpexit”和我們傳入的其他字符。

“phpexit”一共7個字符,因為base64算法解碼時是4個byte一組,所以給他增加1個“a”一共8個字符。這樣,"phpexita"被正常解碼,而后面我們傳入的webshell的base64內(nèi)容也被正常解碼。結(jié)果就是<?php exit; ?>沒有了。

最后效果是 :

php://filter怎么用

利用字符串操作方法

有的同學(xué)說,base64的算法我不懂,上面的方法太復(fù)雜了。

其實(shí),除了使用base64特性的方法外,我們還可以利用php://filter字符串處理方法來去除“死亡exit”。我們觀察一下,這個<?php exit; ?>實(shí)際上是什么?

實(shí)際上是一個XML標(biāo)簽,既然是XML標(biāo)簽,我們就可以利用strip_tags函數(shù)去除它,而php://filter剛好是支持這個方法的。

編寫如下測試代碼即可查看 php://filter/read=string.strip_tags/resource=php://input 的效果:

echo readfile('php://filter/read=string.strip_tags/resource=php://input');

php://filter怎么用

可見,<?php exit; ?>被去除了。但回到上面的題目,我們最終的目的是寫入一個webshell,而寫入的webshell也是php代碼,如果使用strip_tags同樣會被去除。

萬幸的是,php://filter允許使用多個過濾器,我們可以先將webshell用base64編碼。在調(diào)用完成strip_tags后再進(jìn)行base64-decode。“死亡exit”在第一步被去除,而webshell在第二步被還原。

最終的數(shù)據(jù)包如下:

php://filter怎么用

除此之外,我們還可以利用rot13編碼獨(dú)立完成任務(wù)。原理和上面類似,核心是將“死亡exit”去除。<?php exit; ?>在經(jīng)過rot13編碼后會變成<?cuc rkvg; ?>,在PHP不開啟short_open_tag時,php不認(rèn)識這個字符串,當(dāng)然也就不會執(zhí)行了:

php://filter怎么用

當(dāng)然,這個方法的條件就是不開啟短標(biāo)簽。

感謝各位的閱讀!關(guān)于“php://filter怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI