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:
- Use PHP 4 or later.
- If you must support older PHP versions, write your own version of
is_uploaded_file()and run it against the uploaded file entry. - In later versions, reference uploads through
$HTTP_POST_FILESor$_FILES, and useis_uploaded_file()ormove_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.