VT-2026-87902

WordPress Core - Unauthenticated Page Template Path Traversal to RCE

CRITICAL 9.2CVElfipath-traversalrceunauthenticated

Run this lab

$vt start --id vt-2026-87902

Lab not starting or behaving wrong? Report a problem with this lab

Summary

WordPress Core versions prior to 7.1.2 (and the unpatched maintenance releases of older branches) contain an unauthenticated path traversal in page-template resolution. get_page_template() builds the candidate "page-{pagename}.php" from a urldecoded pagename query variable without validating it, so a double-encoded traversal sequence makes locate_template() include a chosen readable local .php file outside the active theme. When the active theme has a top-level page-* directory (e.g. Twenty Twelve, Twenty Fourteen, Neve, Hestia, Sydney) and the server ships pearcmd.php with register_argc_argv enabled (official php Docker image), this leads to remote code execution.

Technical detail

The flaw is in get_page_template() in wp-includes/template.php. The pagename query variable is urldecoded and, when the decoded value differs from the raw value, appended to the template candidate list as "page-{decoded}.php" with no validate_file() check (added in the 7.1.2 fix). locate_template() then resolves that candidate relative to the active theme directory, so a traversal sequence reaches arbitrary readable .php files. Two preconditions widen impact: the active theme must contain a top-level directory whose name starts with "page-" (classic themes such as Twenty Twelve ship page-templates/), and for RCE a reachable .php such as PEAR's pearcmd.php must exist with register_argc_argv enabled - both true on the official php/wordpress Docker image.

Impact

An unauthenticated attacker can include local PHP files outside the active theme, disclosing sensitive data. Where pearcmd.php is reachable and register_argc_argv is on, the inclusion is escalated to unauthenticated remote code execution running as the web-server account, leading to full site compromise.

Exploitation & proof of concept

Local PHP file inclusion via pagename traversal

A double-encoded traversal in the pagename query variable escapes the theme's page-templates/ directory and reaches the WordPress root, so wp-links-opml.php is included and returns its OPML document instead of the normal page body.

POST/param=pagename

REQUEST
POST /?page_id=4&pagename=templates%252F%252E%252E%252F%252E%252E%252F%252E%252E%252F%252E%252E%252Fwp-links-opml HTTP/1.1
Host: {{Hostname}}
Content-Length: 0
RESPONSE
HTTP/1.1 200 OK
Content-Type: text/xml; charset=UTF-8

Nuclei detection: vt-2026-87902.nuclei.yaml

Remediation

  • Update WordPress to 7.1.2 or the patched maintenance release for the installed branch
  • Apply fix commit fdeab470f4b4062462cf8ccdc788f258683c2d6f (validate_file guard in get_page_template)
  • Disable register_argc_argv and remove pearcmd.php from production PHP installs

Lab setup notes

  • Wait for vt-2026-87902-init to report INSTALL_OK (core install + Twenty Twelve + a published page)
  • Access the application at http://localhost:8787
  • Run: nuclei -t vt-2026-87902.nuclei.yaml -u http://localhost:8787

References