The one-sentence version
An arbitrary file upload vulnerability is what happens when a feature meant to accept images, documents, or attachments fails to actually verify what it's receiving — letting an attacker upload a file that the server will execute as code, instead of just store as data.
Of every vulnerability class in this series, this is the one with the shortest distance between "found the bug" and "full control of the site." There's no extra step of forging a session or waiting for an admin to click something. The moment the file lands somewhere the web server will execute it, the attacker has code running on your server.
Why upload fields are a trust decision, not just a feature
A profile-picture field, a form-builder attachment, a document-library uploader — these all make an implicit promise: "we'll accept what you send us, and treat it as the harmless thing it's supposed to be." The vulnerability shows up when that promise isn't actually enforced in code. Common weak-validation mistakes include:
- Trusting the file extension the browser reports, without checking what the file's contents actually are. An attacker can name any file
whatever.jpgregardless of what's inside it. - Checking the MIME type sent in the request instead of the file itself. The
Content-Typeheader is just a claim the uploader makes — an attacker can set it toimage/jpegon a file that's really a PHP script, and a check that only reads that header never notices. - Double-extension tricks like
shell.php.jpgorshell.jpg.phtml. If validation only checks that a recognized image extension appears somewhere in the filename — rather than confirming it's the actual, final extension — a server misconfigured to still execute.phtmlor a similarly-treated extension will run it anyway. This is a well-documented, real-world bypass pattern, not a theoretical one.
None of these are exotic. They're the direct result of checking the label on the box instead of opening it.
Why this connects straight to webshells
We've already covered what a webshell is and why finding one on a "cleaned up" site usually means the infection is still active. An arbitrary file upload vulnerability is frequently exactly how that webshell got there in the first place. The upload IS the delivery mechanism: the attacker doesn't need to compromise an account or find some other way onto the server — they just upload the webshell directly through the feature that was supposed to accept a JPEG.
That's why finding one bug class often means checking for the other. If a site was compromised via an upload vulnerability, assume the attacker used it to plant at least one webshell, and follow the fuller cleanup process described in how to remove WordPress malware.
A real, verified example
In January 2025, Patchstack disclosed CVE-2025-23921, a critical unrestricted file upload vulnerability in Multi Uploader for Gravity Forms, affecting all versions up to and including 1.1.3, with a CVSS score of 9.0 (critical). The plugin's upload endpoint accepted files from unauthenticated visitors with no meaningful file-type validation, letting anyone upload arbitrary files — including working PHP webshells — directly to the server.
This wasn't a theoretical finding. Security researchers at TXOne Networks documented real, ongoing exploitation attempts against the flaw dating back to August 2024 — attackers sending crafted requests to the plugin's upload endpoint with payloads disguised as images (.phtml files posing as image uploads) matching the size and structure of lightweight webshells. The vulnerability was fixed in version 1.1.4.
Why the upload location matters as much as the file itself
Even a well-validated upload feature depends on a second, separate assumption: that the folder files get uploaded into won't actually execute them. WordPress's own wp-content/uploads/ directory is meant to hold media — images, PDFs, documents — not code, and a properly configured server won't run a PHP file placed there even if one somehow ends up in it. That's a second, independent layer of protection sitting behind file-type validation, not a replacement for it.
The problem is that this second layer isn't guaranteed on every hosting setup. Some server configurations will still execute a .php file wherever it's placed, uploads directory included, which is exactly why a validation gap in the plugin becomes a full compromise instead of a harmless mistaken upload. This is also precisely why finding a .php file sitting inside an uploads folder — a directory that should only ever contain media — is treated as a strong, specific red flag rather than something to shrug off, as covered in what a webshell actually is.
Why this is (almost always) a plugin problem
As with the other vulnerability types covered in this series, WordPress core doesn't hand out unrestricted file-upload capability by default — core's own media-upload handling applies its own type restrictions. The pattern shows up when a plugin builds its own upload-handling code for a specific feature — a form-builder attachment field, a custom media importer, a membership-site profile picture uploader — and that custom code skips the validation core would otherwise apply. The more a plugin's upload feature is a "we built our own pipe for this," the more likely a gap exists somewhere in that pipe.
What to actually do about it
- Keep any plugin that accepts user-generated uploads updated, without delay. Form builders, membership plugins, and gallery/document plugins are common locations for this bug class — and as the case above shows, real attackers scan for and exploit these within months of disclosure.
- Be more cautious with plugins that let non-admin or even unauthenticated visitors upload files. A contact-form attachment field or a public submission form is a higher-risk feature than an admin-only media uploader, simply because more people can reach it.
- If you don't need an upload feature, don't leave it active. Disabling or removing an upload-capable feature you're not actually using closes off an attack surface you were never using anyway.
- Watch for unfamiliar files appearing in your uploads directory — particularly anything with a
.php,.phtml, or similarly executable extension. A media library should only ever contain media; a script sitting alongside your images is worth investigating immediately, not explaining away.
None of this replaces the vendor's own patch. As with every vulnerability class in this series, the fix for a specific disclosed flaw is the update that closes it — these habits reduce how much damage a gap does before you patch it, not a substitute for patching in the first place.
Get file, account, and login findings explained the moment they happen — not months later.
Install free →