PHP2Shell: Read our blog on the critical RCE vulnerabilities affecting 70% of the Internet

CVE-2026-31317: 
PHP vulnerability analysis and mitigation

Overview

CVE-2026-31317 is a Server-Side Request Forgery (SSRF) vulnerability in the CraftQL plugin (a GraphQL server for Craft CMS) affecting versions 1.3.7 and earlier. The flaw resides in vendor/markhuot/craftql/src/Listeners/GetAssetsFieldSchema.php and allows unauthenticated attackers to make the server issue arbitrary requests, potentially leading to remote code execution and internal resource access. It was published on April 17, 2026, with a GitHub Advisory (GHSA-8wmw-prw8-2ggm) reviewed on April 18, 2026. The CVSS v3.1 base score is 7.5 (High), and the CVSS v4 overall score is 6.9 (Moderate) (Github Advisory, Feedly).

Technical details

The root cause is CWE-918 (Server-Side Request Forgery): the GetAssetsFieldSchema.php file at line 56 directly passes user-supplied URLs from GraphQL Asset field mutations to PHP's file_get_contents() without any validation or sanitization (PoC Repo). Because file_get_contents() supports multiple PHP URL wrappers — including file://, http://, https://, gopher://, and dict:// — an attacker can supply arbitrary protocol handlers to read local files, probe internal network services, or interact with cloud metadata endpoints. The only precondition is possession of a valid GraphQL token, which may be obtainable through self-service registration depending on site configuration. A public PoC repository including Python and Bash exploit scripts has been published (PoC Repo).

Impact

Successful exploitation allows an unauthenticated (or minimally authenticated) network attacker to read arbitrary local files (e.g., /etc/passwd, .env containing database credentials and API keys), enumerate and probe internal network services (Redis, MySQL, SSH), and steal cloud provider IAM credentials via metadata endpoints (AWS 169.254.169.254, GCP, Azure) (PoC Repo). The primary impact is high confidentiality loss, with secondary risks including lateral movement into internal networks and supply chain compromise via stolen internal API credentials. Availability and integrity of the vulnerable system itself are not directly impacted, but downstream systems accessible via SSRF may be compromised.

Exploitability

A public PoC repository containing working Python and Bash exploit scripts has been published by researcher 'stormmmg' (PoC Repo). As of disclosure, there is no confirmed evidence of active in-the-wild exploitation, and no threat actor attribution has been reported (Github Advisory). The EPSS score is approximately 0.005% (very low probability of exploitation in the next 30 days), and the vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog. The GitHub Advisory notes no patched version has been released for the markhuot/craftql Composer package as of the advisory date.

Exploitation steps

  1. Reconnaissance: Identify Craft CMS installations running CraftQL ≤ 1.3.7 by checking composer.lock for markhuot/craftql or by probing the GraphQL endpoint (typically /api or /graphql). Tools like Shodan or Censys can identify exposed Craft CMS instances.
  2. Obtain a GraphQL Token: Acquire a valid CraftQL API token — this may be available via self-service registration, a leaked .env file, or prior credential exposure.
  3. Craft a malicious GraphQL mutation: Construct a mutation targeting an Asset field with a url parameter pointing to the desired resource. For local file read:
mutation {
  upsertTestDefault(
    title: "SSRF Test"
    heroImage: {url: "file:///etc/passwd"}
  ) { id }
}
  1. Exfiltrate sensitive data: Replace the url value with targets such as file:///var/www/html/.env (database credentials), http://169.254.169.254/latest/meta-data/iam/security-credentials/ (AWS IAM keys), or internal service addresses for port scanning.
  2. Internal network pivoting: Use http://192.168.x.x:<port>/ URLs to enumerate internal services; timing differences (timeouts vs. fast responses) indicate open vs. closed ports.
  3. Leverage stolen credentials: Use exfiltrated database passwords, API keys, or cloud IAM credentials for lateral movement or further compromise (PoC Repo).

Indicators of compromise

  • Network: Outbound HTTP/HTTPS requests from the web server to internal RFC-1918 addresses (10.x.x.x, 172.16.x.x, 192.168.x.x) or cloud metadata IPs (169.254.169.254); outbound requests using non-HTTP protocols (gopher://, dict://) originating from the PHP process.
  • Logs: Craft CMS or web server access logs showing GraphQL mutation requests to the API endpoint with heroImage or asset field parameters containing file://, http://169.254., or internal IP URLs; PHP error logs referencing file_get_contents failures on unusual URLs.
  • File System: Unexpected temporary files in the Craft assets temp directory (storage/runtime/temp/) containing contents of system files (e.g., /etc/passwd content) or cloud metadata responses.
  • Detection Script: Presence of unvalidated file_get_contents($remoteUrl) in vendor/markhuot/craftql/src/Listeners/GetAssetsFieldSchema.php (line ~56) confirms vulnerability; run: grep -n "file_get_contents" vendor/markhuot/craftql/src/Listeners/GetAssetsFieldSchema.php (PoC Repo).

Mitigation and workarounds

No patched version of markhuot/craftql has been released as of the advisory date — the GitHub Advisory lists affected versions as ≤ 1.3.7 with no patched version available (Github Advisory). Immediate mitigations include: (1) disabling the CraftQL plugin if GraphQL is not required; (2) restricting GraphQL API access to trusted IP ranges via firewall or web server configuration; (3) revoking all existing GraphQL tokens and regenerating with minimal permissions; (4) implementing network egress controls to block outbound requests from the web server to internal RFC-1918 ranges and cloud metadata endpoints; and (5) deploying WAF rules to detect and block SSRF payloads in GraphQL mutations. Code-level fixes include whitelisting only http/https schemes, blocking private IP ranges, and replacing file_get_contents() with a hardened HTTP client such as Guzzle with redirect following disabled (PoC Repo).

Community reactions

The vulnerability was noted on Bluesky via automated CVE tracking accounts shortly after disclosure. A security blog post was published at infinitsec.net covering the CraftQL SSRF. No official statement from the CraftQL maintainer (markhuot) has been publicly issued, and the repository shows no patch commits addressing this vulnerability as of the advisory date. Community reaction has been limited given the niche scope of the affected plugin.

Additional resources


Source: This report was generated using AI

Related PHP vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-3qcx-mjf6-48vjHIGHN/A
  • PHP logoPHP
  • craftcms/commerce-mollie
NoYesOct 23, 2026
GHSA-5v62-pcq7-fxj9LOWN/A
  • PHP logoPHP
  • craftcms/cms
NoYesOct 23, 2026
GHSA-hvp5-pwxx-2752LOWN/A
  • PHP logoPHP
  • craftcms/cms
NoYesOct 23, 2026
GHSA-mp59-9rf5-93wrMEDIUMN/A
  • PHP logoPHP
  • craftcms/cms
NoYesOct 23, 2026
GHSA-xpg7-m6gm-4xfhMEDIUMN/A
  • PHP logoPHP
  • craftcms/cms
NoYesOct 23, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management