Safeguard
Application Security•

CWE-616 PHP Upload Variables Overwritten: Cause and Fix

Old PHP code trusted global variables like $userfile to describe an upload. An attacker can set them directly and point the app at any file on disk.

Safeguard Security Team
3 min read

CWE-616, Incomplete Identification of Uploaded File Variables, is a PHP weakness from an older era of the language. It hits legacy PHP applications that still process uploads through global variables instead of the $_FILES array.

How it happens

In old PHP setups, an upload named userfile produced four globals: $userfile, $userfile_size, $userfile_name and $userfile_type. The application then read those variables and assumed they described a file the web server had just received.

The trouble is that globals can be filled from other places. A POST field, a cookie or a query string can set the same names. The code never checks that the file was really uploaded, so the attacker supplies a value such as /etc/passwd and the app processes it.

// Vulnerable: trusts a global that any request can set
$path = $userfile;           // attacker sends userfile=/etc/passwd
echo file_get_contents($path);

MITRE lists three observed examples from 2002, including CVE-2002-1460, where a forum did not verify that a file was uploaded or that the variables were set by the upload itself.

What an attacker gains

Per the record, the impact covers confidentiality and integrity. An attacker can read files or directories, and can modify them if the code goes on to move, rename or overwrite the "uploaded" file.

How to find it

Search a legacy codebase for upload handling that reads bare variables with the _name, _size and _type suffixes, and for any use of $HTTP_POST_FILES without a matching is_uploaded_file() call. A dependency scan will not find this, since it lives in your own code, but it will tell you whether the old PHP application's third-party libraries also carry known issues.

How to fix it

MITRE's mitigations are short:

  1. Use PHP 4 or later.
  2. If you must support older PHP versions, write your own version of is_uploaded_file() and run it against the uploaded file entry.
  3. In later versions, reference uploads through $HTTP_POST_FILES or $_FILES, and use is_uploaded_file() or move_uploaded_file() to confirm you are dealing with a real upload.
// Fixed: confirm the file came from this request's upload
$tmp = $_FILES['userfile']['tmp_name'] ?? '';
if (!is_uploaded_file($tmp)) {
    http_response_code(400);
    exit('Invalid upload');
}
move_uploaded_file($tmp, $destination);

Quick check

Why can an attacker set $userfile without uploading anything?

Because the variable is a plain global. POST data, cookies and other request inputs can populate or overwrite it, and the code never confirms the file came from an upload.

Which functions confirm a file is a real upload?

is_uploaded_file() and move_uploaded_file(), used against entries from $_FILES.

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.