CVE-2026-55584 Elastic Security · Elastic

Detect phpSysInfo PSI_ALLOWED IP Allowlist Bypass via Spoofed Forwarding Headers (CVE-2026-55584) in Elastic Security

Detects exploitation of CVE-2026-55584, an authentication/authorization bypass (CWE-290) in phpSysInfo <= 3.4.5. The PSI_ALLOWED IP allowlist trusts client-supplied X-Forwarded-For, Client-IP, and related forwarding headers when deriving the requestor IP. An attacker can inject a spoofed header value matching an allowlisted address to bypass the IP restriction and access the phpSysInfo interface and its JSON/XML system information endpoints (index.php?json, xml.php) that expose host, network, sensor, and mount details. Detection focuses on inbound HTTP requests to phpSysInfo endpoints carrying suspicious or spoofed forwarding headers, particularly private/loopback allowlist values arriving from external source IPs. Fixed in v3.4.6.

MITRE ATT&CK

Tactic
Initial Access Discovery

Elastic Detection Query

Elastic Security (Elastic)
eql
network where event.category == "web" and
  (url.path : "*phpsysinfo*" or url.path : "*index.php*" or url.path : "*xml.php*" or url.query : ("*json*", "*xml*")) and
  (http.request.headers.x-forwarded-for : ("*127.0.0.1*", "*::1*", "*localhost*", "10.*", "192.168.*", "172.16.*") or
   http.request.headers.client-ip : ("*127.0.0.1*", "*10.*", "*192.168.*")) and
  not cidr_match(source.ip, "10.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12", "127.0.0.0/8")
high severity medium confidence

Matches web events to phpSysInfo endpoints where a forwarding header claims an internal/loopback allowlist value but the network source IP is public.

Data Sources

Packetbeat HTTPFilebeat Web Module

Required Tables

logs-*packetbeat-*

False Positives & Tuning

  • Trusted proxy tiers that rewrite XFF with internal addresses.
  • Approved external scanners exercising the endpoint.
  • Health checks routed through infrastructure that injects private XFF values.

Other platforms for CVE-2026-55584


Testing Methodology

Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Spoofed X-Forwarded-For loopback bypass

    Expected signal: Web access log entry with external source IP and XFF header value of 127.0.0.1 targeting index.php?json.

  2. Test 2Spoofed Client-IP private-range bypass

    Expected signal: Access log showing Client-IP: 192.168.1.10 from an external source IP hitting xml.php.

  3. Test 3Windows PowerShell forwarding-header spoof

    Expected signal: IIS/proxy log entry with X-Forwarded-For 10.0.0.5 from an external client to phpSysInfo.


Response Playbook

Triage

  1. Confirm the target host is running phpSysInfo and identify its version; anything <= 3.4.5 is vulnerable to CVE-2026-55584.
  2. Extract the forwarding headers (X-Forwarded-For, Client-IP, X-Real-IP) from the flagged requests and compare the asserted value against the real TCP source IP recorded by the web server/proxy.
  3. Determine whether PSI_ALLOWED is configured on the instance and which addresses it trusts; a spoofed value matching one of those entries confirms an intended bypass.
  4. Review whether the requests reached sensitive endpoints (index.php?json, xml.php) that leak host, network, sensor, and mount data.

Containment

  1. Upgrade phpSysInfo to v3.4.6 or later, which stops trusting client-supplied forwarding headers for PSI_ALLOWED evaluation.
  2. As an interim control, place phpSysInfo behind an authenticated reverse proxy and strip/overwrite inbound X-Forwarded-For, Client-IP, and X-Real-IP headers at the edge before they reach the app.
  3. Restrict network access to the phpSysInfo port with a firewall/ACL so the IP allowlist is enforced at L3 rather than via HTTP headers.

Evidence Collection

  1. Preserve web server access logs and proxy logs containing the spoofed forwarding headers, source IPs, user agents, and requested URIs.
  2. Capture the phpSysInfo JSON/XML responses returned to the attacker to scope what system information was disclosed.
  3. Snapshot the phpSysInfo configuration (phpsysinfo.ini) showing the PSI_ALLOWED value and version at time of incident.

Escalation Criteria

  • !Escalate if spoofed-header requests successfully retrieved phpSysInfo system information (HTTP 200 to json/xml endpoints), indicating confirmed disclosure.
  • !Escalate if the same external source IP subsequently pivots to enumeration, credential access, or other hosts, suggesting the leaked host/network detail was used for follow-on activity.

Investigation Guide

Related Techniques

Forensic Artifacts

  • >Web server access logs showing X-Forwarded-For/Client-IP values inconsistent with the connecting socket IP.
  • >phpsysinfo.ini configuration containing the PSI_ALLOWED allowlist.
  • >HTTP responses from index.php?json / xml.php recording disclosed system information.

Tuning Guidance

Baseline your legitimate reverse proxy and load balancer IPs and exclude their appended XFF chains, since those are trusted rewrites rather than spoofs. If phpSysInfo sits directly behind a CDN, focus the detection on the left-most (client-asserted) XFF value rather than the full chain. Suppress known scanner and monitoring source IPs. After upgrading to 3.4.6 the header is no longer authoritative, so alerts should be treated as recon attempts rather than successful bypasses.


Hunting Queries

Hunt for external clients presenting private/loopback forwarding-header values while accessing phpSysInfo endpoints, over a wide lookback window.

Hunting — KQL
kql
W3CIISLog | where csUriStem has_any ("index.php","xml.php","phpsysinfo") | extend xff=tostring(column_ifexists("csXForwardedFor","")) | where xff has_any ("127.0.0.1","192.168.","10.","::1") and not(ipv4_is_private(tostring(cIP))) | summarize count() by tostring(cIP), xff, csUriStem
Hunting — SPL
spl
index=web (uri_path="*phpsysinfo*" OR uri_path="*xml.php*" OR uri_query="*json*") | eval xff=coalesce('http_x_forwarded_for','client_ip') | regex xff="(127\.0\.0\.1|::1|10\.|192\.168\.)" | where NOT cidrmatch("10.0.0.0/8",src_ip) AND NOT cidrmatch("192.168.0.0/16",src_ip) | stats count by src_ip, xff, uri_path

Atomic Red Team Tests

Test 1 Spoofed X-Forwarded-For loopback bypass
linux

Sends a phpSysInfo JSON request with an X-Forwarded-For header asserting 127.0.0.1 to bypass a PSI_ALLOWED loopback allowlist.

Command

bash
curl -s -H 'X-Forwarded-For: 127.0.0.1' 'http://target.lab/phpsysinfo/index.php?json' -o /tmp/psi_bypass.json

Cleanup

bash
rm -f /tmp/psi_bypass.json

Expected Telemetry

Web access log entry with external source IP and XFF header value of 127.0.0.1 targeting index.php?json.

Expected Detection

Detection fires on the mismatch between the loopback XFF value and the public source IP.

Test 2 Spoofed Client-IP private-range bypass
linux

Uses a Client-IP header asserting a private allowlisted address against the phpSysInfo XML endpoint.

Command

bash
curl -s -H 'Client-IP: 192.168.1.10' 'http://target.lab/phpsysinfo/xml.php?plugin=complete' -o /tmp/psi_xml.xml

Cleanup

bash
rm -f /tmp/psi_xml.xml

Expected Telemetry

Access log showing Client-IP: 192.168.1.10 from an external source IP hitting xml.php.

Expected Detection

Detection fires on private-range forwarding header from a public source.

Test 3 Windows PowerShell forwarding-header spoof
windows

Issues a phpSysInfo request from Windows with a spoofed X-Forwarded-For header to test allowlist bypass telemetry.

Command

powershell
powershell -Command "Invoke-WebRequest -Uri 'http://target.lab/phpsysinfo/index.php?json' -Headers @{'X-Forwarded-For'='10.0.0.5'} -OutFile $env:TEMP\psi.json"

Cleanup

powershell
powershell -Command "Remove-Item $env:TEMP\psi.json -ErrorAction SilentlyContinue"

Expected Telemetry

IIS/proxy log entry with X-Forwarded-For 10.0.0.5 from an external client to phpSysInfo.

Expected Detection

Detection fires on the spoofed private XFF value from an external source IP.

Related Detections