0 %ˆl–äY>” Šn-jq@¹q Üiõ1hßÅ …iÆÝi¿ÄÀÇ?÷ // path with an attacker-computable md5 marker as the sole reuse gate // allowed a local user to pre-plant the directory (cache poisoning of // bin/cli.php) or plant symlinks the extraction would write through. // A fresh random 0700 directory per run, verified to be a real // directory we own and not a symlink, closes that TOCTOU window. // // The parent ($base) is per-euid (e.g. /tmp/pharextract-0 for root) // and 0700 owned by the current user, so an unprivileged attacker // cannot rename or replace entries inside it after creation. // // posix_geteuid is required: without it $euid would silently collapse // to 0 for every caller AND isOwnedDir would skip the ownership // comparison, letting an attacker who pre-creates the base dir pass // the trust check trivially. There is no safe fallback — hard-fail. if (!function_exists('posix_geteuid')) { die('posix_geteuid is required for safe phar extraction (PHP built without --enable-posix?)'); } $euid = posix_geteuid(); $base = $temp . '/pharextract-' . $euid; @mkdir($base, 0700); if (!self::isOwnedDir($base)) { die('Refusing to use untrusted pharextract base directory'); } $temp = self::makePrivateTempDir($base, basename(__FILE__, '.phar')); if ($temp === false) { die('Could not create a private temporary directory to extract phar'); } self::$temp = $temp; self::$origdir = getcwd(); foreach ($info['m'] as $path => $file) { // Defense in depth: even with a per-euid 0700 $base, re-verify // the extraction root is still our owne