CVE-2026-118423: WP Libre Form File Upload to RCE

– min read

If you run a WordPress site with any kind of contact or upload form, watch this one. Plugin WP Libre Form version 1.5.0.1 stores file uploads without checking the file type. The handler is registered under the nopriv hook – no login required. I set up a local lab to verify the chain end-to-end, and it works exactly as described: unauthenticated multipart POST → PHP landing in the uploads folder → RCE as the web server user.

NVD · Full report (im0xfay) · WordPress plugin archive (closed)

Lab terminal upload and RCE
Lab: unauthenticated upload via admin-ajax followed by RCE execution of the id command

Attack path flow diagram
Three unauthenticated endpoints converging on the same vulnerable move_uploaded_file sink

Overview

CVE-2026-118423 is a CVSS 10.0 (Critical) arbitrary file upload vulnerability in the WP Libre Form plugin (CWE-434).

Field Value
CVE CVE-2026-118423
CVSS 10.0 · AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
CWE CWE-434: Unrestricted Upload of File with Dangerous Type
Vulnerable versions All releases 1.0.1 through 1.5.0.1
Fixed version None – plugin removed from WP.org 2026-09-08
Prerequisite At least one published wplf-form (often present on Contact pages)

Technical Deep Dive

The plugin hooks its submission handler to wp_ajax_nopriv_wplf_submit (line 7 of inc/wplf-ajax.php). The _nopriv_ suffix means WordPress exposes this endpoint to unauthenticated visitors – deliberately. The same handler is also registered as a REST route at wplf/v1/submit without a permission_callback argument.

When a file arrives, the handler runs move_uploaded_file() directly (line 82). The plugin author left a comment on line 66: “Is this enough security wise?” – it was not. The file name is sanitised only through sanitize_file_name() which strips dangerous characters but preserves the .php extension. No wp_check_filetype() call, no MIME-type check, no blacklist.

Root Cause

The core failing is on line 82 of inc/wplf-ajax.php: move_uploaded_file() called on an arbitrary $_FILES entry without any extension filter, MIME-type check, or wp_check_filetype_and_ext() call. WordPress core provides media_handle_upload() which does reject .php uploads (the _wplf_media_library meta path uses it and is safe), but the plugin’s own bypass path skips it entirely.

Lab Proof of Concept

I reproduced the exploit on an isolated local environment (PHP 8.5 + MariaDB 11.8 + WordPress 6.7.1 on a loopback interface with RFC 5737 addresses). The plugin 1.5.0.1 was downloaded from the official WordPress.org archive.

Phase 1 – fingerprint the plugin

Phase 2 – enumerate form ID

Phase 3 – upload a PHP canary

Phase 4 – locate and execute

Phase 5 – verify alt endpoints

All three endpoint variants confirmed. The canary files were deleted after capture; no test accounts or sessions persisted.

Detection

Layer Detection Signal
Access log POST /wp-admin/admin-ajax.php with action=wplf_submit from unauth IPs
Access log POST /wp-json/wplf/v1/submit or ?rest_route=/wplf/v1/submit
Access log GET /wp-content/uploads///lf_*.php with query parameters
WordPress DB wp_posts with post_type=wplf-submission created outside normal user sessions
Filesystem wp-content/uploads/ containing .php files with lf_ prefix
WAF Block multipart POST with filename=*.php matching admin-ajax + action=wplf_submit

Mitigation

Since the plugin has no fixed version (removed from WordPress.org on 8 September 2026), the only safe action is to delete it altogether.

Action Detail
Remove plugin Deactivate and delete wp-libre-form from the plugins page
Block PHP in uploads (Nginx) location ~* /wp-content/uploads/.*\.php$ { deny all; }
Block PHP in uploads (Apache) php_admin_flag engine off
WAF rule Block admin-ajax.php POST with action=wplf_submit + filename=*.php
Audit uploads Search wp-content/uploads for lf_*.php or webshell content
Audit submissions Inspect wp_posts where post_type = “wplf-submission”

Context

This is not the first time a WordPress plugin bypassed the core upload gate. A similar gap powered the PHP session-upload-progress RCE chain (CVE-2026-109618/CVE-2026-109619) earlier this year. For server-side hardening, the WordPress Core Upgrade RCE analysis (CVE-2026-119977) covers the full picture. Log monitoring setup is in the NGINX access log analysis guide.

The WP Libre Form plugin was closed on 8 September 2026. If you still have it active today, treat it as compromised until proven otherwise. Patch the upload path, not the plugin.

Mohamad ZulfahmyCybersecurity · OffSec · Entrepreneur
About me ↗
ON THIS PAGE
On this page