High severityNVD Advisory· Published Nov 6, 2024· Updated Nov 21, 2024
Command execution hijack on Windows with Process class in symfony/process
CVE-2024-51736
Description
Symphony process is a module for the Symphony PHP framework which executes commands in sub-processes. On Windows, when an executable file named cmd.exe is located in the current working directory it will be called by the Process class when preparing command arguments, leading to possible hijacking. This issue has been addressed in release versions 5.4.46, 6.4.14, and 7.1.7. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
symfony/processPackagist | < 5.4.46 | 5.4.46 |
symfony/processPackagist | >= 6.0.0, < 6.4.14 | 6.4.14 |
symfony/processPackagist | >= 7.0.0, < 7.1.7 | 7.1.7 |
symfony/symfonyPackagist | < 5.4.46 | 5.4.46 |
symfony/symfonyPackagist | >= 6.0.0, < 6.4.14 | 6.4.14 |
symfony/symfonyPackagist | >= 7.0.0, < 7.1.7 | 7.1.7 |
Affected products
1- Range: < 5.4.46
Patches
118ecd03eda39[Process] Use %PATH% before %CD% to load the shell on Windows
3 files changed · +18 −20
src/Symfony/Component/Process/ExecutableFinder.php+8 −6 modified@@ -19,7 +19,6 @@ */ class ExecutableFinder { - private $suffixes = ['.exe', '.bat', '.cmd', '.com']; private const CMD_BUILTINS = [ 'assoc', 'break', 'call', 'cd', 'chdir', 'cls', 'color', 'copy', 'date', 'del', 'dir', 'echo', 'endlocal', 'erase', 'exit', 'for', 'ftype', 'goto', @@ -28,6 +27,8 @@ class ExecutableFinder 'setlocal', 'shift', 'start', 'time', 'title', 'type', 'ver', 'vol', ]; + private $suffixes = []; + /** * Replaces default suffixes of executable. */ @@ -65,11 +66,13 @@ public function find(string $name, ?string $default = null, array $extraDirs = [ $extraDirs ); - $suffixes = ['']; + $suffixes = []; if ('\\' === \DIRECTORY_SEPARATOR) { $pathExt = getenv('PATHEXT'); - $suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes); + $suffixes = $this->suffixes; + $suffixes = array_merge($suffixes, $pathExt ? explode(\PATH_SEPARATOR, $pathExt) : ['.exe', '.bat', '.cmd', '.com']); } + $suffixes = '' !== pathinfo($name, PATHINFO_EXTENSION) ? array_merge([''], $suffixes) : array_merge($suffixes, ['']); foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { if ('' === $dir) { @@ -85,12 +88,11 @@ public function find(string $name, ?string $default = null, array $extraDirs = [ } } - if (!\function_exists('exec') || \strlen($name) !== strcspn($name, '/'.\DIRECTORY_SEPARATOR)) { + if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('exec') || \strlen($name) !== strcspn($name, '/'.\DIRECTORY_SEPARATOR)) { return $default; } - $command = '\\' === \DIRECTORY_SEPARATOR ? 'where %s 2> NUL' : 'command -v -- %s'; - $execResult = exec(\sprintf($command, escapeshellarg($name))); + $execResult = exec('command -v -- '.escapeshellarg($name)); if (($executablePath = substr($execResult, 0, strpos($execResult, \PHP_EOL) ?: null)) && @is_executable($executablePath)) { return $executablePath;
src/Symfony/Component/Process/PhpExecutableFinder.php+2 −13 modified@@ -34,19 +34,8 @@ public function __construct() public function find(bool $includeArgs = true) { if ($php = getenv('PHP_BINARY')) { - if (!is_executable($php)) { - if (!\function_exists('exec') || \strlen($php) !== strcspn($php, '/'.\DIRECTORY_SEPARATOR)) { - return false; - } - - $command = '\\' === \DIRECTORY_SEPARATOR ? 'where %s 2> NUL' : 'command -v -- %s'; - $execResult = exec(\sprintf($command, escapeshellarg($php))); - if (!$php = substr($execResult, 0, strpos($execResult, \PHP_EOL) ?: null)) { - return false; - } - if (!is_executable($php)) { - return false; - } + if (!is_executable($php) && !$php = $this->executableFinder->find($php)) { + return false; } if (@is_dir($php)) {
src/Symfony/Component/Process/Process.php+8 −1 modified@@ -1592,7 +1592,14 @@ function ($m) use (&$env, &$varCache, &$varCount, $uid) { $cmd ); - $cmd = 'cmd /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')'; + static $comSpec; + + if (!$comSpec && $comSpec = (new ExecutableFinder())->find('cmd.exe')) { + // Escape according to CommandLineToArgvW rules + $comSpec = '"'.preg_replace('{(\\\\*+)"}', '$1$1\"', $comSpec) .'"'; + } + + $cmd = ($comSpec ?? 'cmd').' /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')'; foreach ($this->processPipes->getFiles() as $offset => $filename) { $cmd .= ' '.$offset.'>"'.$filename.'"'; }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-qq5c-677p-737qghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-51736ghsaADVISORY
- github.com/FriendsOfPHP/security-advisories/blob/master/symfony/process/CVE-2024-51736.yamlghsaWEB
- github.com/FriendsOfPHP/security-advisories/blob/master/symfony/symfony/CVE-2024-51736.yamlghsaWEB
- github.com/symfony/symfony/commit/18ecd03eda3917fdf901a48e72518f911c64a1c9ghsaWEB
- github.com/symfony/symfony/security/advisories/GHSA-qq5c-677p-737qghsax_refsource_CONFIRMx_refsource_MISCWEB
- symfony.com/cve-2024-51736ghsaWEB
News mentions
0No linked articles in our index yet.