← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
tenable:101525 · CWE-787 · Disclosed 2017-07-06

PHP 5

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a cracked engine block that only matters if the attacker can also reach the right pedals

tenable:101525 is a version-based finding for PHP 5.6.x before 5.6.31, published on 2017-07-06. The bundle includes multiple bugs across core PHP and bundled libraries: Oniguruma regex compilation/searching (CVE-2017-9224/9226/9227/9228/9229), unserialize() handling (CVE-2017-12933), INI parsing (CVE-2017-11628), WDDX parsing (CVE-2017-11143/11145), GD/PCRE memory issues, and a large-POST CPU DoS (CVE-2017-11142). The important catch: most of these are not generic “send one HTTP request to any PHP site and get RCE” bugs; they need a reachable application sink such as attacker-controlled regex compilation, unsafe deserialization, WDDX parsing, or unusual parser exposure.

The vendor baseline is inflated for enterprise patch triage because Tenable anchors on the worst-case CVSS from CVE-2017-9228 and explicitly says it did not test exploitability, only the self-reported PHP version. In real fleets, the decisive friction is that an attacker usually needs both an old runtime and a specific insecure app behavior; add distro backports and the version-only signal gets even noisier. That makes this a solid MEDIUM for most 10,000-host programs: fix it, but don’t let it jump ahead of proven one-click edge RCEs.

"Big vendor score, small real-world exploit window: this usually needs an app bug on top of old PHP."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Fingerprint old PHP

The scanner or attacker first identifies a site exposing a PHP version banner such as X-Powered-By: PHP/5.6.x or a package-derived response fingerprint. Tools here are boring: Nessus for defenders, Shodan-style header collection or simple curl/Burp for attackers. This step only proves an old runtime string, not a reachable exploit primitive.
Conditions required:
  • Public or internal HTTP reachability to the web tier
  • Version leakage via headers, error pages, or package telemetry
Where this breaks in practice:
  • Many stacks suppress X-Powered-By or sit behind reverse proxies
  • Distro backports make an old-looking version string a weak exploitability signal
Detection/coverage: Excellent scanner coverage for banner/version detection; poor coverage for whether the vulnerable code path is actually reachable.
STEP 02

Find a vulnerable sink in the app

The attacker must map the application to a sink that exposes one of the patched paths: mb_ereg* with attacker-controlled patterns, unserialize() on untrusted data, parse_ini_string()/INI parsing on user input, wddx_deserialize(), or large POST handling. Burp Suite, source review, and SAST rules are the real weaponized tools here; the PHP version alone is not enough.
Conditions required:
  • Ability to supply crafted input to a PHP function that touches one of the affected parser/library paths
  • Application-specific feature exposing regex, deserialization, WDDX, or parser behavior
Where this breaks in practice:
  • Most PHP apps use static regexes, not attacker-supplied regex compilation
  • WDDX is rare in modern deployments
  • Unsafe unserialize() is common historically but still requires a distinct application flaw, not just old PHP
Detection/coverage: Good SAST coverage for unserialize() and some parser sinks; weak DAST coverage for mbstring/Oniguruma regex-compilation exposure.
STEP 03

Trigger memory corruption or parser failure

If the attacker reaches the right sink, they use public reproducers or custom payloads to hit the parser bug. For the highest-rated path, public GitHub issue material exists for Oniguruma (CVE-2017-9228) showing a reproducible heap write during regex compilation, but that PoC is at library level and still has to be translated into the target app’s request format.
Conditions required:
  • Exact vulnerable code path reached
  • Payload can survive app validation and input normalization
Where this breaks in practice:
  • Turning a library-level reproducer into a stable web exploit is non-trivial
  • Modern hardening, worker recycling, ASLR, and crash-only behavior often collapse impact from theoretical RCE to DoS
Detection/coverage: Crash telemetry in php-fpm, Apache, or nginx upstream logs can reveal failed attempts; network scanners cannot validate this step remotely.
STEP 04

Convert crash potential into business impact

The common real outcome is a worker crash, CPU burn, or localized service interruption. RCE is the theoretical upper bound for a subset of bugs, but in enterprise reality the attacker usually gets more mileage from simpler app-layer bugs than from forcing a legacy PHP parser edge case into reliable code execution.
Conditions required:
  • Target process handles the crafted request
  • Service architecture allows repeated requests against the same vulnerable path
Where this breaks in practice:
  • Pool isolation limits blast radius to one app or one worker set
  • Process supervision restarts crashed workers quickly
  • WAF/body limits can blunt oversized POST DoS cases
Detection/coverage: App logs, php-fpm crash logs, and EDR on the web tier provide the best evidence; remote version scans do not measure impact.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo public active-exploitation signal found in the consulted primary sources, and no CISA KEV listing found for the cited high-end CVEs in this bundle.
Proof-of-concept availabilityYes, but mostly library-level. NVD links GitHub issue material for CVE-2017-9228, and the Oniguruma issue includes a reproducible crash harness rather than a turnkey web exploit.
EPSSFor CVE-2017-9228, Tenable surfaces EPSS 0.00474. The exact percentile was not surfaced in the consulted primary sources.
KEV statusNot KEV-listed in the consulted CISA catalog sources for the representative RCE-class bugs in this advisory.
CVSS vectorVendor/NVD worst-case anchor is CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 for CVE-2017-9228. That is technically valid for the library bug in isolation, but it overstates fleet risk when the application never exposes attacker-controlled regex compilation.
Affected versionsUpstream affected range for this Tenable check is PHP 5.6.0 through 5.6.30. NVD also tracks adjacent fixed branches 7.0.21 and 7.1.7 for several bundled issues.
Fixed versionsUpstream fix is PHP 5.6.31. Distro backports exist: Debian fixed php5 in 5.6.33+dfsg-0+deb8u1 for Jessie, Ubuntu fixed php5 in 5.5.9+dfsg-1ubuntu4.22 for Trusty, and Red Hat shipped bundled fixes in later package errata rather than matching upstream version strings.
Scanner/detection notesTenable states it relies only on the application's self-reported version number and has not tested the vulnerable code paths. Treat internet-scale exposure numbers for this plugin as coarse inventory, not exploitability proof.
Exposure realityReachable population is far smaller than 'all PHP 5.6 sites' because most exploit paths require a second condition: an app that reflects user input into mb_ereg*, unserialize(), parse_ini_string(), WDDX, or oversized POST processing.
Disclosure and researchersUpstream PHP shipped the security release on 2017-07-06. One representative high-severity underlying bug, CVE-2017-9228, was published on 2017-05-24; the public Oniguruma issue shows it was reported by GitHub user lxxxxfdh on 2017-05-23.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.8/10)

The single biggest downgrade factor is code-path friction: an attacker usually needs a vulnerable application behavior on top of the old PHP runtime, not merely network reachability to a PHP banner. Without that second condition, the practical outcome trends toward crashes or no exploit path at all, which is not how a true edge-critical issue behaves in a large fleet.

HIGH Downgrade from vendor critical/high-style labeling to a non-emergency fleet priority
MEDIUM Assessment of reachable exploitability without app-specific sink inventory

Why this verdict

  • Requires an app sink, not just old PHP — most serious paths need attacker-controlled regex compilation, unsafe unserialize(), WDDX, or INI parsing. That means the vulnerability is usually post-discovery, pre-exploitation research work, not a one-request edge compromise.
  • Version-only detection is noisy — Tenable says the plugin relies only on self-reported version. In real estates with Debian/Ubuntu/RHEL backports, that creates meaningful false urgency.
  • Threat intel is cold — no KEV signal found and the representative EPSS exposed by Tenable for CVE-2017-9228 is only 0.00474. Public reproducers exist, but they are not the same thing as mass exploitation evidence.

Why not higher?

This is not a clean internet-edge RCE against every host running PHP 5.6.30. The attack almost always needs a second vulnerable condition inside the app, and several included bugs are more realistically DoS or memory-disclosure crashes than reliable code execution in hardened production workers.

Why not lower?

You still have an old PHP branch with real memory-corruption bugs and public technical reproducers. If one of your exposed apps feeds user input into the affected functions, the score moves from 'legacy noise' to 'legit incident material' quickly, so this does not belong in ignore/backlog limbo.

05 · Compensating Control

What to do — in priority order.

  1. Suppress version leakage — Remove or mask X-Powered-By and related PHP banners so commodity scanners and opportunistic attackers lose the cheap fingerprint. At MEDIUM, there is no noisgate mitigation SLA; do this in the next normal hardening cycle while you work toward patching within the 365-day remediation window.
  2. Hunt risky PHP sinks — Search code and configs for unserialize(, wddx_deserialize(, parse_ini_string(, and mb_ereg/mb_eregi usage with user-controlled patterns. This is the highest-value control because it tells you which hosts are merely old versus actually reachable; at MEDIUM, fold this into routine engineering work and complete it within the same remediation window.
  3. Enforce request-size limits — Clamp oversized POST bodies at the reverse proxy and app server to reduce exposure to the large-POST CPU exhaustion bug (CVE-2017-11142). Use nginx client_max_body_size, Apache LimitRequestBody, and upstream timeouts; there is no mitigation SLA at this severity, so apply as part of normal web-tier hygiene.
  4. Isolate and monitor PHP workers — Run apps in separate php-fpm pools or equivalent worker boundaries with sane restart policies, low privileges, and tight file permissions. That turns most failed parser exploitation into a contained worker recycle instead of a multi-app outage; again, no mitigation SLA at MEDIUM, but it should land before the patch deadline.
What doesn't work
  • MFA doesn't help; these are parser/runtime issues, not account-takeover paths.
  • Network segmentation alone doesn't solve it for internet-facing apps because the vulnerable surface is the web request itself.
  • A generic WAF signature will not reliably catch library-level regex or deserialization edge cases unless you already know the exact app endpoint and payload shape.
  • Closing the ticket because the package version looks old but 'the distro backports fixes' is not enough; verify the actual package errata or host package build before suppressing.
06 · Verification

Crowdsourced verification payload.

Run this on the target PHP host as a local validation check, not from your scanner. Invoke it as bash verify_php_5_6_31.sh with no special privileges required for the basic version test; package backport checks for Debian/Ubuntu use local package metadata if available.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# verify_php_5_6_31.sh
# Purpose: determine whether the local PHP runtime is vulnerable to the upstream
# PHP < 5.6.31 bundle represented by Tenable plugin 101525.
#
# Output:
#   VULNERABLE - upstream PHP 5.6.x earlier than 5.6.31 and no known distro backport match found
#   PATCHED    - PHP not in affected range, or known distro-fixed package build detected
#   UNKNOWN    - PHP missing, version unreadable, or distro backport status cannot be determined confidently
#
# Exit codes:
#   0 PATCHED
#   1 VULNERABLE
#   2 UNKNOWN

set -u

ver_lt() {
  # returns 0 if $1 < $2
  [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" != "$2" ]
}

command -v php >/dev/null 2>&1 || { echo "UNKNOWN: php binary not found"; exit 2; }

PHP_VER_RAW="$(php -r 'echo PHP_VERSION;' 2>/dev/null)"
if [ -z "$PHP_VER_RAW" ]; then
  echo "UNKNOWN: unable to read PHP_VERSION"
  exit 2
fi

PHP_VER="${PHP_VER_RAW%%-*}"

# Fast path: unaffected upstream versions
case "$PHP_VER" in
  5.6.*)
    if ver_lt "$PHP_VER" "5.6.31"; then
      :
    else
      echo "PATCHED: upstream PHP version $PHP_VER >= 5.6.31"
      exit 0
    fi
    ;;
  5.*)
    # Older non-5.6 branches are outside this specific plugin's affected range.
    echo "PATCHED: PHP version $PHP_VER is not in the plugin's 5.6.x < 5.6.31 range"
    exit 0
    ;;
  *)
    echo "PATCHED: PHP version $PHP_VER is newer than the plugin's affected branch"
    exit 0
    ;;
esac

# At this point, upstream-reported PHP is 5.6.x < 5.6.31.
# Check common distro backport cases before declaring vulnerable.
if command -v dpkg-query >/dev/null 2>&1; then
  PKG_VER="$(dpkg-query -W -f='${Version}\n' php5 2>/dev/null | head -n1)"
  if [ -n "$PKG_VER" ]; then
    case "$PKG_VER" in
      5.6.33+dfsg-0+deb8u1*|5.6.33+dfsg-0+deb8u2*|5.6.33+dfsg-0+deb8u3*|5.6.40+*)
        echo "PATCHED: Debian php5 package $PKG_VER includes fixes beyond upstream 5.6.31"
        exit 0
        ;;
      5.5.9+dfsg-1ubuntu4.22*|5.5.9+dfsg-1ubuntu4.23*|5.5.9+dfsg-1ubuntu4.24*)
        echo "PATCHED: Ubuntu php5 package $PKG_VER is a known fixed backport level"
        exit 0
        ;;
    esac
    echo "UNKNOWN: php reports $PHP_VER but distro package $PKG_VER may be backported; verify vendor errata"
    exit 2
  fi
fi

if command -v rpm >/dev/null 2>&1; then
  # Generic RPM check: many vendors backport without changing the upstream PHP_VERSION.
  RPM_PKG="$(rpm -q php php-cli php-common 2>/dev/null | tr '\n' ' ' | sed 's/  */ /g')"
  if [ -n "$RPM_PKG" ]; then
    echo "UNKNOWN: php reports $PHP_VER and RPM packages were found ($RPM_PKG). RPM-based distros often backport fixes; verify against local vendor errata before calling this vulnerable."
    exit 2
  fi
fi

echo "VULNERABLE: upstream PHP version $PHP_VER is in 5.6.x < 5.6.31 and no known backport match was detected"
exit 1
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, treat this as legacy-PHP cleanup, not an emergency war room. For a MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window; use that time to verify which hosts are true source-build or unpatched upstream installs, identify apps exposing unserialize() / mb_ereg* / parser sinks, and schedule the actual PHP update or platform retirement under the noisgate remediation SLA of ≤365 days. If any exposed app is confirmed to compile attacker-controlled regexes or deserialize untrusted data, pull that host forward ahead of the general queue.

Sources

  1. Tenable plugin 101525
  2. PHP 5.6.31 release announcement
  3. PHP 5 changelog entry for 5.6.31
  4. NVD CVE-2017-9228
  5. Oniguruma issue #60 reproducer
  6. Ubuntu CVE-2017-9228 tracker
  7. Debian tracker CVE-2017-12933
  8. Red Hat RHSA-2018:1296
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.