CVE-2019-11048
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.
A Denial of Service (DoS) vulnerability (CVE-2019-11048) has been identified in PHP's multipart/form-data request parser (main/rfc1867.c), which allows a remote attacker who can send a very large file upload request to make PHP abort the request without deleting the temporary files it has already written, so that repeated requests can fill the server's disk. PHP tracks this issue as bug #78875 and bug #78876.
Per MITRE CWE-400: The product does not properly control the allocation and maintenance of a limited resource.
This issue affects all versions of PHP before 7.2.31, PHP 7.3 before 7.3.18 and PHP 7.4 before 7.4.6, which includes the End-of-Life release lines PHP 5.6, 7.0 and 7.1 through their final releases (5.6.40, 7.0.33 and 7.1.33).
Details
Module Info
- Product: PHP
- Affected packages:
php-src(main/rfc1867.c) - Affected versions: <7.2.31, >=7.3.0 <7.3.18, >=7.4.0 <7.4.6
- GitHub repository: https://github.com/php/php-src
- Published packages: https://www.php.net/downloads
- Package manager: N/A
- Fixed in:
- OSS PHP 7.2.31, 7.3.18, 7.4.6
- NES for PHP 5.6.1 (based on PHP 5.6.40)
Vulnerability Info
This Medium-severity vulnerability is found in the request body parser of all versions of PHP before 7.2.31, PHP 7.3 before 7.3.18 and PHP 7.4 before 7.4.6, including the End-of-Life PHP 5.6, 7.0 and 7.1 release lines, which never received the upstream fix. The PHP project scores it 5.3 under CVSS 3.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L).
When a request arrives with a multipart/form-data body, PHP parses it before the script runs: ordinary fields go into $_POST, and each uploaded file is written to a temporary file and described in $_FILES. The parser kept several lengths in signed int variables. For an upload field with an array-style name such as file[...], PHP 5.6.40 computes:
is_arr_upload = (start_arr = strchr(param,'[')) && (param[strlen(param)-1] == ']');
if (is_arr_upload) {
array_len = strlen(start_arr);
if (array_index) {
efree(array_index);
}
array_index = estrndup(start_arr + 1, array_len - 2);
}array_len is an int, so a field name of 2 GiB or more wraps to a negative value, and estrndup() is then asked for an enormous allocation. The companion bug is the same mistake for ordinary form fields: multipart_buffer_read_body() sums the bytes of a field value in an int, which wraps for a value of 2 GiB or more. In both cases PHP hits memory_limit and stops processing the request. Because the temporary files of uploads processed earlier in the same request have not yet been registered for cleanup, they are left on disk.
A remote, unauthenticated attacker can repeat such requests to accumulate stale temporary files and exhaust disk space on the server. HeroDevs' analysis notes that the body is parsed before any script runs, under any SAPI that accepts POST bodies, so the application code does not matter. The attack needs post_max_size to allow a request body of more than 2 GiB; servers that keep post_max_size below that limit are not exposed, and with file_uploads disabled no temporary files are written that could be left behind.
The fix declares these lengths as size_t, so they no longer wrap, and the oversized allocation and the abandoned temporary files no longer occur.
Mitigation
The PHP project publishes security fixes only for its supported release lines. PHP 5.6, 7.0 and 7.1 are End-of-Life and will not receive any public updates to address this issue.
Until an upgrade is possible, keep post_max_size well below 2 GiB, or set file_uploads to Off where uploads are not needed so that no temporary files are created.
Users of the affected components should apply one of the following mitigations:
- Upgrade to PHP 7.2.31, 7.3.18, 7.4.6, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- jr (coredu.mp) (finder)
- Christoph M. Becker (remediation)