← Back to Feed CACHED · 2026-07-31 05:56:44 · CACHE_KEY CVE-2026-17543
CVE-2026-17543 · CWE-89 · Disclosed 2026-07-30

Improper escaping of backslashes in attacker-provided parameters would

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Like a door that locks perfectly — unless you use the side entrance, which was never actually wired to the deadbolt

CVE-2026-17543 is a SQL injection in PHP's ext-pgsql extension, specifically in php_pgsql_convert(), the internal function behind pg_insert(), pg_update(), pg_select(), and pg_delete(). When PostgreSQL runs with standard_conforming_strings = on (the default since PostgreSQL 9.1), PQescapeStringConn() does not escape backslashes. But php_pgsql_convert() wraps results in escape-string constants (E'...'), where backslashes *are* significant. An attacker sends zzz\' OR 1=1 -- as a parameter value; the function doubles the quote to '' but leaves the backslash, so the \' becomes a literal quote character followed by a string-terminating quote — classic second-order escaping mismatch. Affected versions span PHP 8.2 before 8.2.33, 8.3 before 8.3.33, 8.4 before 8.4.24, and 8.5 before 8.5.9.

There is no vendor CVSS score to compare against. GitHub's GHSA advisory rates this High, which aligns with the technical reality: when conditions are met (app uses the specific pg_* convenience functions with user input), exploitation is trivial and unauthenticated, with a complete PoC in the advisory itself. However, these convenience functions are niche — the vast majority of PHP+PostgreSQL applications use PDO, pg_query_params(), or ORM query builders. The affected population is a narrow slice of a narrow slice (PHP + PostgreSQL + legacy convenience functions + user-controlled input), which significantly limits real-world exposure even though the bug itself is textbook-critical.

"Trivial SQLi in PHP pgsql convenience functions; narrow exposure but devastating when hit"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify PHP+PostgreSQL target using pg_* convenience functions

Attacker identifies a web application running PHP with PostgreSQL and using pg_select(), pg_insert(), pg_update(), or pg_delete() to handle user input. This is detectable through error message fingerprinting, technology stack enumeration (Wappalyzer, response headers), or blind parameter fuzzing with backslash payloads.
Conditions required:
  • Target runs PHP 8.2–8.5 in an affected version range
  • Application uses ext-pgsql convenience functions (not PDO or pg_query_params)
  • User-controlled input reaches one of the four affected function calls
Where this breaks in practice:
  • Most PHP+PostgreSQL apps use PDO or parameterized queries, not pg_select/pg_insert/pg_update/pg_delete
  • PostgreSQL is used by roughly 10-15% of PHP deployments; MySQL/MariaDB dominates
  • Modern frameworks (Laravel, Symfony, CakePHP) do not use these functions
Detection/coverage: WAF rules for backslash+quote sequences in parameters can flag attempts. Standard SQLi detection signatures will catch most payloads.
STEP 02

Craft backslash-quote breakout payload

Attacker sends a parameter value containing \' OR 1=1 -- or equivalent. The php_pgsql_convert() function escapes the single quote by doubling it to '' but does not escape the preceding backslash. In the E'...' escape-string context, \' becomes a literal quote followed by a string terminator. The advisory provides a working PoC: pg_select($db, 'user', ['name' => "zzz\\' OR 1=1 --"]). No special tooling required — curl or a browser suffices.
Conditions required:
  • Network access to the web application endpoint
Where this breaks in practice:
  • Input validation or WAF may block obvious SQLi payloads
  • Application may not expose the vulnerable parameter in a reachable route
Detection/coverage: Standard SQLi WAF rules, OWASP ModSecurity CRS rule 942100+ will catch OR 1=1 patterns. SIEM correlation on database error logs.
STEP 03

Execute arbitrary SQL against PostgreSQL backend

With the string context broken, the attacker's injected SQL executes with the privileges of the PHP application's database user. This typically allows SELECT across all tables the app user can access, INSERT/UPDATE/DELETE for data manipulation, and potentially COPY TO for file read or CREATE FUNCTION for code execution if the DB user has elevated privileges. The blast radius is the entire database accessible to that connection.
Conditions required:
  • SQLi payload successfully breaks string context
  • Database user has standard application-level privileges
Where this breaks in practice:
  • Database user may be restricted to specific schemas/tables
  • PostgreSQL's default pg_hba.conf and role permissions limit lateral movement
  • Network segmentation may prevent direct database access from the compromised app
Detection/coverage: Database activity monitoring (DAM) tools detect anomalous queries. PostgreSQL log_statement = 'all' captures injected queries.
STEP 04

Data exfiltration or persistence

Attacker extracts sensitive data (credentials, PII, financial records) via the SQLi channel. If the database user has superuser or CREATEROLE privileges, the attacker can create backdoor accounts or use PostgreSQL's COPY command to write files to the server filesystem, potentially achieving code execution on the database host itself.
Conditions required:
  • Successful SQL injection from step 3
  • Database contains valuable data or elevated DB user privileges
Where this breaks in practice:
  • DLP controls may detect bulk data exfiltration
  • PostgreSQL superuser access is rare for application users
  • File write via COPY requires specific filesystem permissions
Detection/coverage: DLP, network monitoring for large data transfers, database audit logs.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo confirmed in-the-wild exploitation as of 2026-07-31. Not listed on CISA KEV.
Proof of ConceptPublic PoC in the GHSA advisory itself (GHSA-7qpv-r5mr-78m4). Trivial one-liner: pg_select($db, 'user', ['name' => "zzz\\' OR 1=1 --"]).
EPSS ScoreNot yet scored (CVE disclosed 2026-07-30, EPSS lags 24-72 hours for new CVEs).
KEV StatusNot listed as of 2026-07-31.
CVSS Vector (noisgate estimate)CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N — Network-accessible, no privileges, no user interaction, but high attack complexity due to prerequisite that app uses specific niche functions. High confidentiality and integrity impact.
Affected VersionsPHP <8.2.33, 8.3.x <8.3.33, 8.4.x <8.4.24, 8.5.x <8.5.9
Fixed VersionsPHP 8.2.33, 8.3.33 (2026-07-28), 8.4.24 (2026-07-29), 8.5.9. Distro backports expected within 1-2 weeks (Debian, Ubuntu, RHEL, SUSE).
Scanning / ExposureNo GreyNoise or Shodan tags observed yet. Exposure is application-layer (not detectable via port scan). W3Techs reports PHP at ~76% of server-side web, but PostgreSQL usage within PHP is ~10-15% (MySQL dominates), and pg_select/pg_insert usage is a small fraction of that.
Disclosure Date2026-07-30 (GHSA published). Patches released 2026-07-28/29.
ReporterNot attributed in GHSA advisory. PHP security team coordinated disclosure.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (7.5/10)

Assessed at HIGH because the single most decisive factor is the trivially exploitable, unauthenticated SQL injection with a public PoC, offset by the narrow reachable population (only applications using the niche pg_select/pg_insert/pg_update/pg_delete convenience functions with user-controlled input, a small minority of PHP+PostgreSQL deployments). The attack complexity prerequisite — requiring a specific, uncommon code pattern — prevents CRITICAL despite the textbook severity of the SQLi itself.

HIGH Vulnerability mechanics and exploitability
MEDIUM Exposed population estimate (no authoritative usage data for pg_* convenience functions)
LOW In-the-wild exploitation status (CVE is <48 hours old)

Why this verdict

  • Trivial, unauthenticated SQLi with public PoC — the advisory itself contains a working one-liner. No authentication, no user interaction, no race condition. When the code pattern exists, exploitation is copy-paste.
  • Narrow reachable population — the vulnerability only fires in applications using pg_select(), pg_insert(), pg_update(), or pg_delete() with user-controlled input. Most PHP+PostgreSQL applications use PDO, pg_query_params(), or ORM query builders. This is a niche API within a minority database choice (PostgreSQL is ~10-15% of PHP database usage).
  • No authentication or privilege required — the attacker only needs HTTP access to a vulnerable endpoint. This is a pure remote, unauthenticated attack vector.
  • Role multiplier: PHP+PostgreSQL applications occupy a spectrum from low-value dev tools to production SaaS platforms handling PII/financial data. When the vulnerable code pattern exists in a production app backed by a database with sensitive data, the blast radius is full database compromise (confidentiality + integrity). However, PHP's ext-pgsql convenience functions are *not* canonically high-value-role components (they are not hypervisors, DCs, identity providers, etc.). The worst-case role is a production web application with regulated data — serious but contained to that application's database, not fleet-scale. This sets a HIGH floor, not CRITICAL.
  • PHP is ubiquitous but the intersection is small — PHP runs on millions of servers, but the chain of PHP → PostgreSQL → ext-pgsql (not PDO) → convenience functions → user input is a compounding narrowing filter. Each layer reduces the exposed population significantly.

Why not higher?

CRITICAL would require either active exploitation, a canonically high-value-role component (DC, hypervisor, IdP, kernel-mode agent), or a much broader reachable population. The vulnerability is in niche convenience functions that modern PHP frameworks do not use. The blast radius is limited to the individual application's database — not fleet-scale, domain-scale, or supply-chain-scale. The attack complexity is technically low but requires a specific uncommon code pattern to exist in the target.

Why not lower?

MEDIUM would undercount the risk because: (1) the SQLi is trivially exploitable with zero authentication and a public PoC published in the advisory itself, (2) PHP is the most widely deployed server-side language, so even a small percentage of vulnerable apps represents thousands of targets globally, and (3) successful exploitation yields full database read/write — not a partial information disclosure or DoS. The 48-hour-old disclosure with a public PoC creates an immediate exploitation window before patches propagate to distros and containers.

05 · Compensating Control

What to do — in priority order.

  1. Audit codebase for pg_select, pg_insert, pg_update, pg_delete usage — Run grep -rn 'pg_select\|pg_insert\|pg_update\|pg_delete' /path/to/app across all PHP codebases. If none are found, this CVE does not affect you. If found, prioritize those applications for patching within the noisgate HIGH mitigation SLA of 30 days.
  2. Deploy WAF rules blocking backslash-quote sequences — Add ModSecurity or cloud WAF rules to detect \' patterns in request parameters targeting affected endpoints. OWASP CRS rules 942100-942999 cover most SQLi patterns. Deploy within 30 days per noisgate mitigation SLA.
  3. Replace pg_* convenience functions with pg_query_params — Refactor affected code to use pg_query_params() with parameterized queries. This eliminates the vulnerability entirely regardless of PHP version. Example: replace pg_select($db, 'user', ['name' => $input]) with pg_query_params($db, 'SELECT * FROM "user" WHERE name = $1', [$input]).
  4. Restrict database user privileges — Ensure the PostgreSQL user used by PHP applications has minimum required permissions — no superuser, no CREATEROLE, limited to specific schemas. This limits blast radius if SQLi succeeds.
  5. Upgrade PHP to patched versions — Apply PHP 8.2.33, 8.3.33, 8.4.24, or 8.5.9. These are the definitive fix. Target remediation within 180 days per noisgate HIGH remediation SLA, but faster if your codebase grep confirms affected function usage.
What doesn't work
  • PostgreSQL standard_conforming_strings = off — while changing this setting would make PQescapeStringConn() escape backslashes, PostgreSQL has defaulted to on since 9.1 (2011) and changing it breaks other string handling. This is not a viable workaround.
  • Input validation rejecting backslashes — overly aggressive and will break legitimate inputs containing backslashes (file paths, escape sequences in user data). Too fragile for production.
  • Network-level IDS/IPS alone — the payload is a simple string parameter that blends with normal HTTP traffic. Signature-based network detection has high false-negative rates for SQLi without application-layer inspection.
06 · Verification

Crowdsourced verification payload.

Run on each PHP application server to check if the installed PHP version is vulnerable. Requires read access to the php binary. Execute as any user: bash check_cve_2026_17543.sh

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/bin/bash
# CVE-2026-17543 checker — PHP ext-pgsql SQL injection
# Run on PHP application servers. No special privileges needed.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

PHP_BIN=$(command -v php 2>/dev/null)
if [ -z "$PHP_BIN" ]; then
  echo "UNKNOWN — php binary not found in PATH"
  exit 2
fi

# Check if pgsql extension is loaded
HAS_PGSQL=$($PHP_BIN -m 2>/dev/null | grep -ci '^pgsql$')
if [ "$HAS_PGSQL" -eq 0 ]; then
  echo "PATCHED — ext-pgsql not loaded; CVE-2026-17543 does not apply"
  exit 0
fi

VERSION=$($PHP_BIN -r 'echo PHP_VERSION;' 2>/dev/null)
if [ -z "$VERSION" ]; then
  echo "UNKNOWN — could not determine PHP version"
  exit 2
fi

# Parse major.minor.patch
MAJOR=$(echo "$VERSION" | cut -d. -f1)
MINOR=$(echo "$VERSION" | cut -d. -f2)
PATCH=$(echo "$VERSION" | cut -d. -f3 | sed 's/[^0-9].*//')

VULN=0
if [ "$MAJOR" -eq 8 ]; then
  if [ "$MINOR" -eq 2 ] && [ "$PATCH" -lt 33 ]; then VULN=1; fi
  if [ "$MINOR" -eq 3 ] && [ "$PATCH" -lt 33 ]; then VULN=1; fi
  if [ "$MINOR" -eq 4 ] && [ "$PATCH" -lt 24 ]; then VULN=1; fi
  if [ "$MINOR" -eq 5 ] && [ "$PATCH" -lt 9 ]; then VULN=1; fi
fi

if [ "$VULN" -eq 1 ]; then
  echo "VULNERABLE — PHP $VERSION with ext-pgsql loaded (CVE-2026-17543)"
  exit 1
else
  echo "PATCHED — PHP $VERSION is not affected or is patched"
  exit 0
fi
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: Run a fleet-wide grep for pg_select, pg_insert, pg_update, and pg_delete across all PHP codebases. If you find hits, those applications jump to the front of your patch queue — upgrade PHP on those hosts to 8.2.33/8.3.33/8.4.24/8.5.9 immediately and deploy WAF SQLi rules in front of them this week. If the grep comes back clean, you're not exposed to this CVE regardless of PHP version, and you can fold the PHP upgrade into your normal cycle. Per the noisgate mitigation SLA for HIGH, have compensating controls (WAF rules, code audit) in place within 30 days. Per the noisgate remediation SLA, complete the PHP upgrade across all hosts within 180 days. There is no KEV listing and no confirmed in-the-wild exploitation yet, so you have a window — but the public PoC in the advisory itself means weaponization is trivial for anyone who reads it.

Sources

  1. GHSA Advisory — SQL injection in ext-pgsql
  2. PHP 8.3.33 and 8.4.24 Release Announcement
  3. TheHackerWire — CVE-2026-17543
  4. PHP CVS Commit — Fix for PHP-8.5
  5. PHP CVS Commit — Merge into PHP-8.3
  6. PHP CVS Commit — Merge into PHP-8.4
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.