Critical WordPress Alert: Dissecting CVE-2026-15748 (Forminator RCE) & CVE-2026-15826 (UPB Auth Bypass)

The CyberSec Guru

CVE-2026-15748

If you like this post, then please share it:

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Why your support matters: Zero paywalls: Keep the main content 100% free for learners worldwide.

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

In August 2026, the WordPress security landscape was rocked by the disclosure of two catastrophic, pre-authentication vulnerabilities affecting over 640,000 active installations across the ecosystem. Tracked as CVE-2026-15748 (Forminator Forms) and CVE-2026-15826 (User Profile Builder), both flaws have been assigned a maximum severity CVSS v3.1 score of 9.8 (Critical).

What makes these vulnerabilities particularly terrifying is not just their impact—which ranges from unauthenticated Remote Code Execution (RCE) to complete administrative takeover—but the elegance of their exploitation. Neither requires a registered user account, brute-forcing, or complex social engineering. They are silent, automated, and devastating.

In this comprehensive, deep-dive analysis, we will deconstruct the exact PHP logic failures, type confusion traps, and architectural oversights that led to these critical flaws. We will provide actionable threat-hunting methodologies, Web Application Firewall (WAF) rules, and server-level hardening techniques to protect your infrastructure.

The Breakdown of CVE-2026-15748: Forminator Pre-Auth RCE

Affected Software: Forminator Forms – Contact Form, Payment Form & Custom Form Builder
Affected Versions: <= 1.56.1
Patched Version: 1.56.2 (Released July 31, 2026)
Researcher Credit: “daroo” (via Wordfence Bug Bounty)
CWE Classification: CWE-434 (Unrestricted Upload of File with Dangerous Type)

Forminator is a powerhouse in the WordPress ecosystem, utilized by hundreds of thousands of sites for complex drag-and-drop form building, quizzes, and polls. However, its flexibility in handling dynamic field submissions became its Achilles’ heel. CVE-2026-15748 is not a single bug; it is a three-stage exploit chain that chains a logic flaw, a validation bypass, and a server configuration race condition to achieve unauthenticated Remote Code Execution.

The Forged Select Field (Object Injection via Logic Flaw)

To understand the exploit, we must look at how Forminator processes incoming POST requests. When a user submits a form, the Forminator_CForm_Front_Action class iterates through the submitted fields via the set_field_data() method.

Forminator’s generic request sanitizer is designed to be permissive with certain field types (like select-*, radio-*, and checkbox-*), intentionally leaving their nested array values untouched to defer validation to field-specific handlers later in the execution flow.

An attacker leverages this by targeting a form that contains both a File Upload field and a Select field. The attacker submits a malicious payload inside the Select field’s parameter, forging a dictionary that mimics an Upload field configuration.

// VULNERABLE CODE PATH: library/modules/custom-forms/front/front-action.php
private static function set_field_data( $field_id, $field_array, $field_index, ... ) {
// ... [initialization] ...
// The filter allows manipulation of the field data array
$field_data = apply_filters( 'forminator_handle_specific_field_types', $field_data, $form_field_obj, $field_array );
// THE FLAW: If the attacker injects a 'return' key, the entire payload
// is blindly pushed into the global processing array without sanitization.
if ( ! empty( $field_data['return'] ) ) {
unset( $field_data['return'] );
self::$info['field_data_array'][] = $field_data; // Attacker payload injected here
return;
}
}

Because the plugin trusts the field_type declared in this injected array, the subsequent upload processing phase treats this forged Select field payload as a legitimate File Upload configuration.

Bypassing the Blocklist via Regex/Pipe Injection

Once the attacker has injected their forged upload configuration, they must bypass Forminator’s security controls. The plugin attempts to strip dangerous file extensions using the forminator_allowed_mime_types() function.

📬 Stay Ahead of Cyber Threats

Get the latest cybersecurity news, critical vulnerabilities, threat intelligence, tutorials, and exclusive giveaways delivered straight to your inbox. No spam. Unsubscribe anytime.

Subscribe to the Newsletter →
// VULNERABLE CODE PATH: library/helpers/helper-fields.php
function forminator_allowed_mime_types( $mimes = array(), $allow = true ) {
if ( ! $allow ) {
$filters = array( 'htm|html', 'js', 'jar', 'php', 'php3', 'php4', 'phtml', 'exe', 'sh' /* ... */ );
foreach ( array_keys( $mimes ) as $mime_key ) {
$key = strtolower( $mime_key );
// THE FLAW: Strict exact-key matching (in_array with strict=true)
if ( in_array( $key, $filters, true ) ) {
unset( $mimes[ $mime_key ] );
}
}
}
return $mimes;
}

The blocklist uses in_array() with strict type checking. It successfully blocks the literal string 'php'. However, it fails to account for how WordPress core’s wp_check_filetype() function evaluates MIME types. WordPress core supports regex-like pipe alternatives in its MIME arrays.

An attacker supplies the additional-type configuration in their forged payload as:
ph(p)|text/x-php

  1. Forminator’s in_array check looks for 'php'. It does not find 'ph(p)', so it allows it.
  2. WordPress core’s wp_check_filetype() receives ph(p)|text/x-php.
  3. The core regex engine interprets ph(p) as a valid pattern that perfectly matches the .php file extension.
  4. The malicious PHP webshell passes validation and is written to the disk.

The Custom Storage .htaccess Race Condition

By default, Forminator is relatively safe because it uploads files to a directory protected by an .htaccess file containing php_flag engine off, which prevents the Apache web server from executing PHP files in that directory.

However, many enterprise sites configure a Custom File Upload Storage root (e.g., an S3 bucket mounted via FUSE, or a custom off-web-root directory). The vulnerability here is a race condition in the plugin’s architecture. The .htaccess file for custom directories is only generated “when it is first needed, during a frontend request where the WordPress helper responsible for writing the .htaccess file is not loaded.”

Because the helper isn’t loaded during the specific AJAX upload request, the protection file is never created. The attacker simply sends a direct HTTP GET request to the newly uploaded shell.php file, and the server executes it, granting the attacker a reverse shell as the www-data user.

The Breakdown of CVE-2026-15826: User Profile Builder Admin Takeover

Affected Software: User Profile Builder – Beautiful User Registration Forms
Affected Versions: <= 3.16.4
Patched Version: 3.16.5 (Released July 16, 2026)
Researcher Credit: Supakiad S. (m3ez)
CWE Classification: CWE-843 (Access of Resource Using Incompatible Type / Type Confusion)

While Forminator suffers from a complex multi-stage upload chain, User Profile Builder (UPB) falls victim to a classic, yet devastating, PHP type confusion flaw rooted in improper error handling order. This vulnerability allows an unauthenticated attacker to instantly log in as the site’s primary administrator (User ID 1).

The Mechanism: Coercing a WP_Error into 1

UPB features an “Automatically Log In after Registration” setting, designed to improve UX by bypassing email confirmation for new users. When a user submits the registration form, the plugin calls WordPress core’s wp_insert_user() function.

WordPress core strictly enforces a maximum username length of 60 characters (user_login column in the wp_users table is VARCHAR(60)). If an attacker submits a registration request with a username between 61 and 70 characters, wp_insert_user() gracefully fails and returns a WP_Error object.

The fatal flaw exists in the wppb_log_in_user() function. The plugin attempts to sanitize the $user_id variable, but it does so before checking if the variable is actually an error object.

// VULNERABLE CODE PATH: front-end/wppb.register.php
function wppb_log_in_user( $redirect, $redirect_old, $user_id ) {
if ( is_user_logged_in() ) { return; }
// ... [settings retrieval] ...
// THE FLAW: absint() is called BEFORE is_wp_error()
$user_id = absint( $user_id );
// Because $user_id is now an integer, this check FAILS to catch the error
if ( ! $user_id || is_wp_error( $user_id ) ) {
return $redirect_old;
}
// $user_id is now the integer 1.
// get_userdata(1) fetches the primary admin created during WP install.
$user = get_userdata( $user_id );
// The plugin generates a valid transient-backed autologin nonce for User ID 1
$redirect = add_query_arg( wppb_get_autologin_query_args( $user_id ), $redirect );
wp_redirect( $redirect );
}

The Exploitation Chain Explained

  1. The Trigger: The attacker targets a registration form with “Automatically Log In” enabled.
  2. The Payload: The attacker submits a payload with a 65-character username (e.g., attacker_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa).
  3. The Core Rejection: wp_insert_user() rejects the long username and returns a WP_Error object.
  4. The Type Coercion: absint( WP_Error ) is executed. In PHP, when an object without a __toString() method or specific numeric casting is passed to integer conversion functions, it often defaults to 1 (or throws a notice/warning depending on the PHP version, but absint() forces the integer 1).
  5. The Bypass: is_wp_error( 1 ) evaluates to false.
  6. The Takeover: get_userdata( 1 ) successfully retrieves the site’s primary administrator account (User ID 1 is historically the default admin created during the WordPress 5-minute install).
  7. The Session Hijack: The plugin generates a valid, transient-backed autologin nonce tied to User ID 1 and redirects the attacker, granting them a fully authenticated, permanent administrator session.

CVSS Vector Breakdown & Threat Landscape

Both vulnerabilities share the same terrifying CVSS v3.1 Vector String:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Let’s break down what this means for your threat landscape using BERT-friendly semantic analysis:

  • AV:N (Attack Vector: Network): The attack is executed remotely over the internet via standard HTTP/HTTPS requests. No local access or LAN proximity is required.
  • AC:L (Attack Complexity: Low): The attacker does not need to win a race condition, guess cryptographic nonces, or gather specialized intel about the target. The exploit works out-of-the-box against vulnerable configurations.
  • PR:N (Privileges Required: None): This is the most critical metric. The attacker does not need a subscriber account, a customer login, or an administrator password. They are completely unauthenticated.
  • UI:N (User Interaction: None): No phishing is required. An administrator does not need to click a malicious link in the WordPress backend. The attack is entirely automated.
  • S:U (Scope: Unchanged): The vulnerability compromises the WordPress application itself, though the subsequent RCE (in Forminator) can easily pivot to the underlying operating system.
  • C:H / I:H / A:H (Confidentiality, Integrity, Availability: High): The attacker can dump the wp-config.php database credentials (Confidentiality), inject malicious SEO spam or backdoors into every post (Integrity), and wipe the database or launch DDoS attacks from the server (Availability).

The Automated Threat Landscape

Because both vulnerabilities require zero authentication and rely on standard HTTP POST requests, they are prime targets for botnet automation. Threat actors are currently deploying mass-scanners (similar to those used for the 2024 LiteSpeed Cache and GiveWP vulnerabilities) that crawl the Alexa Top 1 Million, identify Forminator and UPB endpoints, and fire the exploit payloads in milliseconds. If you are reading this and have not patched, your server logs are likely already filled with exploit attempts.

Threat Hunting: Indicators of Compromise (IoCs)

Security Operations Centers (SOCs) and WordPress administrators must immediately hunt their web server logs (Apache access.log, Nginx access.log, or WAF logs) for signs of exploitation.

Hunting for CVE-2026-15748 (Forminator)

Because the exploit relies on injecting a forged array into a Select field, the POST body will contain anomalous nested structures.

Log Analysis Strategy:
Look for POST requests to admin-ajax.php where the action is forminator_submit_form_custom_forms. You are looking for URL-encoded or JSON strings containing ph(p) or text/x-php within the form data payload.

Regex for Splunk / ELK / grep:

# Search Nginx/Apache access logs for the MIME bypass signature
grep -E "POST.*admin-ajax\.php.*forminator_submit.*ph\(p\)" /var/log/nginx/access.log

File System Auditing:
Attackers will upload webshells to the Forminator upload directory. Run this command to find PHP files created in the last 30 days inside the uploads folder:

find /var/www/html/wp-content/uploads/forminator/ -type f -name "*.php" -mtime -30 -ls
find /var/www/html/wp-content/uploads/forminator/ -type f -name "*.phtml" -mtime -30 -ls

Hunting for CVE-2026-15826 (User Profile Builder)

You are looking for registration attempts with abnormally long usernames, followed immediately by administrative actions from the same IP address.

Regex for Splunk / ELK / grep:

# Look for user_login parameters exceeding 60 characters
grep -E "POST.*/register/.*user_login=[a-zA-Z0-9_]{61,70}" /var/log/nginx/access.log

Database Auditing:
Check for suspicious transients that may have been generated to facilitate the autologin.

SELECT * FROM wp_options
WHERE option_name LIKE '_transient_wppb_autologin_%'
AND option_value LIKE '%1%';

Note: If you find active transients logging in User ID 1 from unknown IP addresses, your site has been compromised.


Advanced Mitigation & Defense-in-Depth Strategies

Patching the plugins to Forminator 1.56.2 and User Profile Builder 3.16.5 is the primary remediation. However,true EEAT (Experience, Expertise, Authoritativeness, Trustworthiness) in cybersecurity dictates that we never rely solely on application-level patches. We must implement Defense-in-Depth.

Web Application Firewall (WAF) Rules

If you are using ModSecurity, Cloudflare, or AWS WAF, deploy these virtual patches immediately to block the exploit payloads at the network edge.

ModSecurity Rule for CVE-2026-15748 (Forminator MIME Bypass):

SecRule REQUEST_BODY "@rx ph\(p\)|text\/x-php" \
"id:202615748,\
phase:2,\
block,\
t:none,\
msg:'CVE-2026-15748 Forminator Arbitrary File Upload Attempt',\
tag:'attack-rce',\
tag:'cve/2026-15748',\
severity:'CRITICAL'"

ModSecurity Rule for CVE-2026-15826 (UPB Long Username):

SecRule ARGS:user_login "@rx ^.{61,}$" \
"id:202615826,\
phase:2,\
block,\
t:none,\
msg:'CVE-2026-15826 User Profile Builder Auth Bypass Attempt (Long Username)',\
tag:'attack-auth-bypass',\
tag:'cve/2026-15826',\
severity:'CRITICAL'"

Server-Level Hardening (Immutable Upload Directories)

The Forminator RCE only works if the web server executes the uploaded PHP file. You can completely neutralize this class of vulnerability by configuring your web server to treat upload directories as static asset repositories only.

Nginx Configuration:
Add this block to your Nginx server configuration to deny PHP execution in any WordPress upload directory, including custom Forminator paths.

# Deny PHP execution in wp-content/uploads and Forminator directories
location ~* /wp-content/uploads/.*\.php$ {
deny all;
return 403;
}
location ~* /custom-forminator-storage/.*\.php$ {
deny all;
return 403;
}

Apache Configuration (.htaccess):
If you must use Apache, ensure the following is present in the root of your wp-content/uploads/ directory and any custom storage roots:

# Disable PHP Engine in Uploads
<Files *.php>
Order Allow,Deny
Deny from all
# Modern Apache 2.4+ syntax:
Require all denied
</Files>

Disable XML-RPC and REST API User Enumeration

While not directly related to these CVEs, post-exploitation often involves lateral movement. Disable XML-RPC if unused, and restrict the WordPress REST API /wp-json/wp/v2/users endpoint to prevent attackers from easily confirming that User ID 1 is an active administrator.

The Philosophy of Secure WordPress Plugin Development

For PHP developers and WordPress plugin authors, these two CVEs serve as masterclasses in how seemingly minor logical oversights cascade into catastrophic failures. Let’s extract the core lessons for secure coding.

Lesson 1: Never Trust Nested, Attacker-Controlled Configuration

CVE-2026-15748 demonstrates the danger of trusting nested arrays passed through generic sanitizers. Forminator allowed a Select field to dictate the configuration of an Upload field.
The Rule: Always validate the schema of incoming data against a strict, predefined whitelist. If a form expects a Select field, the backend must reject any payload that attempts to define file-type or upload-method properties. Relying on “exact-string blocklists” (like the php blocklist) is a fundamental anti-pattern. Attackers will always find edge cases in regex and core API interpretations (like ph(p)). Use Allowlists, not Blocklists.

Lesson 2: Validate State Before Coercion

CVE-2026-15826 highlights a fatal flaw in PHP type juggling and WordPress error handling. Calling absint() on a variable that might be a WP_Error object is a textbook anti-pattern.
The Rule: Always check the type and state of an object before attempting to sanitize or coerce it.
The correct, secure implementation for the UPB flaw should have been:

// SECURE IMPLEMENTATION
if ( is_wp_error( $user_id ) ) {
// Handle the error, log it, and abort the login flow
return $redirect_old;
}
$user_id = absint( $user_id );

By reversing the order of operations, the developer inadvertently allowed an object to bypass the error check and masquerade as a valid integer.

Lesson 3: The Danger of “Magic” User IDs

Hardcoding or assuming the existence of User ID 1 as the administrator is a legacy WordPress quirk that continues to haunt the ecosystem. While User ID 1 is usually the admin, in multisite environments or custom setups, it might be a system user. However, because attackers know it’s the primary target, any logic flaw that defaults to 1 (like the absint() coercion) will result in an instant critical severity.

Frequently Asked Questions (FAQ)

My site auto-updates plugins. Am I safe from CVE-2026-15748 and CVE-2026-15826?

Generally, yes. If you have background updates enabled for Forminator and User Profile Builder, WordPress should have automatically applied versions 1.56.2 and 3.16.5 respectively. However, you should manually verify the installed versions in your WordPress dashboard. Furthermore, auto-updates do not clean up webshells that may have been uploaded before the patch was applied. You must still perform a file system audit.

Does CVE-2026-15748 affect me if I don’t use Forminator’s File Upload fields?

No. The exploit chain specifically requires the presence of a published form that contains both a File Upload field and a Select field. If your Forminator forms only consist of text inputs, emails, and radio buttons without file uploads, the attack vector is closed. However, updating is still mandatory to secure the plugin’s underlying codebase against future variations of this bug.

I use User Profile Builder, but I don’t have “Automatically Log In” enabled. Am I vulnerable to CVE-2026-15826?

No. The wppb_log_in_user() function, which contains the vulnerable absint() type confusion, is only triggered if the “Automatically Log In after Registration” setting is active. If users are required to click an email confirmation link or wait for manual admin approval, the exploit chain is broken. Note: You must still update to 3.16.5, as leaving legacy vulnerable code on your server is a security risk.

Can Wordfence or Sucuri block these attacks?

Yes. Premium WAF solutions like Wordfence and Sucuri deployed emergency firewall rules in late July 2026, prior to the public disclosure, to block the specific MIME bypasses and long-username payloads associated with these CVEs. If you are using a premium WAF, ensure your firewall ruleset is up to date. Free versions of these plugins may not include the virtual patching rules required to stop these specific automated scanners.

How do I check if my server has been compromised by the Forminator RCE?

Look for anomalous network traffic originating from your server (e.g., outbound connections to unknown IP addresses on port 443 or 80, which indicate a reverse shell). Check your web server access logs for GET requests to .php files located inside the /wp-content/uploads/ directory. Finally, run a malware scanner like Wordfence or WPScan to detect modified core files or injected backdoors.

The Imperative of Proactive Infrastructure Management

The disclosures of CVE-2026-15748 and CVE-2026-15826 in August 2026 are stark reminders that the WordPress ecosystem, while powerful and flexible, is only as secure as its most complex third-party integrations. The transition from a simple form submission to full server compromise took mere milliseconds for automated botnets.

For System Administrators and DevOps Engineers, the mandate is clear: Application-level security is insufficient. You must enforce server-level execution boundaries (Nginx/Apache PHP denials in upload directories) and maintain rigorous log monitoring.

For WordPress Developers, the lesson is etched in code: Strict schema validation, proper object state checking before type coercion, and a deep understanding of WordPress core’s internal API quirks (like wp_check_filetype regex patterns) are non-negotiable requirements for writing secure software.

Do not wait for a defacement, a ransomware note, or a data breach notification to take action. Audit your plugin inventory today, deploy the WAF rules provided in this guide, and harden your upload directories. In the modern threat landscape, the window between public disclosure and active exploitation is measured in hours, not days.

Stay vigilant, patch promptly, and secure your stack.

Disclaimer: The code snippets, exploit mechanics, and vulnerability analyses provided in this article are for educational, defensive, and authorized security research purposes only. Exploiting vulnerabilities on systems you do not own or have explicit permission to test is illegal and violates international cybercrime laws. Always practice responsible disclosure and ethical hacking.

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Your contribution powers free tutorials, hands-on labs, and security resources.

Why your support matters:
  • Writeup Access: Get complete writeup access within 12 hours
  • Zero paywalls: Keep the main content 100% free for learners worldwide

Perks for one-time supporters:
☕️ $5: Shoutout in Buy Me a Coffee
🛡️ $8: Fast-track Access to Live Webinars
💻 $10: Vote on future tutorial topics + exclusive AMA access

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

If you like this post, then please share it:

News

Discover more from The CyberSec Guru

Subscribe to get the latest posts sent to your email!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from The CyberSec Guru

Subscribe now to keep reading and get access to the full archive.

Continue reading