This is less an unlocked front door than a bad hinge on a door most attackers can’t even reach
Tenable plugin 161971 rolls up two PHP flaws fixed in 7.4.30: CVE-2022-31625 in the PostgreSQL extension and CVE-2022-31626 in pdo_mysql with the mysqlnd driver. Affected upstream ranges are PHP 7.4.0-7.4.29, plus parallel 8.0/8.1 ranges. The first bug needs attacker-controlled input to code paths using pg_query_params(). The second needs an application pattern where an untrusted party can influence the MySQL host and password, often by pointing PHP at a rogue MySQL server and sending an abnormally long password.
The vendor/NVD story overstates fleet-wide urgency if you manage thousands of ordinary PHP web nodes. Yes, the technical impact can be RCE, and public exploit material exists. But this is not a broad unauthenticated internet-to-RCE bug against 'any PHP site'; it is extension-specific, workflow-specific, and often requires an already-dangerous app design such as self-service DB connection forms or admin tools like Adminer/phpMyAdmin. That friction pulls this down from HIGH to a solid MEDIUM for most enterprises.
4 steps from start to impact.
Find a reachable PHP 7.4.29-or-older target
< 7.4.30. Tenable itself notes this plugin is version-only and relies on the application's self-reported version, so scanner hits will include systems where the risky extensions or workflows are absent. Weaponized tools at this stage are routine fingerprinting and version enumeration, not a vulnerability-specific exploit.- PHP 7.4.x earlier than 7.4.30 is deployed
- Version is externally observable or discoverable by authenticated scanning
- PHP version disclosure is often suppressed
- A remote version hit does not prove
pdo_mysql/mysqlndorpgsqlis loaded - Distro-packaged builds may be backported differently than simple banner logic implies
Reach the specific vulnerable workflow
CVE-2022-31626, the attacker needs an application that lets an untrusted user influence the DB host and credentials so PHP will connect to an attacker-controlled MySQL endpoint; Ambionics explicitly called out tools such as Adminer and phpMyAdmin. For CVE-2022-31625, the target app must pass attacker-controlled values into PostgreSQL parameterized-query handling in a way that triggers the bad free path. The weaponized tooling here is a rogue MySQL server or crafted app input, not a generic web exploit kit.pdo_mysqlwithmysqlndis installed for 31626, or PostgreSQL extension usage for 31625- Application exposes user influence over DB connection parameters or query parameter types
- Attacker can reach the admin/self-service workflow
- Most production PHP apps never let internet users choose the DB host/password
- Many enterprises do not expose DB admin consoles publicly
- The PostgreSQL bug depends on a narrower coding pattern than ordinary form submission
Trigger memory corruption
CVE-2022-31626, Ambionics showed a fake MySQL server plus an excessively long password can trigger the overflow; for CVE-2022-31625, invalid parameter handling in pg_query_params() can lead to freeing uninitialized pointers. This is where the issue becomes technically serious, but only after the earlier setup hurdles are cleared.- Attacker can drive the exact extension code path
- Input shape matches the vulnerable edge case
- PHP worker process reaches the relevant function
- Long-password edge cases are unusual in real traffic
- Crashing a worker is easier than stable code execution
- Modern hardening may reduce exploit reliability even when the bug is reachable
Convert crash to code execution and pivot
- Exploit reliability on the target build
- Valuable secrets or lateral paths available from the PHP runtime context
- Exploit portability across builds is limited
- Process isolation, containers, SELinux/AppArmor, and secret hygiene reduce payoff
- No evidence this bug became a routine mass-exploitation internet spray target
The supporting signals.
| In-the-wild status | I found no current public evidence of KEV listing or broad active exploitation for CVE-2022-31625 / CVE-2022-31626. This is an inference from current public-source review, not proof of absence. |
|---|---|
| Public exploit / PoC | Yes. The PHP bug tracker entries are public and include exploit discussion; CVE-2022-31626 includes an Ambionics report with a fake MySQL server PoC and notes impact on tools such as Adminer/phpMyAdmin. |
| Reporting researcher | Charles Fol, Ambionics reported both issues in May 2022. |
| EPSS | CVE-2022-31626: about 12.89% / ~94th percentile; CVE-2022-31625: about 0.77% / ~73rd percentile according to current EPSS mirrors surfacing FIRST data. |
| KEV status | Not observed in CISA KEV public results during this review; no known KEV added date identified. |
| CVSS reality check | Worst-case score comes from CVE-2022-31626: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H at 8.8 HIGH from NVD, but the PHP CNA score is lower-complexity-adjusted at 7.5 HIGH because exploitation is conditional. |
| Affected versions | Upstream PHP affected: 7.4.0-7.4.29, 8.0.0-8.0.19, 8.1.0-8.1.6. |
| Fixed versions | Upstream fixed in 7.4.30, 8.0.20, and 8.1.7. Debian Bullseye fixed php7.4 in 7.4.30-1+deb11u1; Debian 10 LTS later carried fixes in 7.3.31-1~deb10u2; Gentoo marks unaffected >=7.4.30. |
| Exposure / scanning | Third-party attack-surface telemetry on CVE Details shows roughly 304,589 IPs associated with affected exposure and port 80 as the top observed port, but treat that as coarse exposure data, not proof the dangerous extension path is reachable. |
| Disclosure timeline | PHP 7.4.30 shipped on 2022-06-09; NVD published both CVEs on 2022-06-16. |
noisgate verdict.
The single biggest downward pressure is that exploitation usually requires a specific application design flaw or admin workflow, not just 'a PHP server on the internet.' This is a real memory-corruption issue with public exploit material, but reachability is narrow enough that most fleets should not treat every PHP 7.4 host as an urgent remote-RCE fire drill.
Why this verdict
- Down from vendor HIGH: the worst bug (
CVE-2022-31626) needspdo_mysqlwithmysqlnd*and* an app flow where an attacker can influence DB host and password, which is uncommon in ordinary public web apps - More friction:
CVE-2022-31625requires PostgreSQL extension usage and a narrower bad-parameter path intopg_query_params(), so many PHP deployments are unaffected in practice even if the version is old - Still not LOW: public exploit material exists, the bugs can cross into real RCE territory, and exposed DB admin tooling or self-service connection workflows materially amplify risk
Why not higher?
This is not a broad unauthenticated internet exploit against vanilla PHP request handling. The attack path compounds multiple prerequisites: the right extension, the right application behavior, and often attacker influence over backend connection details or edge-case parameter types. That sharply narrows reachable population and keeps it out of HIGH for most 10,000-host environments.
Why not lower?
Calling it LOW would ignore two important facts: the impact can be full code execution in the PHP worker context, and exploit information is public enough to be operationalized against the small set of apps that expose the right workflow. If you run internet-reachable DB admin consoles or custom 'test connection' features, this can move from theoretical to very real.
What to do — in priority order.
- Map extension usage — Identify which hosts actually load
pdo_mysql,mysqlnd,pgsql, orpdo_pgsql, and which apps expose DB connection testing or self-service login workflows. For a MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but do this discovery early so you can locally escalate the truly exposed subset. - Restrict DB admin tools — Put Adminer, phpMyAdmin, phpPgAdmin, install wizards, and 'test DB connection' pages behind VPN, SSO, or strict source-IP allowlists. This cuts off the most plausible external path to
CVE-2022-31626; for this MEDIUM case there is no mitigation SLA, but apply during normal hardening rather than waiting for the patch window to expire. - Disable unused PHP extensions — If a host does not need PostgreSQL or
pdo_mysql/mysqlnd, remove or disable those modules. That removes the vulnerable code path entirely and is often faster than waiting on app-owner patch cycles; again, no mitigation SLA — go straight to the 365-day remediation window for the software fix. - Constrain outbound DB egress — Block web tiers from making arbitrary outbound MySQL/PostgreSQL connections except to approved database destinations. This is especially effective against the rogue-MySQL-server setup needed for
CVE-2022-31626; apply as routine segmentation, not emergency response. - Validate connection inputs — If you own custom code that accepts user-supplied DB connection values, cap password length and prohibit arbitrary host selection. That does not replace patching, but it directly addresses the exploit precondition the Ambionics report described.
- A generic WAF will not reliably stop this because the dangerous part may be a server-initiated connection to a rogue MySQL host or an app-internal extension path, not a recognizable HTTP payload alone.
- Simply hiding the PHP version banner reduces reconnaissance noise but does nothing to remove the memory-corruption bug.
- Patching only the database server does not help; the vulnerable code is in the PHP client-side extensions.
Crowdsourced verification payload.
Run this on the target Linux/PHP host, not your scanner. Invoke it as bash check_php_7430.sh /usr/bin/php or just bash check_php_7430.sh if php is in PATH; root is not required, but the account must be able to execute the PHP CLI and read module/package metadata.
#!/usr/bin/env bash
# check_php_7430.sh
# Verify exposure to PHP 7.4.x < 7.4.30 issues covered by Tenable 161971
# Outputs one of: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0 PATCHED, 1 VULNERABLE, 2 UNKNOWN
set -u
PHP_BIN="${1:-php}"
have_cmd() { command -v "$1" >/dev/null 2>&1; }
ver_ge() { [ "$(printf '%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]; }
ver_lt() { [ "$1" != "$2" ] && [ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]; }
if ! have_cmd "$PHP_BIN"; then
echo "UNKNOWN - php binary not found: $PHP_BIN"
exit 2
fi
PHP_VER="$($PHP_BIN -r 'echo PHP_MAJOR_VERSION,".",PHP_MINOR_VERSION,".",PHP_RELEASE_VERSION;' 2>/dev/null)"
if [ -z "$PHP_VER" ]; then
echo "UNKNOWN - unable to query PHP version"
exit 2
fi
MODULES="$($PHP_BIN -m 2>/dev/null | tr '[:upper:]' '[:lower:]')"
PHPINFO_LINE="$($PHP_BIN -i 2>/dev/null | grep -i '^client api version => mysqlnd' | head -n1)"
has_pdo_mysql=0
has_mysqlnd=0
has_pgsql=0
has_pdo_pgsql=0
echo "$MODULES" | grep -qx 'pdo_mysql' && has_pdo_mysql=1
echo "$MODULES" | grep -qx 'mysqlnd' && has_mysqlnd=1
echo "$MODULES" | grep -qx 'pgsql' && has_pgsql=1
echo "$MODULES" | grep -qx 'pdo_pgsql' && has_pdo_pgsql=1
[ -n "$PHPINFO_LINE" ] && has_mysqlnd=1
PKG_NOTE=""
if have_cmd dpkg-query; then
PKG_NOTE="$(dpkg-query -W -f='${Package} ${Version}\n' 'php7.4*' 2>/dev/null | paste -sd ';' -)"
elif have_cmd rpm; then
PKG_NOTE="$(rpm -qa 2>/dev/null | grep -Ei '^php(|74|7\.4|74-)' | paste -sd ';' -)"
fi
# This plugin is specifically for 7.4.x < 7.4.30.
# Same CVEs also affect 8.0/8.1, but those belong to different checks/advisories.
if [[ ! "$PHP_VER" =~ ^7\.4\. ]]; then
echo "UNKNOWN - installed PHP is $PHP_VER; Tenable 161971 specifically targets PHP 7.4.x < 7.4.30. Packages: ${PKG_NOTE:-none}"
exit 2
fi
if ver_ge "$PHP_VER" "7.4.30"; then
echo "PATCHED - PHP version is $PHP_VER (>= 7.4.30). Packages: ${PKG_NOTE:-none}"
exit 0
fi
# Version is vulnerable upstream. Now assess whether the relevant extensions are present.
if [ $has_pdo_mysql -eq 1 ] && [ $has_mysqlnd -eq 1 ]; then
echo "VULNERABLE - PHP $PHP_VER with pdo_mysql + mysqlnd loaded; matches CVE-2022-31626 exposure preconditions. Packages: ${PKG_NOTE:-none}"
exit 1
fi
if [ $has_pgsql -eq 1 ] || [ $has_pdo_pgsql -eq 1 ]; then
echo "VULNERABLE - PHP $PHP_VER with PostgreSQL extension loaded; matches CVE-2022-31625 exposure preconditions. Packages: ${PKG_NOTE:-none}"
exit 1
fi
echo "UNKNOWN - PHP $PHP_VER is below 7.4.30, but the relevant extensions were not detected in this CLI context. Re-check the exact FPM/Apache SAPI config. Packages: ${PKG_NOTE:-none}"
exit 2
If you remember one thing.
161971 hit. First, slice the population to hosts that are both PHP 7.4.29 or older *and* actually use pdo_mysql/mysqlnd or PostgreSQL paths exposed to untrusted users; for this MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window, unless you discover exposed Adminer/phpMyAdmin-style workflows, which you should harden immediately as a local exception. Then complete the actual upgrade to 7.4.30+ or the relevant distro-fixed package inside the noisgate remediation SLA of ≤ 365 days, while separately treating the broader fact that PHP 7.4 is EOL as a platform-lifecycle problem you should retire sooner than that if possible.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.