Back to Blog
Insights

CVE-2026-15748: Forminator Pre-Auth RCE on 600,000 Sites

CVE-2026-15748: Forminator Pre-Auth RCE on 600,000 Sites

Forminator Forms runs on more than 600,000 WordPress sites. Until 31 July 2026, a form on any of them that combined a file-upload field with a dropdown could be talked into accepting a PHP file from a complete stranger.

CVE-2026-15748 is a CVSS 9.8 flaw requiring no login and offering a straight path to a web shell, affecting Forminator Forms up to version 1.56.1, a plugin running on more than 600,000 WordPress sites, and fixed in version 1.56.2 on 31 July 2026. Here is what actually goes wrong, and (the part most write-ups skip) why a large share of Forminator sites were never exploitable at all.

What it is

FieldValue
CVECVE-2026-15748
CVSS v3.19.8 Critical
ClassArbitrary file upload leading to remote code execution
AuthenticationNone. Public form submission
AffectedForminator Forms ≤ 1.56.1
Fixed in1.56.2, released 31 July 2026
Reported byResearcher "daroo", via the Wordfence Bug Bounty Program
RecordNVD: CVE-2026-15748

Are you affected?

Read this section before you panic or relax, because the answer is not simply "are you running Forminator".

Exploitation requires a published form that contains both:

  1. a File Upload field, and
  2. a Select (dropdown) field

Both. A contact form with just name, email and message is not exploitable through this path. A job-application form with a CV upload and a "position applied for" dropdown is the textbook target.

That is an unusually specific precondition for a 9.8, and it is why the honest exposure number is far lower than 600,000. It is also why you cannot answer "are we affected?" from the plugin list alone. Somebody has to look at the forms.

How the bug works

Two separate weaknesses chain together. Neither is enough alone.

1. The blocklist that does not match its own entries

File handling lives in handle_file_upload(). Forminator keeps a blocklist of dangerous extensions and checks an uploaded file against it.

The check uses exact-key matching against a lookup table whose keys are not always single extensions: some entries group several variants into one key using pipe alternatives. A lookup for a single extension therefore fails to match a compound key that contains it. The dangerous extension is on the list, the list is consulted, and the file still passes.

This is a specific instance of a very general failure:

A blocklist is only as good as the assumption that its lookup and its contents use the same format. When the data is richer than the check, entries silently stop counting.

2. The upload configuration the visitor gets to write

The second weakness is what makes the first one reachable. Forminator's public submission handler trusts upload-field configuration supplied in the request: configuration that should come from the saved form definition on the server.

An attacker forges that configuration by injecting a crafted value through the Select field. The dropdown is the delivery mechanism; the payload is a fake upload-field config that tells the plugin what to accept and where to put it.

Public form submission
        │
        ├── forged Select value ──► attacker-controlled upload field config
        │
        ▼
handle_file_upload()
        │
        ├── extension blocklist  ──► exact-key match misses the compound key
        │
        ▼
PHP file written to an uploads path
        │
        ▼
Request the file directly ──► code execution as the web-server user

Once PHP executes, the site is gone in the ways that matter: wp-config.php and therefore the database credentials, an administrator account of the attacker's choosing, persistence that survives a plugin update, and a foothold on the hosting account.

The lesson worth taking

Neither half of this bug is exotic. A blocklist with a formatting mismatch is a bad afternoon. A handler that trusts client-supplied configuration is a bad design decision. Chained, they are a pre-auth RCE on six hundred thousand sites.

The design lesson is the second one. The server already knows what a form's upload field is supposed to accept: it stored it. Every byte of that configuration that arrives from the browser instead is an opportunity. This is the same class of mistake as trusting a hidden field for a price, and it is exactly what we look for in an application penetration test.

Is it being exploited?

As of disclosure, there was no confirmed in-the-wild exploitation and no public proof-of-concept. The vulnerability was found through a bug bounty programme, not in incident response.

Two cautions. First, "no public PoC" is a statement about today, and the technique is now described publicly in enough detail to reconstruct. Second, plugins with six-figure install bases are scanned continuously; the window between a well-understood WordPress bug and mass automated exploitation is historically short.

The disclosure timeline, as reported by The Hacker News and SecurityOnline, was to the credit of everyone involved fast:

DateEvent
11 July 2026Submitted to Wordfence
14 July 2026Validated, proof-of-concept confirmed, vendor notified
31 July 2026Forminator 1.56.2 released with the fix

What to do today

  1. Update Forminator to 1.56.2 or later. If you are on 1.57.x, be aware a second critical flaw was disclosed in August. See our write-up of CVE-2026-66583, which requires 1.57.1.
  2. Inventory your forms. Find every published form containing both a File Upload and a Select field. Those were the exposed ones and they are where you should look hardest for signs of abuse.
  3. Search your uploads directory for PHP. Nothing in a forms plugin's upload path should ever be executable.
  4. Confirm your upload roots refuse to execute PHP. If you use a custom upload directory, verify it has its own protection. Do not assume it inherited one.

How to check whether someone got there first

Look for executable files anywhere under your uploads tree:

find wp-content/uploads -type f \( -name '*.php' -o -name '*.phtml' -o -name '*.phar' \) -printf '%TY-%Tm-%Td %p\n' | sort

Any result is worth investigating; a result dated before 31 July on a site running an affected version deserves an incident response, not a delete.

Then check your access logs for direct requests to files under the uploads path:

grep -E 'wp-content/uploads/.*\.(php|phtml|phar)' access.log

A successful upload is quiet. The retrieval is not: an attacker has to request the file to run it, and that request lands in your logs with a 200.

If you find either, treat the host as compromised: rotate the database password in wp-config.php, rotate all administrator passwords and application passwords, audit the user table for accounts you did not create, and check for scheduled tasks and mu-plugins that arrived without you. Continuous monitoring for exactly this pattern is what SOC as a service is for.

The broader point

This is the third WordPress plugin flaw in a month where the vulnerable path ran through trusting structure supplied by the client. Plugins are where most WordPress risk lives, and a plugin with a public submission endpoint is an internet-facing application with all the obligations that implies.

If your business depends on a WordPress site, the questions worth answering are: which plugins expose unauthenticated endpoints, who reviews them, and how quickly do you find out when one of them ships a 9.8. We help teams answer those in a secure web development engagement, or talk to us if you would rather have someone check the forms for you.

Get Started

Want a security-first build?

Get a free security review. We'll look at where you stand today and tell you what to fix first, no strings attached.

Talk to an Expert
CVE-2026-15748: Forminator Pre-Auth RCE on 600,000 Sites - IKZERO