文件包含漏洞與PHP偽協議


PHP中支持的偽協議

file:// — 訪問本地文件系統
http:// — 訪問 HTTP(s) 網址
ftp:// — 訪問 FTP(s) URLs
php:// — 訪問各個輸入/輸出流(I/O streams)
zlib:// — 壓縮流
data:// — 數據(RFC 2397)
glob:// — 查找匹配的文件路徑模式
phar:// — PHP 歸檔
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音頻流
expect:// — 處理交互式的流

 file://協議

 PHP.ini:
file:// 協議在雙off的情況下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on

file:// 用於訪問本地文件系統,在CTF中通常用來讀取本地文件的且不受allow_url_fopen與allow_url_include的影響
filebh.php

<?php
if(isset($_GET['page']))
{
    include $_GET['page'];
}
?>

  file:// [文件的絕對路徑和文件名]
 

php://協議

php://filter在雙off的情況下也可以正常使用;
條件:
不需要開啟allow_url_fopen,僅php://input、 php://stdin、 php://memory 和 php://temp 需要開啟allow_url_include。

php:// 訪問各個輸入/輸出流(I/O streams),在CTF中經常使用的是php://filter和php://input,php://filter用於讀取源碼,php://input用於執行php代碼。

php://filter

php://filter 是一種元封裝器, 設計用於數據流打開時的篩選過濾應用。 這對於一體式(all-in-one)的文件函數非常有用,類似 readfile()、 file() 和 file_get_contents(), 在數據流內容讀取之前沒有機會應用其他過濾器。

resource=<要過濾的數據流>     這個參數是必須的。它指定了你要篩選過濾的數據流。
read=<讀鏈的篩選列表>         該參數可選。可以設定一個或多個過濾器名稱,以管道符(|)分隔。
write=<寫鏈的篩選列表>    該參數可選。可以設定一個或多個過濾器名稱,以管道符(|)分隔。
<;兩個鏈的篩選列表>        任何沒有以 read= 或 write= 作前綴 的篩選器列表會視情況應用於讀或寫鏈。

可以運用多種過濾器(字符串/轉換/壓縮/加密)
例如平時我們用來任意文件讀取的payload

php://filter/read=convert.base64-encode/resource=upload.php 這里讀的過濾器為convert.base64-encode,就和字面上的意思一樣,把輸入流base64-encode。 resource=upload.php,代表讀取upload.php的內容 

這樣就可以以base64編碼的方式讀取文件源代碼

過濾器

過濾器有很多種,有字符串過濾器、轉換過濾器、壓縮過濾器、加密過濾器
<字符串過濾器>
 

string.rot13
進行rot13轉換
string.toupper
將字符全部大寫
string.tolower
將字符全部小寫
string.strip_tags
去除空字符、HTML 和 PHP 標記后的結果。
功能類似於strip_tags()函數,若不想某些字符不被消除,后面跟上字符,可利用字符串或是數組兩種方式

舉例  

<?php
    $fp = fopen('php://output', 'w');
    stream_filter_append($fp, 'string.rot13');
    echo "rot13:";
    fwrite($fp, "This is a test.\n");
    fclose($fp);
    echo "<br>";

    $fp = fopen('php://output', 'w');
    stream_filter_append($fp, 'string.toupper');
    echo "Upper:";
    fwrite($fp, "This is a test.\n");
    fclose($fp);
    echo "<br>";

    $fp = fopen('php://output', 'w');
    stream_filter_append($fp, 'string.tolower');
    echo "Lower:";
    fwrite($fp, "This is a test.\n");
    fclose($fp);
    echo "<br>";

    $fp = fopen('php://output', 'w');
    echo "Del1:";
    stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE);
    fwrite($fp, "<b>This is a test.</b>!!!!<h1>~~~~</h1>\n");
    fclose($fp);
    echo "<br>";

    $fp = fopen('php://output', 'w');
    echo "Del2:";
    stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, "<b>");
    fwrite($fp, "<b>This is a test.</b>!!!!<h1>~~~~</h1>\n");
    fclose($fp);
    echo "<br>";

    $fp = fopen('php://output', 'w');
    stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, array('b','h1'));
    echo "Del3:";
    fwrite($fp, "<b>This is a test.</b>!!!!<h1>~~~~</h1>\n");
    fclose($fp);
?>

實例模擬

<?php  
$filename=$_GET["a"];  
$data="test test";  
file_put_contents($filename, $data);  
?>  

 PHP file_put_contents() 函數

payload=http://127.0.0.1/xxx.php?a=php://filter/write=string.tolower/resource=test.php

 可以往服務器中寫入一個文件內容全為小寫且文件名為test.php的文件:

 

xxx.php

<?php  
$filename=$_GET["a"];  
echo file_get_contents($filename);  
?>  

 PHP file_get_contents() 函數

 ile_get_contents()的$filename參數不僅僅為文件路徑,還可以是一個URL(偽協議)。

payload=http://127.0.0.1/xxx.php?a=php://filter/convert.base64-encode/resource=test.php

  test.php的內容以base64編碼的方式顯示出來

 

 xxx.php

<?php  
$filename=$_GET['a'];
$data="test test";
include("$filename");
?>

 

payload=http://127.0.0.1/xxx.php?a=php://filter/convert.base64-encode/resource=test.php

 

同樣可以把test.php的內容以base64編碼的方式顯示出來

雙引號包含的變量$filename會被當作正常變量執行,而單引號包含的變量則會被當作字符串執行。

php://input

 php://input 是個可以訪問請求的原始數據的只讀流,可以讀取到post沒有解析的原始數據, 將post請求中的數據作為PHP代碼執行。因為它不依賴於特定的 php.ini 指令。
注:enctype=”multipart/form-data” 的時候 php://input 是無效的。

allow_url_fopen :off/on
allow_url_include:on

 xxx.php

<?php  
echo file_get_contents($_GET["a"]);  
?>  

 

 

 但是當PHP代碼為:

<?php  
$test=$_GET['a'];
include($test);
?>    

  

 並且當遠程包含打開的時候(allow_url_include=on),就可以造成任意代碼執行。
 

zip://, bzip2://, zlib://協議

zip://, bzip2://, zlib://協議

PHP.ini:
zip://, bzip2://, zlib://協議在雙off的情況下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on

3個封裝協議,都是直接打開壓縮文件。
compress.zlib://file.gz - 處理的是 '.gz' 后綴的壓縮包
compress.bzip2://file.bz2 - 處理的是 '.bz2' 后綴的壓縮包
zip://archive.zip#dir/file.txt - 處理的是 '.zip' 后綴的壓縮包里的文件

 

zip://, bzip2://, zlib:// 均屬於壓縮流,可以訪問壓縮文件中的子文件,更重要的是不需要指定后綴名。

zip://協議

php 版本大於等於 php5.3.0
使用方法:
zip://archive.zip#dir/file.txt
zip:// [壓縮文件絕對路徑]#[壓縮文件內的子文件名]**
要用絕對路徑+url編碼#

測試:
新建一個名為zip.txt的文件,內容為<?php phpinfo();?>,然后壓縮為名為test.zip的zip文件。如果可以上傳zip文件則上傳zip文件,若不能則重命名為test.jpg后上傳其他幾種壓縮格式也可以這樣操

作。

 

 更名為jpg
payload:http://127.0.0.1/xxx.php?a=zip://C:\Users\liuxianglai\Desktop\test.jpg%23zip.txt

 

 

 

小結:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM