CVE-2024-5585

Command Injection
Affects
PHP
in
PHP
No items found.
Versions
>=7.4.0 <8.1.29, >=8.2.0 <8.2.20, >=8.3.0 <8.3.8 (Windows only)

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

PHP is a general-purpose scripting language used mostly for web development. It runs behind web servers through server APIs such as Apache mod_php and PHP-FPM, and powers content management systems and frameworks such as WordPress, Drupal, Moodle and Laravel. Its proc_open() function starts a process and, since PHP 7.4, accepts the command as an array of program name and arguments, which PHP is meant to pass on without shell interpretation.

A Command Injection vulnerability (CVE-2024-5585) has been identified in the Windows implementation of PHP's proc_open() function, which allows an attacker who controls the arguments of a batch file launched with the array syntax to run arbitrary commands, when the program name ends in a space or a dot. The issue bypasses the fix for CVE-2024-1874. PHP tracks this issue as GHSA-9fcc-425m-g385.

Per OWASP: Command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In this attack, the attacker-supplied operating system commands are usually executed with the privileges of the vulnerable application.

This issue affects PHP on Windows: PHP 7.4.0 and later before 8.1.29, PHP 8.2 before 8.2.20 and PHP 8.3 before 8.3.8, which includes the End-of-Life PHP 7.4 and 8.0 release lines through their final releases (7.4.33 and 8.0.30).

Details

Module Info

Vulnerability Info

This High-severity vulnerability is found in the Windows builds of PHP 7.4.0 and later before 8.1.29, 8.2 before 8.2.20 and 8.3 before 8.3.8, including the End-of-Life PHP 7.4 and 8.0 release lines, which never received the upstream fix. The PHP project scores it 7.7 under CVSS 3.1 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L).

On Windows, a .bat or .cmd file always runs through cmd.exe, which interprets characters such as &, | and % in its arguments. CVE-2024-1874 showed that proc_open() did not escape arguments for cmd.exe in that case. Its fix added a check that decides whether the program will run through cmd.exe by looking at the extension of the program name, and escapes the arguments only then. In PHP 8.1.28 the check ends with:

if (extension == NULL || extension == prog_name) {
    /* No file extension found, it is not batch file. */
    return false;
}

/* Check if the file extension is ".bat" or ".cmd" which is always executed by cmd.exe. */
return _stricmp(extension, ".bat") == 0 || _stricmp(extension, ".cmd") == 0;

Windows strips trailing spaces and dots from a program name before it starts the program, so x.bat followed by a space, or x.bat., still runs the batch file through cmd.exe, but the string comparison no longer sees a .bat or .cmd extension. The arguments are then passed without the extra escaping, and an attacker who controls them can inject commands that cmd.exe runs with the privileges of the PHP process. On PHP 7.4, which never received the CVE-2024-1874 fix upstream, the arguments of batch files are not escaped for cmd.exe at all.

Exploitation needs a Windows build of PHP and an application that launches a batch file through proc_open() with the array syntax, passes attacker-controlled arguments, and lets the program name end in a space or a dot. Linux and other Unix builds are not affected, because there proc_open() hands the argument array directly to execvp() without a shell and all of the changed code is Windows-only. HeroDevs' release notes for NES for PHP 7.4.1 state that this fix is carried for Windows builds.

The fix resolves the program name the way Windows does, with GetLongPathNameW() and GetFullPathNameW(), before it checks the extension, so trailing spaces and dots no longer hide a batch file:

bool uses_cmd = false;
if (_wcsicmp(file_part, L"cmd.exe") == 0 || _wcsicmp(file_part, L"cmd") == 0) {
    uses_cmd = true;
} else {
    const WCHAR *extension_dot = wcsrchr(file_part, L'.');
    if (extension_dot && (_wcsicmp(extension_dot, L".bat") == 0 || _wcsicmp(extension_dot, L".cmd") == 0)) {
        uses_cmd = true;
    }
}

Mitigation

The PHP project publishes security fixes only for its supported release lines. PHP 7.4 and 8.0 are End-of-Life and will not receive any public updates to address this issue.

Until an upgrade is possible, do not launch batch files through proc_open() with arguments derived from user input on Windows, and do not let user input influence the program name.

Users of the affected components should apply one of the following mitigations:

  • Upgrade to PHP 8.1.29, 8.2.20, 8.3.8, or later.
  • Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.

Credits

Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2024-5585
PROJECT Affected
PHP
Versions Affected
>=7.4.0 <8.1.29, >=8.2.0 <8.2.20, >=8.3.0 <8.3.8 (Windows only)
NES Versions Affected
Published date
June 9, 2024
≈ Fix date
June 6, 2024
Fixed in
Category
Command Injection
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
PHP
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.