Pair
In earlier PHP versions, file uploading may be implemented through the following code:
- ......
- If (isset ($ _ FILES ['file']) {
- $ Tmp_name = $ _ FILES ['file'] ['tmp _ name'];
- }
- If (file_exists ($ tmp_name )){
- Copy ($ tmp_name, $ destfile );
- }
- ......
However, a $ _ FILES ['file'] array may be forged. If the content of tmp_name is specified as/etc/passwd and other sensitive information, so it is easy to have security problems. In later versions, PHP solved this problem with is_uploaded_file () and move_uploaded_file, using the PHP uploaded_files function will not only check whether $ _ FILES ['file'] ['tmp _ name'] exists, in addition, the system checks whether $ _ FILES ['file'] ['tmp _ name'] is an uploaded file, which makes it impossible to forge the $ _ FILES variable, because the script will terminate execution when checking that $ _ FILES ['file'] ['tmp _ name'] is not uploaded by PHP.
Is forging impossible? In many scripts, I can see operations such as @ extract ($ _ POST) in the preliminary test to ensure that the program can continue to run in the environment where register globals is off, in such an environment, we can easily forge the $ _ FILES array or even overwrite the original $ _ FILES array. However, it is still very difficult to completely forge a $ _ FILES array, because you cannot review is_uploaded_file () and move_uploaded_file ().
However, during testing in the PHP environment in windows, we found that PHP temporary files are quite regular, in the format of C: WINDOWS TEMPPHP93.tmp. When uploading files, the file name will be C: WINDOWSTEMPPHPXXXXXX. tmp format change, where XXXXXX is a hexadecimal number and is added in order, that is, if the temporary file name for this upload is C: WINDOWSTEMPPHP93.tmp, the next time is C: WINDOWSTEMPPHP94.tmp, the temporary file name becomes regular.
However, we may not know what the current file name is, which can be leaked through the PHP error mechanism, for example, if we copy a temporary file to an unauthorized directory or contain characters prohibited by the file system in the target file, the name of the temporary file can be leaked, of course, the premise is that there is no error suppression processing.
So how can I get rid of is_uploaded_file () and move_uploaded_file? Look at the PHP uploaded_files function code:
- PHP_FUNCTION(is_uploaded_file)
- {
- zval **path;
- if (!SG(rfc1867_uploaded_files)) {
- RETURN_FALSE;
- }
- if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &path) != SUCCESS) {
- ZEND_WRONG_PARAM_COUNT();
- }
- convert_to_string_ex(path);
- if (zend_hash_exists(SG(rfc1867_uploaded_files), Z_STRVAL_PP(path), Z_STRLEN_PP(path)+1)) {
- RETURN_TRUE;
- } else {
- RETURN_FALSE;
- }
- }
It is used to check whether the current file name exists from the rfc1867_uploaded_files hash table. Rfc1867_uploaded_files stores the variables and content related to file upload generated by the system and PHP during the current PHP script running. If yes, it indicates that the specified file name is indeed uploaded this time; otherwise, it indicates no.
A strange feature of PHP is that when you submit an upload form, PHP will upload the file to a temporary directory before processing it, it will not be destroyed until the PHP script stops running. That is to say, even if you submit such a form to a PHP script that does not accept the $ _ FILSE variable, the $ _ FILSE variable will still be generated and the file will be uploaded to the temporary directory first. The problem arises. The following script may explain this problem:
- < ?
- $a=$_FILES['attach']['tmp_name'];
- echo $a.”………….”;
- $file=’C:\WINDOWS\TEMP\PHP95.tmp’;
- echo $file;
- if(is_uploaded_file($file)) echo ‘………………Yes’;
- ?>
Among them, C: \ WINDOWS \ TEMP \ PHP95.tmp is the name of the temporary file I guessed. At that time, when testing this script, we need to upload a file or 100 files to it, make the temporary file name C: \ WINDOWS \ TEMP \ PHP95.tmp. If the script has extract operations at the moment, we can easily forge a $ _ FILES variable.
No? You may want to ask how the $ _ FILES variable works. We can generate a file name that is not allowed by the original program. when processing the upload, PHP will have a file name similar to basename () but once it can be forged, we can easily add it to the file name .. // wait for anything you like
The actual use of the PHP uploaded_files function may be a little harsh, but it is still a flaw in PHP.