← Back to Feed CACHED · 2026-08-12 07:28:27 · CACHE_KEY tenable:130276
tenable:130276 · CWE-787 · Disclosed 2019-10-24

PHP-FPM fpm_main.c Underflow Remote Code Execution via fastcgi_split_path_info

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

Someone left the factory gate unlocked in 2019 and the key still works today

CVE-2019-11043 is a buffer underflow in PHP-FPM's fpm_main.c that lets an unauthenticated remote attacker achieve arbitrary code execution on any nginx + PHP-FPM stack where the fastcgi_split_path_info directive uses a regex anchored with ^…$ and no try_files guard is present. By sending a URL containing an encoded newline (%0a), the attacker breaks the regex, forces PATH_INFO to empty, triggers an underflow that corrupts FCGI protocol memory, and ultimately overwrites PHP configuration values (php_value) to point auto_prepend_file at attacker-controlled content. Affected versions are PHP 7.1.x < 7.1.33, 7.2.x < 7.2.24, and 7.3.x < 7.3.11 — all of which have been end-of-life for years.

The vendor CVSS of 9.8 CRITICAL (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) is fair for environments that actually run the vulnerable configuration. The specific nginx directive requirement prevents a truly universal 'spray and pop' scenario — you need nginx, PHP-FPM, and the fastcgi_split_path_info pattern without try_files. That said, this config is extremely common in real-world nginx+PHP deployments; dozens of popular tutorials and framework docs recommended it for years. Combined with the CISA KEV listing, public Metasploit module, EPSS of 0.9947, and the fact that the patch has been available since October 2019, any remaining vulnerable instance represents a negligent exposure. The vendor severity is accurate.

"Unauthenticated RCE on internet-facing PHP-FPM+nginx stacks. KEV-listed, Metasploit-ready, patch 7 years overdue."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify nginx + PHP-FPM target

The attacker scans for web servers returning nginx headers serving PHP content. Shodan, Censys, or FOFA queries for Server: nginx combined with .php responses narrow the target list. The attacker then fingerprints the PHP version via X-Powered-By headers or error pages.
Conditions required:
  • Target exposes an HTTP/HTTPS endpoint running nginx
  • PHP-FPM is the backend handler
Where this breaks in practice:
  • Many modern deployments strip X-Powered-By headers, requiring blind version probing
  • PHP 8.x is now dominant; finding 7.1–7.3 unpatched narrows targets significantly
Detection/coverage: Web application scanners (Nessus plugin 130276, Qualys QID 150199) detect the vulnerable PHP version. GreyNoise tags track scanning for this CVE.
STEP 02

Confirm vulnerable fastcgi_split_path_info config

The attacker sends a crafted URL with a %0a (newline) in the path component to test whether fastcgi_split_path_info breaks on the newline. A 200 response or altered behavior (vs. a 404/403) confirms the vulnerable regex configuration is present. This is a non-destructive probe.
Conditions required:
  • nginx config uses fastcgi_split_path_info with ^…$ regex
  • No try_files or if guard blocks the request before reaching PHP-FPM
Where this breaks in practice:
  • WAFs or CDNs that normalize or reject %0a in URLs will block this probe
  • Configs using try_files $uri =404 before fastcgi_pass are immune
Detection/coverage: WAF rules for encoded newline characters in URI paths. IDS signatures exist for Snort/Suricata (SID references for CVE-2019-11043).
STEP 03

Trigger underflow and corrupt FCGI memory

Using the phuip-fpizdam exploit tool (by researcher neex / Emil Lerner), the attacker sends ~20-1000 carefully crafted requests to systematically corrupt PHP-FPM's shared memory. The tool brute-forces the correct offset to overwrite PHP_VALUE entries in the FCGI protocol data, setting auto_prepend_file to a remote URL or php://input.
Conditions required:
  • PHP-FPM worker processes share memory layout (default behavior)
  • Attacker can send multiple rapid requests to the same worker
Where this breaks in practice:
  • Rate limiting on the endpoint can slow or break the brute-force
  • PHP-FPM's process manager may recycle workers, resetting the corruption
Detection/coverage: Anomalous burst of requests to a single PHP endpoint with %0a in the path. PHP-FPM error logs may show segfaults or unexpected PHP_VALUE overrides.
STEP 04

Achieve remote code execution

Once auto_prepend_file is set to php://input, every subsequent POST request to any PHP page on the server executes the POST body as PHP code. The attacker now has arbitrary code execution as the PHP-FPM worker user (typically www-data or nginx). From here, standard post-exploitation proceeds: reverse shell, credential harvesting, lateral movement.
Conditions required:
  • Step 3 succeeded in overwriting PHP_VALUE
  • PHP-FPM worker has outbound connectivity or the attacker can exfiltrate inline
Where this breaks in practice:
  • Execution is as the web server user, not root — privilege escalation may be needed for full host compromise
  • Network segmentation may limit lateral movement from a DMZ web server
Detection/coverage: EDR/HIDS detecting unexpected child processes from PHP-FPM workers (e.g., /bin/sh spawned by php-fpm). File integrity monitoring on PHP configs.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationConfirmed. CISA KEV-listed. Active exploitation observed since late 2019. Used in opportunistic campaigns targeting exposed nginx+PHP stacks.
CISA KEVListed. Added to KEV catalog with remediation due date of 2022-04-15. Any federal agency should have patched years ago.
EPSS Score0.9947 (99th+ percentile) — among the highest-scoring CVEs in the EPSS model, reflecting widespread tooling and exploitation history.
CVSS v3.1 VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H9.8 Critical. Network-attackable, no auth, no user interaction, full CIA impact.
Proof-of-ConceptMultiple public exploits. neex/phuip-fpizdam (original researcher tool), Metasploit module (exploit/multi/http/php_fpm_rce), and exploit-db #47553.
Affected VersionsPHP 7.1.x < 7.1.33, 7.2.x < 7.2.24, 7.3.x < 7.3.11. All three branches are now end-of-life. PHP 5.x and 8.x are not affected by this specific flaw.
Fixed VersionsPHP 7.1.33, 7.2.24, 7.3.11 (released 2019-10-24). Distro backports: Debian (DSA-4561), Ubuntu (USN-4166-1), RHEL/CentOS via php-fpm package updates.
Scanning / ExposureTenable plugin 130276, Qualys QID 150199, Nuclei template available. GreyNoise has observed consistent scanning for this CVE. Internet-facing nginx+PHP-FPM instances remain discoverable via Shodan (Server: nginx + PHP headers).
Disclosure Date2019-09-26 (reported to PHP bug tracker by Emil Lerner). Patch released 2019-10-24. Public exploit same week.
ResearcherEmil Lerner (@neaborom) — presented at ZeroNights 2019. Exploit tool: phuip-fpizdam.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to CRITICAL (9.5/10)

The single most decisive factor is that this is an unauthenticated, network-reachable RCE with a public Metasploit module, confirmed active exploitation, and CISA KEV listing — the trifecta that makes downgrading indefensible. While the fastcgi_split_path_info configuration requirement provides marginal friction, this nginx pattern is common enough in real deployments that it does not meaningfully reduce the reachable population.

HIGH Vulnerability mechanics and exploit reliability
HIGH Active exploitation and KEV status
MEDIUM Current internet-exposed population (most should have patched by now, but legacy instances persist)

Why this verdict

  • Unauthenticated RCE from the network — no credentials, no user interaction, no social engineering. An attacker needs only HTTP access to a vulnerable endpoint. This is the most dangerous attack class.
  • KEV-listed with EPSS 0.9947 — CISA confirmed active exploitation. The EPSS score is in the 99th+ percentile. This is not theoretical; it is weaponized and deployed at scale.
  • Metasploit module and multiple public exploits — the phuip-fpizdam tool automates the entire chain. Metasploit's exploit/multi/http/php_fpm_rce module lowers the skill bar to script-kiddie level.
  • Role multiplier: PHP-FPM+nginx stacks commonly serve as internet-facing web application tiers. In many organizations, these are the front door — hosting customer portals, APIs, e-commerce, and CMS platforms. Compromise of a web tier yields access to backend databases, application secrets, and internal network segments. While not a domain controller or hypervisor, the blast radius is tenant-to-segment scale (web server → database credentials → data exfiltration → lateral movement). In containerized or shared-hosting environments, the blast radius can extend to multi-tenant compromise. This keeps the floor at CRITICAL.
  • Configuration requirement is common, not rare — the fastcgi_split_path_info pattern with ^…$ regex and no try_files is recommended in official PHP documentation, Laravel deployment guides, WordPress nginx configs, and countless Stack Overflow answers. The 'narrow config' argument does not hold.

Why not higher?

This is already CRITICAL at 9.5. The 0.3-point reduction from 9.8 reflects the genuine configuration prerequisite (fastcgi_split_path_info + no try_files) which does exclude some nginx+PHP-FPM deployments — particularly those using more modern config templates that include file-existence checks. A perfect 10.0 would imply zero prerequisites beyond network reachability.

Why not lower?

Downgrading below CRITICAL is not defensible for a KEV-listed, Metasploit-equipped, unauthenticated RCE. The configuration requirement is widespread enough that it cannot be treated as a rare edge case. The EPSS score of 0.9947 empirically confirms that real-world exploitation probability is near-certain for exposed instances. Any remaining unpatched instance is a live target.

05 · Compensating Control

What to do — in priority order.

  1. Add try_files $uri =404; before every fastcgi_pass directive — This is the most effective mitigation and takes minutes to deploy. It causes nginx to return 404 for non-existent paths before the request ever reaches PHP-FPM, completely neutralizing the underflow. Deploy within 3 days per noisgate mitigation SLA for CRITICAL findings.
  2. Block encoded newlines in URI paths at WAF/reverse proxy — Configure your WAF (ModSecurity, Cloudflare, AWS WAF) to reject requests containing %0a or %0d in the URL path. This blocks the exploit's triggering mechanism. Deploy within 3 days.
  3. Upgrade PHP to 8.x (or at minimum 7.4.33) — All affected branches (7.1, 7.2, 7.3) are end-of-life and receive no security updates. Upgrading to PHP 8.x eliminates this CVE and hundreds of others. Plan and execute within the 90-day noisgate remediation SLA.
  4. Restrict PHP-FPM process privileges and network access — Run PHP-FPM workers with minimal filesystem permissions and block outbound network access from web server hosts where possible. This limits post-exploitation blast radius even if the vuln is triggered.
What doesn't work
  • Disabling PATH_INFO in PHP configuration alone — the vulnerability is in the FCGI protocol handling in fpm_main.c, not in PHP's use of PATH_INFO. The underflow occurs before PHP configuration is consulted.
  • IP-based access controls on the web server — this is an unauthenticated attack through legitimate HTTP traffic. Unless you can enumerate every legitimate client IP, ACLs won't help without breaking the application.
  • PHP disable_functions — by the time the attacker controls auto_prepend_file, they can use techniques that bypass disable_functions (e.g., FFI, mail() + LD_PRELOAD). This is not a reliable mitigation.
06 · Verification

Crowdsourced verification payload.

Run this script on each target host running nginx + PHP-FPM. It checks the installed PHP version and inspects nginx configs for the vulnerable fastcgi_split_path_info pattern. Requires root or sudo to read nginx config files. Example: sudo bash check_cve_2019_11043.sh

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2019_11043.sh — Detect CVE-2019-11043 (PHP-FPM underflow RCE)
# Run on target host as root. Outputs VULNERABLE / PATCHED / UNKNOWN.
set -euo pipefail

RESULT="UNKNOWN"
VULN_PHP=0
VULN_NGINX=0

# --- Check PHP version ---
if command -v php &>/dev/null; then
  PHP_VER=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION.".".PHP_RELEASE_VERSION;' 2>/dev/null || echo "0.0.0")
  IFS='.' read -r MAJ MIN REL <<< "$PHP_VER"
  echo "[*] PHP version detected: $PHP_VER"
  if [[ "$MAJ" -eq 7 ]]; then
    if [[ "$MIN" -eq 1 && "$REL" -lt 33 ]]; then
      VULN_PHP=1
      echo "[!] PHP 7.1.x < 7.1.33 — VULNERABLE version"
    elif [[ "$MIN" -eq 2 && "$REL" -lt 24 ]]; then
      VULN_PHP=1
      echo "[!] PHP 7.2.x < 7.2.24 — VULNERABLE version"
    elif [[ "$MIN" -eq 3 && "$REL" -lt 11 ]]; then
      VULN_PHP=1
      echo "[!] PHP 7.3.x < 7.3.11 — VULNERABLE version"
    else
      echo "[+] PHP version is patched or not in vulnerable range"
    fi
  else
    echo "[+] PHP $MAJ.x is not affected (only PHP 7.1-7.3 vulnerable)"
  fi
else
  echo "[?] PHP not found on this host"
fi

# --- Check nginx config for vulnerable pattern ---
NGINX_CONF_DIRS=("/etc/nginx" "/usr/local/nginx/conf" "/opt/nginx/conf")
for CONFDIR in "${NGINX_CONF_DIRS[@]}"; do
  if [[ -d "$CONFDIR" ]]; then
    echo "[*] Scanning nginx configs in $CONFDIR ..."
    # Look for fastcgi_split_path_info without nearby try_files
    MATCHES=$(grep -rl 'fastcgi_split_path_info' "$CONFDIR" 2>/dev/null || true)
    if [[ -n "$MATCHES" ]]; then
      for F in $MATCHES; do
        echo "[!] fastcgi_split_path_info found in: $F"
        if ! grep -q 'try_files' "$F" 2>/dev/null; then
          VULN_NGINX=1
          echo "[!] No try_files guard found in $F — VULNERABLE config"
        else
          echo "[+] try_files guard present in $F — mitigated"
        fi
      done
    else
      echo "[+] No fastcgi_split_path_info directives found"
    fi
  fi
done

# --- Verdict ---
if [[ "$VULN_PHP" -eq 1 && "$VULN_NGINX" -eq 1 ]]; then
  RESULT="VULNERABLE"
  echo ""
  echo "==> VULNERABLE: CVE-2019-11043 — PHP version AND nginx config are exploitable"
elif [[ "$VULN_PHP" -eq 1 && "$VULN_NGINX" -eq 0 ]]; then
  RESULT="VULNERABLE"
  echo ""
  echo "==> VULNERABLE: PHP version is affected. Nginx config may not be exploitable but upgrade PHP immediately."
elif [[ "$VULN_PHP" -eq 0 ]]; then
  RESULT="PATCHED"
  echo ""
  echo "==> PATCHED: PHP version is not in the vulnerable range"
else
  echo ""
  echo "==> UNKNOWN: Could not determine full exposure"
fi

exit 0
07 · Bottom Line

If you remember one thing.

TL;DR
If Tenable plugin 130276 is firing in your environment in 2026, you have a seven-year-old unpatched unauthenticated RCE on an internet-facing stack with a live Metasploit module and CISA KEV listing. This is a hair-on-fire finding. Per the noisgate mitigation SLA for CRITICAL, deploy the try_files $uri =404; nginx config fix or WAF block within 3 days — this afternoon if possible. Per the noisgate remediation SLA, complete the PHP upgrade to 8.x (the only supported branch) within 90 days. Every affected PHP 7.1/7.2/7.3 instance is also missing years of other security patches across dozens of CVEs, so the upgrade is non-negotiable. Prioritize any host in a DMZ or serving customer-facing traffic. If you cannot upgrade PHP within 90 days, formally accept the risk at CISO level and document it — running EOL PHP on the internet is an audit finding on its own.

Sources

  1. Tenable Plugin 130276
  2. Tenable Blog — CVE-2019-11043 Analysis
  3. neex/phuip-fpizdam — Original Exploit
  4. Exploit-DB — Metasploit Module
  5. NGINX Official Mitigation Guide
  6. Qualys Blog — CVE-2019-11043 Deep Dive
  7. Tenable CVE Entry — CVE-2019-11043
  8. Knownsec 404 Team — Vulnerability Analysis
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.