StoryChief WordPress Plugin Unauthenticated Arbitrary File Upload via Webhook (CVE-2025-7441)
by Pwdnx1337 · 2026-07-06
- Severity
- Critical
- CVE
- CVE-2025-7441
- Category
- web
- Affected product
- StoryChief WordPress plugin
- Affected versions
- 1.0.42 (per source repository)
- Disclosed
- 2026-07-06
- Patch status
- unpatched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-06 |
| Last Updated | 2026-07-06 |
| Author / Researcher | Pwdnx1337 |
| CVE / Advisory | CVE-2025-7441 |
| Category | web |
| Severity | Critical |
| CVSS Score | 9.8 (per NVD) |
| Status | PoC |
| Tags | storychief, wordpress, wordpress-plugin, arbitrary-file-upload, ssrf, remote-code-execution, unauthenticated, webhook, hmac, cwe-434, python |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | StoryChief WordPress plugin |
| Versions Affected | 1.0.42 (per source repository) |
| Language / Platform | Python 3 PoC targeting a PHP/WordPress plugin backend |
| Authentication Required | No |
| Network Access Required | Yes |
Summary
The StoryChief WordPress plugin exposes an unauthenticated REST webhook endpoint (/wp-json/storychief/webhook) that accepts a JSON payload describing a “published” story, including a data.featured_image.data.sizes.full field containing a URL. The plugin performs a server-side HTTP GET on that attacker-supplied URL and persists the fetched content directly into the public WordPress uploads directory without validating the source domain, MIME type, or file extension. Because the endpoint only checks an HMAC signature over the payload (computed with an empty/known key in the reference implementation) rather than requiring real authentication, an unauthenticated attacker can plant an arbitrary file — including a .php webshell — at a predictable path (wp-content/uploads/<YEAR>/<MM>/<filename>). If the hosting environment executes PHP inside the uploads directory, this results in unauthenticated remote code execution and full site compromise.
Vulnerability Details
Root Cause
The webhook handler builds the payload structure and blindly fetches whatever URL is embedded under featured_image, without an allowlist of trusted domains or content-type/extension validation, then writes the fetched bytes to a public, potentially execution-capable directory. The PoC constructs this exact payload shape and signs it with an empty HMAC key, which the target’s webhook signature check apparently accepts as valid:
| |
The resulting file is saved under a date-based public path (wp-content/uploads/YYYY/MM/<basename-of-file_url>), which the PoC then polls to confirm successful upload.
Attack Vector
- Attacker hosts a malicious file (e.g. a PHP webshell) at a URL they control.
- Attacker builds a JSON payload placing that URL in
data.featured_image.data.sizes.full, computes an HMAC-SHA256 signature over the escaped JSON using an empty key, and places it inmeta.mac. - Attacker POSTs the signed payload to
<target>/wp-json/storychief/webhookwithContent-Type: application/json. - The plugin fetches the URL server-side and stores the file under the public uploads directory using the original filename from the URL.
- Attacker requests
<target>/wp-content/uploads/<YEAR>/<MM>/<filename>directly; if PHP execution is permitted in that directory, the planted file executes with the web server’s privileges.
Impact
Unauthenticated arbitrary file upload / SSRF-driven file plant leading to remote code execution and full compromise of the WordPress site (and potentially the underlying host), limited only by whether the hosting environment executes PHP from the uploads directory.
Environment / Lab Setup
Target: WordPress site running the StoryChief plugin (version 1.0.42 or vulnerable range)
Attacker: Python 3 with `requests` library (optional: `curl` binary for --use-curl fallback)
Attacker-controlled HTTP host to serve the payload file referenced by --file-url
Network reachability from the target server to the attacker's file URL (server-side fetch)
Proof of Concept
PoC Script
See
CVE-2025-7441.pyin this folder.
| |
Detection & Indicators of Compromise
POST /wp-json/storychief/webhook with a JSON body containing
data.featured_image.data.sizes.full = <external URL>
Outbound HTTP requests from the WordPress server to unfamiliar/attacker domains
immediately following a request to /wp-json/storychief/webhook
Newly created files in wp-content/uploads/<YEAR>/<MM>/ with unexpected
extensions (.php, .phtml, etc.) not matching normal media uploads
Signs of compromise:
- Unexpected
.phpor script files present underwp-content/uploads/ - Server-side HTTP fetches to unknown external hosts correlated with webhook POSTs
- Successful HTTP 200 responses when directly requesting a suspicious uploads path
- Unusual admin-ajax or webshell-style requests following an uploads-directory hit
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade StoryChief plugin to a patched version once available; no official patched version identified at time of mirroring — see references |
| Interim mitigation | Block or restrict /wp-json/storychief/webhook via WAF/server rules, disable PHP execution in wp-content/uploads/, restrict outbound egress from the web server to untrusted domains, and enforce real webhook authentication/signature verification with a secret (non-empty) key |
References
Notes
Mirrored from https://github.com/Pwdnx1337/CVE-2025-7441 on 2026-07-06. The PoC script includes an extra --bypass-with-cve-2026-33691 flag that pads the file extension with whitespace to attempt a WAF/OWASP-CRS bypass; this is unrelated to the core CVE-2025-7441 vulnerability logic but is bundled in the same script.
| |