This is a smoke alarm wired to two locked closets, not the whole building
Tenable plugin 166901 fires on PHP 7.4.x before 7.4.33 and bundles two fixes from the November 3, 2022 PHP 7.4.33 security release: CVE-2022-31630 in gd imageloadfont() and CVE-2022-37454 in SHA-3 hash_update(). The first needs an application to accept an attacker-supplied font file and then use that font with imagechar(); the second needs the application to drive the SHA-3 code path with attacker-controlled data, with the public PHP reproducer using a 4,294,967,295-byte update call.
Vendor CRITICAL is technically anchored to the 9.8 score on CVE-2022-37454, but that score badly overstates fleet risk for ordinary PHP web hosting. On real estates, neither bug is 'send one HTTP request to any PHP site and get RCE'; both depend on uncommon app logic, and one of them was explicitly described by PHP maintainers as requiring obviously malicious invocation. For a 10,000-host patch queue, this belongs below remotely reachable edge RCEs and known-exploited flaws.
4 steps from start to impact.
Find an app that actually reaches the vulnerable function
imageloadfont() on attacker-controlled input; for CVE-2022-37454, the app must invoke SHA-3 hashing through hash_update() on attacker-controlled data or files. Tooling is trivial here: curl, Burp, or a custom HTTP client are enough to probe workflows.- Attacker can reach the PHP application remotely
- The application uses the affected PHP runtime branch (
7.4.0-7.4.32) - A rare vulnerable feature is actually exposed by application code
- Most PHP sites never call
imageloadfont()at all - Many apps use SHA-256/MD5/HMAC flows, not SHA-3 streaming updates
- Version-based scanners cannot prove the vulnerable function is reachable
Supply a crafted font or crafted SHA-3 input
imagechar(). For CVE-2022-37454, public research from Nicky Mouha provides a PHP reproducer and a crafted-file route against vulnerable SHA-3 implementations; the PHP bug report shows a crash path via hash_update() with a huge attacker-controlled length.- Application accepts attacker-controlled file or data into the exact vulnerable function
- Relevant extension or algorithm is enabled (
gdfor 31630, SHA-3 path for 37454)
- Upload filters, MIME controls, and business logic often block custom font files
- The SHA-3 path is highly app-specific and usually not user-controlled
- Huge inputs, file-size caps, request limits, and PHP memory limits suppress many practical attempts
imageloadfont() use; DAST coverage is usually poor unless the test app exposes a very specific upload-and-render flow.Trigger memory error, disclosure, or crash
- Precise crafted input reaches the vulnerable parser or hash routine
- The PHP worker processes the attacker-controlled object fully
- Interpreter crashes are easier than reliable RCE
- Modern hardening, worker recycling, and container isolation reduce blast radius
- Many successful outcomes are single-worker DoS or partial memory disclosure, not full host takeover
Turn a bug into code execution
- Attacker can repeatedly hit the same vulnerable code path
- Crash-only behavior can be refined into controlled memory corruption
- Host-level mitigations do not kill the session first
- No strong evidence of broad in-the-wild exploitation
- No KEV listing for either CVE
- The vulnerable population is much narrower than 'all PHP servers'
The supporting signals.
| In-the-wild status | No authoritative evidence of broad in-the-wild exploitation found for CVE-2022-31630 or CVE-2022-37454 in the sources reviewed. |
|---|---|
| KEV status | Not listed in the CISA Known Exploited Vulnerabilities catalog based on targeted CISA searches reviewed during this assessment. |
| Proof-of-concept availability | Yes, but niche. PHP bug #81738 includes a working crash reproducer for hash_update() from Nicky Mouha; public references also exist for imageloadfont() PoCs, but neither is a ubiquitous one-request web exploit. |
| EPSS | CVE-2022-37454: about 1.16% EPSS / 78th percentile from Docker Scout, with other public mirrors around 0.76%-1.5%. CVE-2022-31630: about 0.065% EPSS / 20th percentile from Docker Scout. |
| CVSS reality check | CVE-2022-37454 is 9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) and dominates the plugin severity. CVE-2022-31630 is split-scored: NVD 7.1 vs PHP Group 6.5, which already signals dispute over real attackability. |
| Affected versions | For this plugin: PHP 7.4.0-7.4.32. The release also fixed the same issues in 8.0.0-8.0.24 and 8.1.0-8.1.11. |
| Fixed versions | Upstream fixed in PHP 7.4.33 on 2022-11-03. Distros may backport fixes without changing the major/minor stream; e.g. SUSE ships patched php7* packages at 7.4.33-150200.3.46.2 and later. |
| Exposure reality | Internet exposure of PHP is huge, but exposure of the reachable vulnerable code paths is not. Most apps do not expose user-driven imageloadfont() flows, and many never use SHA-3 streaming through hash_update() at all. |
| Disclosure timeline | Public release and fix landed on 2022-11-03 in PHP 7.4.33; CVE-2022-37454 was disclosed around 2022-10-21, while CVE-2022-31630 was published on 2022-10-27. |
| Reporter / research origin | CVE-2022-37454 was reported by Nicky Mouha and later analyzed in a NIST paper. CVE-2022-31630 maps to PHP bug #81739 and a Zend security note warning specifically about gd imageloadfont(). |
noisgate verdict.
The decisive downgrade driver is prerequisite friction: exploitation requires uncommon, application-specific PHP code paths rather than simple network reachability to a PHP host. There is also no KEV listing or strong live-fire evidence, so this does not compete with internet-edge RCEs for immediate patch bandwidth.
Why this verdict
- Requires specific app behavior: neither issue is exploitable just because TCP/80 or TCP/443 reaches a PHP site; the app must call
imageloadfont()or SHA-3hash_update()on attacker-controlled input. - Population narrows hard at each step:
imageloadfont()is niche, and SHA-3 streaming is uncommon in mainstream PHP web apps. That takes this from 'all PHP servers' to a much smaller subset. - The vendor baseline is inflated by one component CVE: Tenable inherits the 9.8 score from
CVE-2022-37454, but that score models theoretical impact, not the rarity of a remotely reachable vulnerable workflow in enterprise deployments.
Why not higher?
There is no credible evidence in the reviewed sources that attackers are broadly exploiting these bugs against typical internet-facing PHP sites. More importantly, the attack chain assumes either a rare font-loading feature or a very specific SHA-3 hashing path on untrusted input; those are compounding prerequisites that sharply reduce real exposure.
Why not lower?
These are still memory-safety bugs inside the interpreter, not harmless edge cases. If you run a bespoke app that accepts untrusted font files or hashes attacker-supplied large files with SHA-3, the impact can move from crash/disclosure into serious compromise territory.
What to do — in priority order.
- Block untrusted font workflows — If any app uses GD custom fonts, stop accepting user-supplied font files or gate them behind strict allowlists and offline validation. This directly cuts off
CVE-2022-31630; for a MEDIUM verdict there is no mitigation SLA, so fold it into normal engineering change control rather than emergency work. - Avoid SHA-3 on attacker-controlled bulk input — Review custom code that uses
hash_init('sha3-*')andhash_update()on untrusted uploads, archives, or streams. Where possible, move that work out of request paths or replace the pattern during normal remediation planning; again, no mitigation SLA for a MEDIUM finding. - Enforce upload and request ceilings — Keep tight reverse-proxy body limits, PHP
upload_max_filesize,post_max_size,memory_limit, and worker timeouts. These do not 'fix' the bugs, but they add practical friction against the large crafted inputs used in public SHA-3 reproductions and reduce crash surface. - Prefer supported distro backports or newer runtimes — If you cannot retire PHP 7.4 immediately, use a vendor-supported package stream with documented backports instead of frozen upstream tarballs. That reduces both this advisory and the much larger strategic risk of running an upstream-EOL runtime.
- A WAF does not reliably help; the dangerous condition is inside interpreter logic after the application chooses to load a font or hash data.
- Hiding the PHP version does nothing; the exploitability question is the code path, not banner exposure.
- EDR alone is not a compensating control for the initial bug. It may catch payloads later, but it will not stop an out-of-bounds read or a worker crash.
Crowdsourced verification payload.
Run this on the target Linux host that executes PHP, not from an auditor workstation. Save as check_php_166901.sh, then run bash check_php_166901.sh /usr/bin/php or simply bash check_php_166901.sh to use php from PATH; no root is required, but the script needs permission to execute the local PHP binary and query package metadata if present.
#!/usr/bin/env bash
# check_php_166901.sh
# Purpose: assess exposure to Tenable plugin 166901 (PHP 7.4.x < 7.4.33)
# Output: 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() {
# returns 0 if $1 >= $2
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n1)" = "$1" ]
}
ver_lt() {
# returns 0 if $1 < $2
! ver_ge "$1" "$2"
}
if ! have_cmd "$PHP_BIN"; then
echo "UNKNOWN"
exit 2
fi
PHP_VERSION_RAW="$($PHP_BIN -r 'echo PHP_VERSION;' 2>/dev/null || true)"
if [ -z "$PHP_VERSION_RAW" ]; then
echo "UNKNOWN"
exit 2
fi
# Normalize versions like 7.4.33-1ubuntu1 to the leading semantic portion.
PHP_VERSION="$(printf '%s' "$PHP_VERSION_RAW" | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/')"
BRANCH="$(printf '%s' "$PHP_VERSION" | awk -F. '{print $1 "." $2}')"
# This script is scoped to plugin 166901 only.
if [ "$BRANCH" != "7.4" ]; then
echo "UNKNOWN"
exit 2
fi
# If the runtime itself reports 7.4.33+, this advisory is fixed.
if ver_ge "$PHP_VERSION" "7.4.33"; then
echo "PATCHED"
exit 0
fi
# Check whether this may be a distro backport situation.
PKG_HINT=""
if have_cmd dpkg-query; then
PKG_HINT="$(dpkg-query -W -f='${Package} ${Version}\n' 'php7.4*' 2>/dev/null | head -n 5 || true)"
elif have_cmd rpm; then
PKG_HINT="$(rpm -qa 2>/dev/null | grep -E '^php(|74|7\.4)(-|$)' | head -n 5 || true)"
fi
# If package metadata itself clearly contains 7.4.33, treat as patched backport/package.
if printf '%s' "$PKG_HINT" | grep -q '7\.4\.33'; then
echo "PATCHED"
exit 0
fi
# Otherwise a 7.4.0-7.4.32 runtime is vulnerable if not obviously backported.
# Because distros sometimes backport security fixes without changing the runtime version,
# package-managed installs with ambiguous metadata are marked UNKNOWN instead of VULNERABLE.
if [ -n "$PKG_HINT" ]; then
echo "UNKNOWN"
exit 2
fi
echo "VULNERABLE"
exit 1
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.