Application File Organization Security Concerns - Mach-II/Mach-II-Framework GitHub Wiki
- Using directory structure and webroot location to protect your XML files
- Using the web server layer to protect XML configuration files
- Use the CFML engine to protect configure files
- Final Note
Because configuration files are traditionally xml files, it is important to insure that no sensitive information is made available to someone able to download them. To insure this, it is recommended that you use one of the following methods.
This is by far the most effective, as it places your xml in a location that is inaccessible to HTTP Get and Post requests. The following example illustrates an application directory structure that only places in the web root those files that need to respond to and HTTP request.
|-+ ApplicationRoot
|- config
|- modules
|- listeners
|- filters
|- plugins
|- model
|- webroot
index.cfm
application.cfc
For more information, see Recommended Conventions
- Configuration files are outside the webroot and cannot be directly requested via the browser
- Simplified security that does not require "protection" of configuration files using rewriting rules / directory access permissions
- No further action needed to similarly protect configuration files from other frameworks such as ColdSpring, Transfer, etc.
- Hosting services may not allow for this structure
If you must keep your configuration files within the webroot then it is important to take steps to protect them. Controlling access to assets in the web space is best left to the web server. Therefore, the strongest protection is to use the web server to deny access to your configuration file.
Within the Apache configuration file, you could add the following in the website's .conf
file:
<Directory "/path/to/your/webroot/config">
AllowOverride None
Options None
Order allow,deny
Deny from all
</Directory>
More globally, this would also work (you may have to enable the mod_rewrite
package first):
RewriteEngine On
RewriteRule .+\.xml$ /index.html [L,NC,QSA,R]
Combining the two, you could use the following:
NameVirtualHost *:80
<VirtualHost *:80>
ServerAdmin [email protected]
DocumentRoot "/path/to/your/webroot"
ServerName example.com
ErrorLog "logs/example.log"
CustomLog "logs/exampleaccess.log" common
RewriteEngine On
RewriteRule .+\.xml$ /index.html [L,NC,QSA,R]
<Directory "/path/to/your/webroot">
AllowOverride None
Options None
Order allow,deny
Allow from all
RewriteBase /
</Directory>
<Directory "/path/to/your/webroot/config">
AllowOverride None
Options None
Order allow,deny
Deny from all
</Directory>
</VirtualHost>
If you only wish to protect xml files inside the /config directory, or any sub directories then this following rewrite will suffice:
RewriteEngine On
RewriteRule ^/config/([A-Za-z0-9\-\_\/]+)*?\.xml$ [F]
The [F] is a forbidden command. The regex looks for any letter, number, '_', '-', or folders '/'. You can of course remove the /config/ to make this applicable site wide but I always like to leave space for other more general xml files eg: rss.xml or sitemap.xml
Denying directory access in IIS is also a simple matter:
- Using the IIS Admin applet, navigate to your website's config folder.
- Right-click on the folder and select "Properties".
- Go to the "Directory Security" tab, click the "Edit" button under "Anonymous Access and Authentication Control".
- Un-check "Allow Anonymous Access".
- No need to take further action to similarly protect other config files, as the web server will deny access to all files within the selected folder(s)
- Must have access to the web server
Your CFML engine can be used to protect the data in your configuration files. One common method is to change your mach-ii.xml
file to a mach-ii.cfm
file. Then add the following to the top of your configuration file:
<!-- <cfsetting enablecfoutputonly="true" /><cfsilent> -->
And add the following to the end of the your configuration file:
<!-- </cfsilent> -->
Because the line is wrapped in XML comment tags, the line does not become part of the XML data, but your CFML engine will still process the <cfsetting>
and cfsilent
tags as usual, thus preventing output.
You could also add the following code to your Application.cfc
:
<cffunction name="onRequestStart" returnType="boolean" output="true">
<cfargument name="targetPage" type="string" required="true" />
<!--- Handle the request. Make sure we only process Mach-II requests. --->
<cfif NOT CompareNoCase('index.cfm', listLast(arguments.targetPage, '/'))>
<cfset handleRequest() />
<cfreturn true />
<cfelse>
<cfreturn false />
</cfif>
</cffunction>
The <cfreturn false />
will prevent the HTTP request from starting if the request is not to your application's index.cfm
page.
- Can be used even on a hosting service that does not allow files outside a webroot and does not give access to a webserver
- Must be added to every configuration file to be protected and leave a possible security hole if this technique is not applied to all configuration files.
- The configuration file is no longer XML and will not automatically validate against a DTD using common XML tools (XMLBuddy, etc). Further steps will need to be taken to validate your XML (CFML
xmlValidate()
function, Mach-II bootstrapper validation, etc)
Sensitive information should not go in plaintext .xml
or .cfm
files, regardless of the protections at the server or application level. Asset passwords (Database, FTP, etc), encryption keys, and other pieces of sensitive information should be stored elsewhere, such as your CFML engine administrator (such as database passwords) or in a database table with limited access. This limits the data's exposure far more than plaintext files on a web server does.