Safeguard
Application Security•

CWE-434 Unrestricted File Upload: How It Happens and How to Fix It

Let users upload files without limits and one of them may be a web shell. CWE-434 explained, with vulnerable and fixed PHP examples.

Safeguard Security Team
4 min read

CWE-434 is the product allowing upload or transfer of dangerous file types that are automatically processed within its environment. Profile photos, document attachments, import features and AI/ML model uploads all count. MITRE lists ASP.NET, PHP, web servers and AI/ML among the affected platforms.

How it happens

The app accepts a file, saves it somewhere the server can reach, and either trusts the filename or checks only a weak signal. If an attacker uploads shell.php into a directory where PHP runs, requesting it executes their code.

<?php
// Vulnerable: trusts the client's filename, stores under web root
$name = $_FILES["avatar"]["name"];
move_uploaded_file($_FILES["avatar"]["tmp_name"], "/var/www/html/uploads/" . $name);

MITRE's observed examples:

  • A PHP based FAQ management app that did not check the MIME type of uploaded images (CVE-2023-5227).
  • A web mail product storing ".shtml" attachments that could contain server side includes (CVE-2001-0901).
  • A PHP upload that did not restrict file types (CVE-2002-1841).
  • Upload and execution of a .php file (CVE-2005-1868).

What an attacker gains

The record lists executing unauthorized code or commands, with impact on integrity, confidentiality and availability. MITRE notes arbitrary code execution is possible if the uploaded file is interpreted as code by the recipient, especially for web server extensions like .asp and .php.

How to find it

MITRE cites these techniques from the SOAR report:

  • Dynamic analysis with automated results: web application scanners and web services scanners give partial coverage cost effectively.
  • Dynamic analysis with manual results: fuzz testers and framework based fuzzers.
  • Manual static analysis of source: focused spot checks and manual code review, rated highly cost effective.
  • Automated static analysis of source: source code weakness analyzers, including context configured ones, rated highly cost effective.

A fast manual test is to upload a harmless file with a script extension and a double extension like photo.jpg.php, then see whether it is stored and whether requesting it runs.

How to fix it

The record lists no formal mitigations, so these are the standard controls.

  1. Allowlist types. Accept only the extensions you need, and check content type and the file's actual signature, not just the name.
  2. Rename on save. Generate a random name and set the extension yourself.
  3. Store outside the web root, or on separate storage that never executes files, and serve through a handler.
  4. Disable execution in upload directories at the server level.
  5. Limit size and scan uploads for malware where appropriate.
  6. Re-encode images so embedded payloads are stripped.
<?php
// Fixed: allowlist, random name, stored outside web root
$allowed = ["jpg" => "image/jpeg", "png" => "image/png"];
$ext = strtolower(pathinfo($_FILES["avatar"]["name"], PATHINFO_EXTENSION));
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($_FILES["avatar"]["tmp_name"]);

if (!isset($allowed[$ext]) || $allowed[$ext] !== $mime) {
    http_response_code(400);
    exit("File type not allowed");
}
$dest = "/var/app-uploads/" . bin2hex(random_bytes(16)) . "." . $ext;
move_uploaded_file($_FILES["avatar"]["tmp_name"], $dest);

Try it yourself

A dynamic scan is one of the ways to catch a risky upload endpoint on a running app.

Click through it at your own pace, or open it full screen.

Quick check

Is checking the Content-Type header enough?

No. The client sets it. Check the extension against an allowlist and verify the file's real content on the server.

Why store uploads outside the web root?

Then a file cannot be requested and executed by URL, even if a bad one slips through.

Why rename the file?

The original name is attacker controlled. A random name with an extension you choose removes that control.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.