5

I have a php web application that allows file uploads to a specific directory.

I would like to prevent the execution of any file that is uploaded into that directory whether it is ASP, PHP, or anything else that may be supported by IIS. I'm already blocking the upload of asp and php files at the application layer, but as a measure of defense in depth against a possible error in that validation code I would like to add a configuration to IIS to prevent execution of these files.

Is there a way to do that in IIS?

2
  • How much control do you have over the server/IIS? If you know the module name, then you can place some special web.config file into that folder that will instruct IIS to remove those specific modules that deal with PHP/ASP etc -- but you need to know those handlers/modules names in advance (unless you are happy to remove them all, which does not make much, if any, sense). This also will not work, if configuration of that part of the config section is prohibited to be done in web.config file (such restrictions can only be applied at higher level, e.g. server level).
    – LazyOne
    Commented Apr 20, 2012 at 22:49
  • Well, I guess I'd love an answer that works both for situations where you have full control of the server and maybe a second where you have less control (i.e. shared hosting). At a minimum I'd like to remove the php module. I actually do want to remove the ability to execute any code inside this one directory (even if it seems like it doesn't make sense).
    – greggles
    Commented Apr 20, 2012 at 23:03

5 Answers 5

9

First of all -- this really depends on your server configuration -- if such modifications are allowed to be performed on directory level (section is not locked on parent/server level).

In order to disable execution of specific file extension yo need to know the handler name that is responsible for this. On each system this name can be different, especially for PHP, since it is not standard handler (created by user with admin rights). For example (web.config that needs to be placed in such folder):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <remove name="PHP 5" />
        </handlers>
    </system.webServer>
</configuration>

The above will remove handler named "PHP 5" that is responsible for handling *.php files on my PC. With *.asp handler this should be easier since it has standard name, but it can easily be changed if required.

Another approach -- remove ALL handlers altogether. In this case you do not need to know handler names. This has one serious drawback -- you will not be able to serve anything from this folder and subfolders, even static files.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <clear />
        </handlers>
    </system.webServer>
</configuration>

To bypass this drawback you can create URL rewriting rule and forward all requests to such files to your special script that will actually serve those files (script will have access to those files, so no problems here). The downside -- it can be quite complex (depends on number of file types it will be handling) + will produce a bit of unnecessary processing overhead (how big -- depends on your script, how you will code it).

3rd approach seems to be more optimal (really depends on your other requirements) -- we will remove ALL handlers and will add the one that serves static files back .. so images/html/css/js etc should still work if requested from such folder:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <clear />
            <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
        </handlers>
    </system.webServer>
</configuration>

If you still require some other standard handlers to be available in this folder .. then you will have to add them back in a similar manner.

3
  • The problem that I have with any web-config based approach is that users have access to the folder that we are trying to protect this way, and that they can modify or delete the web.config. Upload and IIS permissions are coupled that way, and introducing another layer of folders goes beyond of a simple security fix and will inconvenience my users. I am still looking for a way to protect folders with user content.
    – cdonner
    Commented Jun 25, 2012 at 20:33
  • @cdonner So .. what is the problem? Wrap your config into location element and then such web.config it can be placed in different location (e.g. root folder): <location path="subfolder/protect"><system.webServer>....</system.webServer></location>. If you cannot use web.config at all -- you will have to place such code (using full path to that folder though) in server wide config file.
    – LazyOne
    Commented Jun 26, 2012 at 8:46
  • @cdonner If you have access to the server's file system directly (or can execute commands that will affect file system), then just use appropriate security permissions on such web.config to prevent any access over FTP (or whatever is required).
    – LazyOne
    Commented Jun 26, 2012 at 8:49
4

One good and easy way to prevent execution of certain file extensions under an specific folder is to use the "Request filtering" feature of IIS to prevent accessing them altogether.

Go to the folder in IIS and in the "File Name Extensions" tab of the "Request filtering" feature, add "Deny file extension" rules for the file extensions that you want to lock.

That will generate this sections in the web.config file for that folder:

<system.webServer>
    <security>
        <requestFiltering>
            <fileExtensions>
                <add fileExtension=".aspx" allowed="false" />
                <add fileExtension=".php" allowed="false" />
                <add fileExtension=".asp" allowed="false" />
            </fileExtensions>
        </requestFiltering>
    </security>
</system.webServer>

In this example we block the access to .php, .asp and .aspx files. So if someone tries to access any file with this extensions in your folder they will get a 404 status code (as if the file doesn't exist).

That would be a good way to prevent execution in a fast and simple way.

1
  • But anyone can still upload a web.config into your upload folder, and override your handlers configuration, so that they will be able to run scripts again with other file extensions. See this link for exploit example, where web.config itself is used to redefine that web.config should be served by the ASP handler, and in case he puts scripts directly inside web.config. As far as I understand, the only real solution is to restrict the handlers (and not the extensions) and forbid handlers overriding (or forbid web.config uploads)
    – drizin
    Commented May 28, 2019 at 1:25
2

Assuming that you want the uploaded files to be served as static content (or else you could just save the uploads outside the root folder of your application):

Inside your root web.config (which can't be overwritten by users), use this (as suggested by Javier G., but with allowOverride=false):

  <location path="upload" allowOverride="false">
    <system.webServer>
      <handlers accessPolicy="Read" />
    </system.webServer>
  </location>

Or this (as suggesteed by LazyOne, but with allowOverride=false):

  <location path="upload" allowOverride="false">
    <system.webServer>
      <handlers accessPolicy="Read">
        <clear />
        <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
      </handlers>
    </system.webServer>
  </location>

If you don't use allowOverride=false, anyone can upload a web.config in your open folder, and override your handlers configuration, so that they will be able to run scripts again. See this link for exploit example.

1
  • Actually, I would not use the first one as it will still allow execution of the ASPX file and will just not display the result. This will allow someone who can upload a dynamic file from exfiltrating any data that IIS_USRS (or whatever iis is running as) can access. The LazyOne version completely blocks any dynamic files. Commented Oct 21 at 18:20
1

Just to add to the posted solution for others who might be running into the same issue: None of those worked for me until I figured out that the handlers were locked at the top level. I'm not a server admin or even close to it, so that took me a little while. Until the applicationHost.config file was edited to allow overrides, including even an empty <handler> section in a lower level web.config file was enough to break everything from that level down. Works great now, though.

1

Add this Web.config to your uploads directory (or even better, to the parent Web.config inside a location path="whatever" tag)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers accessPolicy="Read"/>
  </system.webServer>
</configuration>

This tells IIS that handlers (such as PHP) may only read, and not execute, therefore showing a 404 for executable scripts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.