VYPR
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.

PackageAffected versionsPatched versions
symfony/processPackagist
< 5.4.465.4.46
symfony/processPackagist
>= 6.0.0, < 6.4.146.4.14
symfony/processPackagist
>= 7.0.0, < 7.1.77.1.7
symfony/symfonyPackagist
< 5.4.465.4.46
symfony/symfonyPackagist
>= 6.0.0, < 6.4.146.4.14
symfony/symfonyPackagist
>= 7.0.0, < 7.1.77.1.7

Affected products

1

Patches

1
18ecd03eda39

[Process] Use %PATH% before %CD% to load the shell on Windows

https://github.com/symfony/symfonyNicolas GrekasOct 28, 2024via ghsa
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

News mentions

0

No linked articles in our index yet.