CVE-2022-31625
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 pgsql extension connects PHP applications to PostgreSQL databases.
A Memory Corruption vulnerability (CVE-2022-31625) has been identified in pg_query_params() and related functions of PHP's pgsql extension, which allows an attacker who can pass a query parameter that cannot be converted to a string to make PHP free pointers it never initialized, which can corrupt memory and, according to the CVE record, lead to remote code execution or a denial of service. PHP tracks this issue as bug #81720.
Per MITRE CWE-590: The product calls free() on a pointer to memory that was not allocated using associated heap allocation functions such as malloc(), calloc(), or realloc().
This issue affects PHP 7.4 before 7.4.30, PHP 8.0 before 8.0.20 and PHP 8.1 before 8.1.7. HeroDevs' analysis found that the End-of-Life PHP 5.6 and 7.2 release lines contain the faulty cleanup code but cannot reach it; NES for PHP carries the fix on those lines so that their code matches upstream.
Details
Module Info
- Product: PHP
- Affected packages:
php-src(ext/pgsql) - Affected versions: >=7.4.0 <7.4.30, >=8.0.0 <8.0.20, >=8.1.0 <8.1.7
- GitHub repository: https://github.com/php/php-src
- Published packages: https://www.php.net/downloads
- Package manager: N/A
- Fixed in:
- OSS PHP 7.4.30, 8.0.20, 8.1.7
- NES for PHP 5.6.1 (based on PHP 5.6.40)
- NES for PHP 7.2.1 (based on PHP 7.2.34)
Vulnerability Info
This High-severity vulnerability is found in the pgsql extension of PHP 7.4 before 7.4.30, 8.0 before 8.0.20 and 8.1 before 8.1.7. The PHP project scores it 8.1 under CVSS 3.1 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H) and classifies it as CWE-590 (free of memory not on the heap) and CWE-824 (access of uninitialized pointer).
pg_query_params() sends a query with separate parameter values, the way prepared statements do. PHP allocates an array of string pointers, one per parameter, with safe_emalloc(), which does not initialize it, then converts each parameter to a string and stores a copy. If a conversion fails, it frees the parameters and returns false. In PHP 7.4.29 the loop body reads:
ZVAL_COPY(&tmp_val, tmp);
convert_to_cstring(&tmp_val);
if (Z_TYPE(tmp_val) != IS_STRING) {
php_error_docref(NULL, E_WARNING,"Error converting parameter");
zval_ptr_dtor(&tmp_val);
_php_pgsql_free_params(params, num_params);
RETURN_FALSE;
}
params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));The cleanup frees all num_params entries, but only the first i have been set; the rest hold whatever was in that memory before. Freeing those values as pointers can corrupt PHP's heap. The upstream fix describes the bug as leading to remote code execution, and the CVE record warns that it could lead to remote code execution or a denial of service.
Exploitation needs an application that passes attacker-influenced values to pg_query_params() (or the related send functions) that cannot be converted to a string, such as an object without a __toString() method. This works in any SAPI with the pgsql extension loaded; applications using other database drivers are not affected. HeroDevs' analysis found that on PHP 5.6 and 7.2 the conversion always produces a string (an object without __toString() raises a recoverable error and becomes "Object"), so the faulty error path is not reached on those lines. NES for PHP 5.6 and 7.2 include the fix so that the code matches upstream.
The fix frees only the parameters converted so far:
_php_pgsql_free_params(params, i);Mitigation
The PHP project publishes security fixes only for its supported release lines. Every affected release line received an upstream fix before it reached End-of-Life.
Users of the affected components should apply one of the following mitigations:
- Upgrade to PHP 7.4.30, 8.0.20, 8.1.7, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- Charles Fol (finder)
- Christoph M. Becker (remediation)