CVE-2025-1735
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 and PDO_PgSQL extensions connect PHP to PostgreSQL through the libpq client library, and provide escaping functions such as pg_escape_string() and PDO::quote() for building queries.
A SQL Injection vulnerability (CVE-2025-1735) has been identified in the escaping code of PHP's pgsql and PDO_PgSQL extensions, which ignores the errors that libpq reports, so that an attacker who can supply a string that is invalid in the connection's character encoding may get an improperly escaped value into a query, or crash the PHP process. PHP tracks this issue as GHSA-hrwm-9436-5mv3.
Per OWASP: A SQL injection attack consists of insertion or "injection" of a SQL query via the input data from the client to the application. A successful SQL injection exploit can read sensitive data from the database, modify database data (Insert/Update/Delete), execute administration operations on the database (such as shutdown the DBMS), recover the content of a given file present on the DBMS file system and in some cases issue commands to the operating system.
This issue affects all versions of PHP before 8.1.33, PHP 8.2 before 8.2.29, PHP 8.3 before 8.3.23 and PHP 8.4 before 8.4.10, which includes every End-of-Life release line from PHP 5.6 through 8.0, each up to its final release.
Details
Module Info
- Product: PHP
- Affected packages:
php-src(ext/pgsql,ext/pdo_pgsql) - Affected versions: <8.1.33, >=8.2.0 <8.2.29, >=8.3.0 <8.3.23, >=8.4.0 <8.4.10
- GitHub repository: https://github.com/php/php-src
- Published packages: https://www.php.net/downloads
- Package manager: N/A
- Fixed in:
- OSS PHP 8.1.33, 8.2.29, 8.3.23, 8.4.10
- NES for PHP 5.6.1 (based on PHP 5.6.40)
- NES for PHP 7.2.1 (based on PHP 7.2.34)
- NES for PHP 7.4.1 (based on PHP 7.4.33)
Vulnerability Info
This Medium-severity vulnerability is found in the pgsql and PDO_PgSQL extensions of all PHP versions before 8.1.33, 8.2 before 8.2.29, 8.3 before 8.3.23 and 8.4 before 8.4.10, including every End-of-Life release line from PHP 5.6 through 8.0, which never received the upstream fix. The PHP project scores it 5.9 under CVSS 3.1 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H), and the CVE record lists both SQL injection (CWE-89) and NULL pointer dereference (CWE-476).
PHP escapes strings for PostgreSQL with libpq's PQescapeStringConn(), PQescapeIdentifier() and PQescapeByteaConn(). PQescapeStringConn() reports a problem, such as a byte sequence that is invalid in the connection's encoding, through an error parameter, but PHP did not pass that parameter, so it could not see the error. According to HeroDevs' analysis, libpq still writes a malformed result in that case, and PHP used it in the query. PQescapeIdentifier() and PQescapeByteaConn() return NULL on error, and several PHP call sites used the result without checking it.
The advisory traces the issue to the PostgreSQL report that became CVE-2025-1094, which a reporter demonstrated through PHP. An improperly escaped value can let attacker input change the meaning of a query, and a NULL result, for example from pg_insert() with a table name that cannot be escaped, crashes the process. The PostgreSQL project now makes invalidly encoded strings fail on the server, but its maintainers note that this may not be sufficient, depending on how the escaped value is used.
Exploitation needs an application that passes attacker-supplied strings to pg_escape_string(), pg_escape_bytea(), the pg_insert(), pg_update(), pg_delete(), pg_select() or pg_convert() helpers, or to PDO::quote() and emulated prepares on a PostgreSQL connection with a multibyte encoding, under any server API. HeroDevs' analysis notes that libpq reports these errors only since its own CVE-2025-1094 fix (PostgreSQL 13.19, 14.16, 15.11, 16.7, 17.3 and vendor backports); with an older libpq the escaping weakness lies in libpq itself. Applications that use native prepared statements with bound parameters do not rely on these escaping functions.
The fix checks every escape for an error. PDO::quote() and emulated prepares fail, pg_escape_string() and pg_escape_bytea() throw an exception, and the insert, update, delete, select and convert helpers fail with a warning or notice. The PDO_PgSQL quoter now reads:
default:
quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3);
quoted[0] = '\'';
quotedlen = PQescapeStringConn(H->server, quoted + 1, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), &err);
if (err) {
efree(quoted);
return NULL;
}
quoted[quotedlen + 1] = '\'';
quoted[quotedlen + 2] = '\0';
quotedlen += 2;Mitigation
The PHP project publishes security fixes only for its supported release lines. PHP 5.6, 7.0, 7.1, 7.2, 7.3, 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, use prepared statements with bound parameters instead of the escaping functions, and keep libpq updated to a release that includes the CVE-2025-1094 fix.
Users of the affected components should apply one of the following mitigations:
- Upgrade to PHP 8.1.33, 8.2.29, 8.3.23, 8.4.10, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- Andres Freund (finder)
- Jakub Zelenka (remediation)