This is a summary of [Iwaniuk 2011]
PHP 5.3.6 (source) uses two slightly different datastructures to handle metadata on a file upload/multifile upload [RFC 1867]. PHP gates which of these codepaths and datastructures to use based on user controlled input, and it is possible to mangle the datastructure by forcing PHP to shove multifile upload metadata into the datastructure/codepath meant for single file metadata.
(Most of the following occurs in the function: SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler).)
In rfc1867.c:1177 we have the core of the problem which are calls to snprintf with user controlled data that is given in param (lines 4 and 6 below):
In rfc1867.c:1157 PHP does a check which chooses what datastructure and codepath to use for the metadata, based on the user controlled input in param. If param ends with a “]” (ie. “file”) then PHP selects the codepath for the multifile upload; otherwise PHP treats the upload as a single file upload.
Here’s the PHP code that showcases the vulnerability, slightly modified from the original to help understand what is going on:
Ideally, this code should be accessed by a safe front end uploader:
Using this when we upload 3 files and thus PHP’s $_FILES will be an array (“file”) of 5 arrays, (“name”, “type”, “tmp_name”, “error”, and “size”) each of these with 3 elements each to hold the metadata for the seperate files:
Array ( [file] => Array ( [name] => Array (  => index.php  => 123  => file.txt ) [type] => Array (  => application/octet-stream  => application/octet-stream  => text/plain ) [tmp_name] => Array (  => /tmp/php97bGry  => /tmp/php75jehC  => /tmp/phpDygN6F ) [error] => Array (  => 0  => 0  => 0 ) [size] => Array (  => 24  => 16  => 15 ) ) )
Thus, $_FILES[“name”][0..2] are the file names, $FILES[“tmp_name”][0..2] are the names that the uploaded files have in /tmp before PHP processes them. Note that in a single file upload, we have a simple array used with 5 elements, not an array of arrays.
Here’s an portion of the code with extra debugging stuff added so that we can see what’s going on. I pulled it out to run as a stand alone binary for clarity. Some function names, the e-*str functions have been renamed to the cstdlib versions.
The original safe uploader page uses the params of “file”. This results in the call:
register_http_post_files_variable(file[type], cd, http_post_files, 0 TSRMLS_CC
One can do is copy the webpage to your local machine, and modify it as such:
In short, an issue occurs because php does not actually check the parameters
This is the version of PHP I can verify this is vulnerable with:
Follow up: check into the TSRM/ directory, there look to be some interesting code bits in there.
TSRMLS_DC is a shortcut for “, void *** tsrm_ls”.
 A. Iwaniuk, Overriding $_FILES array during uploading multiple files in php.