PHP伪协议详解
PHP偽協(xié)議詳解
php支持的偽協(xié)議
1 file:// — 訪問本地文件系統(tǒng) 2 http:// — 訪問 HTTP(s) 網(wǎng)址 3 ftp:// — 訪問 FTP(s) URLs 4 php:// — 訪問各個輸入/輸出流(I/O streams) 5 zlib:// — 壓縮流 6 data:// — 數(shù)據(jù)(RFC 2397) 7 glob:// — 查找匹配的文件路徑模式 8 phar:// — PHP 歸檔 9 ssh2:// — Secure Shell 2 10 rar:// — RAR 11 ogg:// — 音頻流 12 expect:// — 處理交互式的流1 php://filter
php://filter 是一種元封裝器, 設計用于數(shù)據(jù)流打開時的篩選過濾應用。 這對于一體式(all-in-one)的文件函數(shù)非常有用,類似 readfile()、 file() 和 file_get_contents(), 在數(shù)據(jù)流內容讀取之前沒有機會應用其他過濾器。
簡單通俗的說,這是一個中間件,在讀入或寫入數(shù)據(jù)的時候對數(shù)據(jù)進行處理后輸出的一個過程。
php://filter可以獲取指定文件源碼。當它與包含函數(shù)結合時,php://filter流會被當作php文件執(zhí)行。所以我們一般對其進行編碼,讓其不執(zhí)行。從而導致 任意文件讀取。
協(xié)議參數(shù)
| resource=<要過濾的數(shù)據(jù)流> | 這個參數(shù)是必須的。它指定了你要篩選過濾的數(shù)據(jù)流。 |
| read=<讀鏈的篩選列表> | 該參數(shù)可選。可以設定一個或多個過濾器名稱,以管道符(|)分隔。 |
| write=<寫鏈的篩選列表> | 該參數(shù)可選。可以設定一個或多個過濾器名稱,以管道符(|)分隔。 |
| <;兩個鏈的篩選列表> | 任何沒有以 read= 或 write= 作前綴 的篩選器列表會視情況應用于讀或寫鏈。 |
常用:
php://filter/read=convert.base64-encode/resource=index.php php://filter/resource=index.php利用filter協(xié)議讀文件±,將index.php通過base64編碼后進行輸出。這樣做的好處就是如果不進行編碼,文件包含后就不會有輸出結果,而是當做php文件執(zhí)行了,而通過編碼后則可以讀取文件源碼。
而使用的convert.base64-encode,就是一種過濾器。
過濾器
字符串過濾器
該類通常以string開頭,對每個字符都進行同樣方式的處理。
string.rot13
一種字符處理方式,字符右移十三位。
string.toupper
將所有字符轉換為大寫。
string.tolower
將所有字符轉換為小寫。
string.strip_tags
這個過濾器就比較有意思,用來處理掉讀入的所有標簽,例如XML的等等。在繞過死亡exit大有用處。
轉換過濾器
對數(shù)據(jù)流進行編碼,通常用來讀取文件源碼。
convert.base64-encode & convert.base64-decode
base64加密解密
convert.quoted-printable-encode & convert.quoted-printable-decode
可以翻譯為可打印字符引用編碼,使用可以打印的ASCII編碼的字符表示各種編碼形式下的字符。
壓縮過濾器
注意,這里的壓縮過濾器指的并不是在數(shù)據(jù)流傳入的時候對整個數(shù)據(jù)進行寫入文件后壓縮文件,也不代表可以壓縮或者解壓數(shù)據(jù)流。壓縮過濾器不產生命令行工具如 gzip的頭和尾信息。只是壓縮和解壓數(shù)據(jù)流中的有效載荷部分。
用到的兩個相關過濾器:zlib.deflate(壓縮)和 zlib.inflate(解壓)。zilb是比較主流的用法,至于bzip2.compress和 bzip2.decompress工作的方式與 zlib 過濾器大致相同。
加密過濾器
mcrypt.*和 mdecrypt.*使用 libmcrypt 提供了對稱的加密和解密。
更多妙用:https://www.leavesongs.com/PENETRATION/php-filter-magic.html
利用filter偽協(xié)議繞過死亡exit
什么是死亡exit
死亡exit指的是在進行寫入PHP文件操作時,執(zhí)行了以下函數(shù):
file_put_contents($content, '<?php exit();' . $content);亦或者
file_put_contents($content, '<?php exit();?>' . $content);這樣,當你插入一句話木馬時,文件的內容是這樣子的:
<?php exit();?><?php @eval($_POST['snakin']);?>這樣即使插入了一句話木馬,在被使用的時候也無法被執(zhí)行。這樣的死亡exit通常存在于緩存、配置文件等等不允許用戶直接訪問的文件當中。
base64decode繞過
利用filter協(xié)議來繞過,看下這樣的代碼:
<?php$content = '<?php exit; ?>';$content .= $_POST['txt'];file_put_contents($_POST['filename'], $content);當用戶通過POST方式提交一個數(shù)據(jù)時,會與死亡exit進行拼接,從而避免提交的數(shù)據(jù)被執(zhí)行。
然而這里可以利用php://filter的base64-decode方法,將$content解碼,利用php base64_decode函數(shù)特性去除死亡exit。
base64編碼中只包含64個可打印字符,當PHP遇到不可解碼的字符時,會選擇性的跳過,這個時候base64就相當于以下的過程:
<?php$_GET['txt'] = preg_replace('|[^a-z0-9A-Z+/]|s', '', $_GET['txt']);base64_decode($_GET['txt']);所以,當$content 包含 <?php exit; ?>時,解碼過程會先去除識別不了的字符,< ; ? >和空格等都將被去除,于是剩下的字符就只有phpexit以及我們傳入的字符了。由于base64是4個byte一組,再添加一個字符例如添加字符’a’后,將’phpexita’當做兩組base64進行解碼,也就繞過這個死亡exit了。
這個時候后面再加上編碼后的一句話木馬,就可以getshell了。
strip_tags繞過
這個<?php exit; ?>實際上是一個XML標簽,既然是XML標簽,我們就可以利用strip_tags函數(shù)去除它,而php://filter剛好是支持這個方法的。
但是我們要寫入的一句話木馬也是XML標簽,在用到strip_tags時也會被去除。
注意到在寫入文件的時候,filter是支持多個過濾器的。可以先將webshell經過base64編碼,strip_tags去除死亡exit之后,再通過base64-decode復原。
php://filter/string.strip_tags|convert.base64-decode/resource=shell.php更多繞過方法:file_put_content和死亡·雜糅代碼之緣
2 data://
數(shù)據(jù)流封裝器,以傳遞相應格式的數(shù)據(jù)。可以讓用戶來控制輸入流,當它與包含函數(shù)結合時,用戶輸入的data://流會被當作php文件執(zhí)行。
示例用法:
1、data://text/plain, http://127.0.0.1/include.php?file=data://text/plain,<?php%20phpinfo();?>2、data://text/plain;base64, http://127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b范例
Example #1 打印 data:// 的內容
<?php // 打印 "I love PHP" echo file_get_contents ( 'data://text/plain;base64,SSBsb3ZlIFBIUAo=' ); ?>Example #2 獲取媒體類型
<?php $fp = fopen ( 'data://text/plain;base64,' , 'r' ); $meta = stream_get_meta_data ( $fp );// 打印 "text/plain" echo $meta [ 'mediatype' ]; ?>3 file://
用于訪問本地文件系統(tǒng),并且不受allow_url_fopen,allow_url_include影響
file://協(xié)議主要用于訪問文件(絕對路徑、相對路徑以及網(wǎng)絡路徑)
比如:http://www.xx.com?file=file:///etc/passsword
4 php://
在allow_url_fopen,allow_url_include都關閉的情況下可以正常使用
php://作用為訪問輸入輸出流
5 php://input
php://input可以訪問請求的原始數(shù)據(jù)的只讀流,將post請求的數(shù)據(jù)當作php代碼執(zhí)行。當傳入的參數(shù)作為文件名打開時,可以將參數(shù)設為php://input,同時post想設置的文件內容,php執(zhí)行時會將post內容當作文件內容。從而導致任意代碼執(zhí)行。
例如:
http://127.0.0.1/cmd.php?cmd=php://input
POST數(shù)據(jù):<?php phpinfo()?>
注意:
當enctype="multipart/form-data"的時候 php://input` 是無效的
遇到file_get_contents()要想到用php://input繞過。
6 zip://
zip:// 可以訪問壓縮包里面的文件。當它與包含函數(shù)結合時,zip://流會被當作php文件執(zhí)行。從而實現(xiàn)任意代碼執(zhí)行。
zip://中只能傳入絕對路徑。 要用#分隔壓縮包和壓縮包里的內容,并且#要用url編碼%23(即下述POC中#要用%23替換) 只需要是zip的壓縮包即可,后綴名可以任意更改。 相同的類型的還有zlib://和bzip2://參考鏈接:
php偽協(xié)議實現(xiàn)命令執(zhí)行的七種姿勢
PHP偽協(xié)議總結
總結
- 上一篇: 1 100的奇数和编程php,用PHP求
- 下一篇: oracle instant imp,使