ColdFusion Muse

Protecting the CFIDE directory in IIS

Yesterday I had a server with IIS and a few hundred sites on it. Some, though not all, of the sites had an unprotected CFIDE directory mapped. So my task was to protect these directories by denying all IPs from access except a specific IP range. Before I describe the task and my trick let me remind you that this is not time to tout Linux or Apache or bash Microsoft in the comments. The muse welcomes comments but enjoys variety. We all know about Apache and its manifest benefits. We don't need you to remind us in spite of your excellent credentials and biting wit. IIS is fine platform with many strong points too and there are folks who need this information. They should not feel like they are sneaking into the adult section of the video store to get it. Now back to the Muse' usual good humor. Here's the scoop....

In IIS 7.5 before you are able to do that you must make sure that the "IP and Domain Restrictions" role service is installed. In prior versions of IIS (before 7.0) IP restrictions were a native part of IIS and you could access them from the security tab. But in 7.5 this is a separate service that has to be installed and is not "pre-selected" when you install IIS. In case you are scratching your head (how do I install a role service) try the following. Open server manager, click on features, scroll down to IIS and click on the "add role services" box. Under the security items you will see what you are looking for. Make sure the box is checked. It looks like this.

Next you will need to find the directory you are looking for in IIS. Using IIS manager navigate to CFIDE/Administrator and select it in the tree on the left hand side. Then click on the task icon that says "IPv4 Address and Domain Restrictions". You will see a blank screen with some link to the right. Click on the link that says "Edit Feature Settings" and you will see 2 options - allow and Deny. Like this.

Change the setting to "deny". In other words we are telling IIS to deny all IP addresses any access to this directory. Not to worry, we are now going to add exceptions. In the task pane click on the link for "add Allow" entry. You should see this dialogue.

It's pretty straightforward. If you wanted to allow a subnet on your local network for example, you might add

Lots of Busy Work

Ok, but that's modifying the properties of one site. It's useful and easy and you could walk someone through it over the phone if you had to - all advantages of a GUI interface right? But as I said, I had to go through hundreds of sites looking for this problem. If I have to do these steps over and over for administrator and adminapi I'm going to poke my eye out. I have a solution for that. Before I describe it let me make sure of one thing. You must have exclusive access to the server. In other words, no one else should be making any IIS changes while you do this. As long as that condition is met you can do the following.

ApplicationHost.config Magic

Navigate to Windows/system32/inetsrv/config and open a file called applicationHost.config in an editor. You might note a lot of backup files here - applicationHost.config.1-n - IIS does this to keep previous copies of the file. I always make my own backup of the file anyway before I begin. Once you are editing the file go to the bottom of the file. Your new IP restrictions should exist there as the last entries. They look like this:

<location path="mywebsite/CFIDE/adminapi">
<ipSecurity allowUnlisted="false">
<add ipAddress="" subnetMask="" allowed="true" />
<add ipAddress="" subnetMask="" allowed="true" />
<location path="mywebsite/CFIDE/administrator">
<ipSecurity allowUnlisted="false">
<add ipAddress="" subnetMask="" allowed="true" />
<add ipAddress="" subnetMask="" allowed="true" />

The thing to note here is the "path" attribute and the first part of the path string. It is actually the "name" of the website in IIS. In other words, if the name of the web site (as displayed under sites in the left hand IIS navigation) is "joes barbershop" your path would actually be path="joes barbershop/CFIDE/Administrator". If you are like me and you put the domain name in as the site name then this is not as obvious as you might think.

Using this information I can duplicate these 2 nodes over and over again for each site I need to protect. I can even script the creation of these nodes if I need to. This saved me time on a grueling task. IIS picks up the change immediately too - as soon as you save the file. I Hope this helps you. Happy Admining to one and all.

Russ's Gravatar Another even quicker method, is to just create a web.config file with the IP address restrictions in it and just copy that into the CFIDE folder on each server.
Here is how to do that in case you don't know.
# Posted By Russ | 5/10/13 12:46 PM
Russ's Gravatar BTW, if you are doing this on public websites rather than your cfadmin website, you do realise that the IP restrictions will break any scripts which actually need to load from CFIDE, such as cfform validation, cftextarea and ajax stuff.
# Posted By Russ | 5/10/13 12:50 PM
Mark Kruger's Gravatar @Russ - yes the web.config file works as well with a slightly different syntax. not sure it is faster than editing a single file though.

As to breaking the scripts directory, by protecting only "admin" and "adminapi" instead of the whole "CFIDE" directory I am avoiding that issue. But we usually use a separate scripts directory with a setting in the admin for it and virtuals. That's a different admin task and equally exhausting if you have to do it after the fact (ha).
# Posted By Mark Kruger | 5/10/13 1:19 PM
Russ's Gravatar If you make a copy of the CFIDE with all folders removed except the required scripting stuff, this means no website is vulnerable and nothing needs to be locked down except the site that does have your cfadmin (default website). There isn't really any reason for all sites to have access the admin and adminapi etc folders anyway.
You can bulk change your vulnerbale CFIDE vdirs in the applicationhost.config too.
# Posted By Russ | 5/10/13 1:58 PM
Charlie Arehart's Gravatar Mark, good work as always.

But I would caution that rather than go through this bother of locking down all CFIDE admins by IP address, you'd do better (in IIS 7.5, as you're using) to instead install the Request Filtering feature (also not installed by default, but added the same was as the IP & Domain feature).

Then go to the server level and use this feature and its "URL" tab to add a "deny sequence" for /CFIDE/administrator. That will immediately block the use of that URL in all sites. (And you'd want to do the same for /CFIDE/adminapi and /CFIDE/componentutils, at a minimum.)

Then you'd go to any sites where you DO want to allow access to the Admin (hopefully only one or very few), and then use the Request Filtering feature at the site level to "remove" that deny sequence that was added. (And remove only the /CFIDE/administrator, not the other two added above.)

Then you could add the IP address limitation as you have described.

There are two key benefits of this approach: first, it automatically propagates to all sites. Second, it propagates to all FUTURE sites.

With the approach you've listed, a problem is that if you later add a new site, and then rerun the CF 10 web server config tool, it will add a CFIDE virtual directory to all sites and now that site's admin will be "open", if you don't think to add the lock down of the admin directory by IP address.

Again, that would not happen with the request filtering approach.

This is indeed the approach discussed in the CF10 lockdown guide, and I can confirm it's worked for several dozen customers I've worked with.

For those on IIS 7.0, there is no request filtering interface that can be added, but it is still configurable in the applicationhost.config file, and that approach is discussed in the CF9 lockdown guide.

Hope that's helpful to you and readers.
# Posted By Charlie Arehart | 5/11/13 12:09 AM
James Moberg's Gravatar Here's my current global rewrite rule that I have in the applicationhost.config. (I recently added "railo-context" because a PCI scanner started requesting it and causing ColdFusion errors to occur.)

[rule name="Block CFIDE" enabled="true" patternSyntax="ECMAScript" stopProcessing="true"]
[match url="^(cfide|railo-context|default.|Trustkeeper).*$" /]
[conditions logicalGrouping="MatchAll" trackAllCaptures="false"]
[add input="{REMOTE_ADDR}" pattern="^(192.168.1.[0-9]{1,3})(.*)$" negate="true" /]
[add input="{REMOTE_ADDR}" pattern="^($" negate="true" /]
[action type="CustomResponse" statusCode="404" statusReason="File or directory not found." statusDescription="The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable." /]
# Posted By James Moberg | 5/13/13 12:48 PM
Mark Kruger's Gravatar @Charlie,

Great tip - thanks.


Nice... love the regex. Very helpful.

# Posted By Mark Kruger | 5/13/13 12:50 PM
Dries's Gravatar @Charlie
And what's the option in IIS 6?
I want to lock all the CFIDE folder (adminapi, administrator & componentutils for more then 100 sites.

# Posted By Dries | 7/3/13 8:19 PM
James Moberg's Gravatar To lock down IIS6, we wrote a URLRewrite rule using Ionic's Isapi Rewrite Filter (IIRF) so that only an internal IP class could access any files located with /CFIDE/ in the path. (We since upgraded and use IIS7 and use the Microsoft Rewrite Module. It's more reliable.)

Here's a link to IIRF:
# Posted By James Moberg | 7/3/13 8:37 PM

Blog provided and hosted by CF Webtools. Blog Sofware by Ray Camden.