Jul
2009
Securing Your XML Config Files
Posted in Model-Glue, ColdFusion, Frameworks
Yesterday I rolled out a new site, http://www.blitztweets.com. I announced it on Twitter, a few folks retweeted (thanks!), and Ray Camden descended upon it like a vulture descends upon a wounded bunny in the high noon desert heat. Ray's got a knack for finding flaws in CF sites, and I'd be lying if I said I didn't have him in mind during development.
Overall, I think I did pretty well. He found two issues. First, my contact form could be submitted without the user filling in any fields. That was OK. I don't particularly mind if somebody really wants to send me an empty contact form. But the second issue... ooh, that was a doozy, and I'm duly embarrassed by it. He linked me to http://www.blitztweets.com/config/ColdSpring.xml, which proceeded to display the entire contents of the file in my browser window (it's since been fixed). Oops.
The site is built in Model-Glue 3, and is my first MG3 site. If memory serves, in Model-Glue 2, both the ModelGlue.xml and ColdSpring.xml were renamed with a .cfm extension. My first thought was to apply this same "fix" to the current site, but as Ray pointed out, the files would still be browseable. With that in mind, I set out to figure out the "best way" to secure the XML config files.
In my search, I noticed a couple of things. First, I was surprised that there wasn't more information out there on how to do this (or maybe I just suck at Google). Given the number of people that use any of the frameworks that make use of XML files, I'd have thought this would be a more popular topic. Second... like so many other things in this field, there is no "one true way".
I'll go over a few of the methods that I found, and describe the pros and cons (as I see them) for each.
Rename the .xml files with an .xml.cfm extension
This is undoubtedly one of the quickest fixes. But if somebody knows the path to your document they can still browse it. You can get around this by sticking an Application.cfm into your config directory with a <cfabort />. This method works, and I think a few of the popular CF frameworks make use of this security model out-of-the-box. While it works fine, there was something about it that just felt "hacky" to me. I'm not quite sure what it was, but I wanted to continue the search.
Moving the config files out of the webroot and using ColdFusion mappings
This was the first avenue that I explored, as suggested by Scott Stroz. I moved both of the XML files (ColdSpring.xml and ModelGlue.xml) out of the webroot and deleted the config folder. In my Application.cfc, I created a mapping to the new (not in the webroot) config folder. The path to ColdSpring.xml is defined in index.cfm, so I updated that to use the new mapping.
The path to ModelGlue.xml is defined in ColdSpring.xml. At first, I thought this was going to be a deal-breaker as I didn't think an XML file would recognize a ColdFusion mapping. However, both Todd Sharp and Jon Messer correctly pointed out that Model-Glue doesn't just import/read the XML file, it actually parses it, and it will recognize and respect the ColdFusion mapping.
My concern about this method is that the mapped path to the config folder is different on my development environment (OS X) than it is on my production box (Windows). This is easily handled with a conditional in the Application.cfc where I set the mapping (using cgi.http_host to determine the environment).
While this worked, I still wasn't quite comfortable with it. If I moved the location of the out-of-webroot config files, I'd have to remember to update the mapping. Not having all of the files together was also somewhat of a paradigm shift for me. I know there are people who rely heavily on mappings and don't put anything but view files in the webroot, and that's probably a model I should look into more... but for now, it was a little outside of my comfort zone.Apache to the rescue
I started using Apache on my development box back when I was on Windows. IIS (on non-server OS's) only allowed one (active) site at any given time, and switching sites was a pain. My current production server is a VPS that's also running Apache.
In my VirtualHosts directive for blitztweets, I added a new <Directory> directive that controlled my config directory (which was now back in the webroot). Inside I added:
Order deny,allow Deny from all
Upon browsing to the ColdSpring.xml file, I was greeted with the message, "You are not authorized to view this file". Perfect. Almost.
As far as I was concerned, it was OK that people knew they weren't authorized to view the file, but I'd prefer that they don't even know the file is there. Quick change to the <Directory> directive:
Redirect / /index.cfm/
This redirects the user to a non-existent Model-Glue event, which triggers my existing "missing event" error handler, and is the method that I ultimately settled on.
I'm sure there are probably several other creative ways to accomplish this (for example, Todd had mentioned he uses IIS to set a non-browseable permission on the config folder). Any of the above methods will work as well. Like so many other things, it's just a matter of finding which one feels most comfortable for you.


Comments
Add Comment | Subscribe to Comments
-
-
-
-
-
-
-
-
-
-
-
-
Add Comment# Posted Dan G. Switzer, II on 7/22/09 11:18 AM
@Charlie:
While the Application.cfm method does seem "hacky", that's basically the method I've always used (although I may implement *other* web server solutions *on top* of the Application.cfm implementation.)
The reason I like the Application.cfm is because it's guaranteed to work. If you migrate your code to a new server and forget to implement the Apache rules, then your code is vulnerable (unless you use an .htaccess file.) The Application.cfm hack migrates with your code.
Lastly, you could use a CFLOCATION tag in your Application.cfm to duplicate your Apache rule.
Just my 2 cents...
# Posted Scott Stroz on 7/22/09 11:24 AM
I typically set up my projects the way they will be deployed to production.
Using this as an example I might have:
{project}/wwwapp
{project}/wwwapp/config
{project}/wwwapp/www
I would then point Apache to {project}/wwwapp/www as my web root. This way, I need not worry about changing variables or mappings or anything else when deployed to production. For large projects, I would even set up a semi-automated process to handle deployment.
Undoubtedly, I would have more dirs under 'wwwapp', but I think yo get the idea.
# Posted Raymond Camden on 7/22/09 11:35 AM
And let me be clear - I forget to block the XML files all the time. I _just_ did it for RIAForge a few days ago. :)
But I do kick everyone's butt in MyBrute, so there.
# Posted Scott Stroz on 7/22/09 11:47 AM
@Ray - which is why I use the process that I do..it makes it much easier NOT to forget.
Also, it allows me to keep all my MG specific files, such as view files, controllers, services, etc out of the web root as well.
# Posted Steve Withington on 7/23/09 8:31 AM
Semi-related ... you mentioned:
"IIS (on non-server OS's) only allowed one (active) site at any given time, and switching sites was a pain."
Just thought I would mention this is technically incorrect. I threw together a quick blog post on how to do this rather easily: http://www.stephenwithington.com/blog/index.cfm/20...
# Posted Charlie Griefer on 7/23/09 8:47 AM
@Steve:
Thanks for the link. The 2nd method (modifying the hosts and using headers) looks pretty nice.
Right now, my production box is Apache, so I'm OK with my development box being Apache. If I find myself in a situation where I'm back on IIS in production, I'll definitely keep this in mind (since I generally try to keep dev and production as similar as possible)
# Posted Scott Stroz on 7/23/09 8:59 AM
@Steve - I am unable to view the videos from my iPhone, but, do these methods get around the XP limitation if having only one IIS site running at s time?
# Posted Steve Withington on 7/23/09 1:15 PM
@Scott,
I haven't used XP for quite some time now (just ordered upgrade for Windows 7 even) ... the main issue I remember was that you had to have XP Pro to use IIS 6.0 (at that time anyway). Today however, you can use IIS 7 on XP SP2 and the same methods should apply.
# Posted Jake Munson on 7/24/09 11:10 AM
Charlie,
You almost seemed to be apologizing for using Apache in your post...no need to be embarrassed, you're not alone. In fact, if anybody should be apologizing, it's IIS users, according to the market share numbers:
http://news.netcraft.com/archives/web_server_surve...
# Posted Charlie Griefer on 7/24/09 11:18 AM
@Jake - No, wasn't apologizing at all. Didn't mean for it to come across that way. I'd just always been on IIS, so that was my "comfort zone". If Steve had blogged his entry a few years back, I might still be on IIS (moved off just to be able to easily run multiple sites on my development machine). Back then, my production environment was a shared server with IIS, so that was a little uncomfortable (only in that there was a significant difference between my dev environment and production). Today I'm on a VPS and using Apache in production. So dev and production are "in sync", so I'm happy and unapologetic :)
I like Apache fine (I think I only know about 2% of it, but I like that 2%).
As far as Apache vs. IIS... I do my best to remain Switzerland-like in those types of debates :)
# Posted Jake Munson on 7/24/09 12:02 PM
@Charlie,
I hear ya. I'm like you, I like Apache, but I only know about 2% of it. That said, we use IIS here at work and I have had more than a few "pull my hair out" experiences with it. I have never had any with Apache, but that might be because I don't work with it very much (I mainly just use it, not administer it).
I'm more than happy to get in an IIS vs. Apache debate with people...but I try to keep emotions out of it (at least from my side of the debate). I think there are multitudes of reasons why Apache makes more sense than IIS, in a production environment. </2 cents>
# Posted Chris Peterson on 11/5/09 6:51 AM
Charlie, fwiw, I dont put view files for Model-Glue under the web root either, you can use a mapping for those as well. About the only thing I put under the actual web root are the Application.cfc, index.cfm, and any files that CF does not render (javascripts, css, images, etc).