php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68535 Uploaded files are not deleted because of missing impersonation
Submitted: 2014-12-01 23:00 UTC Modified: 2014-12-17 08:27 UTC
From: lf at evasys dot de Assigned:
Status: Not a bug Package: IIS related
PHP Version: 5.5.19 OS: Windows Server 2012
Private report: No CVE-ID: None
 [2014-12-01 23:00 UTC] lf at evasys dot de
Description:
------------
When uploading a file by a HTML form to a PHP script, the uploaded file will remain in upload_tmp_dir, even when the request ended (and this file was not removed explicitly by the PHP code).

Test script:
---------------
Any file upload from a multipart HTML form.

Expected result:
----------------
Unused, not moved or not deleted temp files of a file upload are normally deleted by PHP when the request ended. We can reproduce this on Apache environments. This is also the behavior php.net describes for file uploads: "The file will be deleted from the temporary directory at the end of the request if it has not been moved away or renamed.", see: http://php.net/manual/en/features.file-upload.post-method.php

We can also see in procmon that php.cgi.exe tries to delete the temp file.

Actual result:
--------------
The file is created in upload_tmp_dir. In our case with the IUSR account since we use "Anonymous Authentication" in IIS. The file is not touched by the PHP code. The request ends. PHP tries to delete the temporary file, but the access is denied.

We analyzed this with procmon. What you can see there is, that php-cgi.exe process seems not impersonate on the delete request like on move_uploaded_file() or any other filesystem access.

Workaround: If we add MODIFY rights for IIS_IUSRS group on uploaded_tmp_dir the file will be deleted after the request ended as expected.

Environment: PHP 5.3.x/5.4.x via FCGI on IIS 7.x

Reproduced on WS2012, WS2008 R2.

This may also be a security releated issue, because when PHP does not delete temp files created by uploads the server is vulnerable by a possible DoS attack.

Maybe related to https://bugs.php.net/bug.php?id=54951

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-12-01 23:14 UTC] requinix@php.net
Sounds like a configuration issue with your temp directory, not with PHP itself.

What's the state of the permissions? Temp folders typically get CREATOR OWNER with (nearly) full rights, or else the IUSR needs them. And remember that there are separate permissions for creating, modifying, and deleting files.
 [2014-12-01 23:15 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2014-12-01 23:44 UTC] lf at evasys dot de
IUSR has MODIFY rights to this folder. This folder is also used for session files which can be/are deleted by GC. The upload tmp files (like any other file created in our PHP/IIS environments) were originated by IUSR, so it makes so sense to me, why IUSR shouldn't be able to remove especially this upload tmp files but any other file originated by IUSR.

When I create and then delete a file in the same directory by a simple test script it is also working.

There is something absolutely going wrong, when PHP tries to delete the temp files of uploads on IIS webserver. At least I can see in procmon that the impersonation is missing on this delete action.
 [2014-12-02 09:08 UTC] lf at evasys dot de
-Status: Feedback +Status: Open
 [2014-12-02 09:08 UTC] lf at evasys dot de
Status
 [2014-12-02 09:12 UTC] ab@php.net
-Status: Open +Status: Feedback
 [2014-12-02 09:12 UTC] ab@php.net
How exactly do you see it's missing?

Thanks.
 [2014-12-02 13:05 UTC] lf at evasys dot de
-Status: Feedback +Status: Open
 [2014-12-02 13:05 UTC] lf at evasys dot de
I added a screenshot with some marks of my procmon log:
https://www.dropbox.com/s/wh4u4d61rxxj4jf/procmon.png?dl=0

Please see the explaination of the log:

Block 1: This is the file upload and the origination of the upload temp file. As you can see, every action is done with impersonation od IUSR.

Block 2: This is where the PHP script that was targeted by the HTML form is loaded. Also done with impersonation.

Block 3: This is the result of a test my script does:
**NOTE: I removed my log functions from the script.

    // IUSR has "Modify" rights on this folder  
    $sFolder = "IUSR/";
    $sTestFile = $sFolder."test.txt";

    // Create test file
    $hFile = fopen($sTestFile, "w+");
    fwrite($hFile, "test");
    fclose($hFile);

    // Check if test file was created
    file_exists($sTestFile);

    // Delete test file
    unlink($sTestFile);

    // Check if test file was deleted
    file_exists($sTestFile);

Also every action done with impersonation.

Block 4: The same test but in another folder where I set IIS_IUSRS with "Modify" rights:

    // IIS_IUSRS group has "Modify" rights on this folder  
    $sFolder = "IIS_IUSRS/";

    ...like above...

This proves, that my script can normally not write with IIS_IUSRS credentials. Also every action done with impersonation.

Block 5: The same test, but now in upload_tmp_dir:

    // IUSR has "Modify" rights on this folder 
    $sFolder = ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir();

    ...like above...

This test proves, that my configuration is valid for the upload_tmp_dir. Also every action done with impersonation.

Block 6: The request ended, the uploaded file was not touched. In this case PHP will delete the file. But the access is denied and you can see that the impersonation is missing!

procmon can be downloaded here:
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx

I also proved the log from progmon as native PML (procmon file) and CSV here:
https://www.dropbox.com/sh/eyrxqjqkyqncqdk/AADNOnnfDZeUbW1k950LxryVa?dl=0
 [2014-12-02 17:37 UTC] ab@php.net
-Status: Open +Status: Not a bug
 [2014-12-02 17:37 UTC] ab@php.net
Thanks for so detailed explanation. I've tried to repro this different ways including yours but still couldn't. Regarding the impersonation, you can see from these lines that it works with PHP, shown are the relevant lines where you've the "access denied" result.

5:05:54.9676630 PM	php-cgi.exe	75828	CreateFile	C:\inetpub\temp\php\php3C2A.tmp	SUCCESS	Desired Access: Read Attributes, Delete, Disposition: Open, Options: Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, Impersonating: IIS APPPOOL\DefaultAppPool, OpenResult: Opened
5:05:54.9677298 PM	php-cgi.exe	75828	QueryAttributeTagFile	C:\inetpub\temp\php\php3C2A.tmp	SUCCESS	Attributes: A, ReparseTag: 0x0
5:05:54.9677732 PM	php-cgi.exe	75828	SetDispositionInformationFile	C:\inetpub\temp\php\php3C2A.tmp	SUCCESS	Delete: True
5:05:54.9678180 PM	php-cgi.exe	75828	CloseFile	C:\inetpub\temp\php\php3C2A.tmp	SUCCESS

However not using the built-in account but the app pool identity. So at least this topic is closed, PHP impersonation works (would even wonder if it wouldnt - that's the same API everywhere).

Regarding the configuration of the built-in accounts and groups regarding security - yeah, there are probably numerous approaches besides the baselines. For instance while investigating I've found this one http://serverfault.com/questions/282806/should-i-impersonate-php-via-fastcgi where people don't even bother fastcgi.impersonate .

So due to the above one can say that you're reporting clearly a configuration issue, not a PHP one.

Thanks.
 [2014-12-02 21:44 UTC] lf at evasys dot de
Did you set fastcgi.impersonate = 1?
 [2014-12-03 07:30 UTC] ab@php.net
Yes, for IIS it makes pretty much sense IMO.
 [2014-12-11 13:39 UTC] lf at evasys dot de
So I do not understand your argument. The documentation and you in person are clearly recommending to use fastcgi.impersonate. Also http://php.net/manual/de/install.windows.iis7.php states: "This means that in order for IIS to execute PHP scripts, it is necessary to grant IUSR account read permission on those scripts. If PHP applications need to perform write operations on certain files or write files into some folders then IUSR account should have write permission to those."

I gave proove that IUSR has access rights to the files and that IUSR is originator of the files and that PHP simply does not impersonate in this case. So please tell me where the configuration issue is?

I will tell you what a configuration issue is: In your test you grant also access to the temp folder for IIS APPPOOL\DefaultAppPool (or one of the groups including this user like IIS_USRS or Users). PHP is able to delete the temp file in this case because this is the identity of the worker and which is used if php-cgi.exe is NOT impersonating. Of course, this is also an impersonation but NOT the right one.

What the guys are discussing in the link you provided is interesting, but at least this also just proves my point. They discuss to setup access rights in a different way and with a different purpose.

Granting modify access to the IIS APPPOOL\DefaultAppPool or the IIS_IUSRS on upload_tmp_dir is a workaround but in the end this is the true misconfiguration you are talking about. Messing with credentials is not the answer to a bug.

Only in this file action PHP is not acting as documented. And every other file action is done with impersonation of IUSR like the create and move (move_uploaded_file) action of the upload tmp-files.

You really want to tell, that this is a not a bug but a configuration issue?
 [2014-12-17 08:27 UTC] ab@php.net
@lf at evasys dot de

Please refer to this http://www.iis.net/learn/manage/configuring-security/application-pool-identities . Just do not use IUSR but the app pool identity, and it's all good. Also, robably you might fire a documentation issue or even provide a patch. 

Thanks.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 10 17:01:27 2024 UTC