Blog

Brad Wood

October 07, 2019

Spread the word


Share your thoughts

More and more people are using CommandBox or our Ortus Docker containers (powered by CommandBox) for production deployments.  Commandbox uses JBoss Undertow which is very lightweight and fast, and capable of service traffic just as fast as IIS or Apache.  A lot of people ask me about running CommandBox in production and I always say it's fine so long as you follow the same basic lockdown procedures you'd take on any web server.  If you have IIS or Apache sitting in front of CommandBox, most of this configuration can happen there, but for people who want drop-dead simple prod servers, here's some quick tips on locking down your CommandBox server.

Server Settings

Most of CommandBox's settings are secure-by-default, but just to mention a couple:

web.directoryBrowsing 

Make sure this is set to false so a visitor can't view files on your server in directories with no index.cfm

server set web.directoryBrowsing=false

web.errorPages

We have a default 404 page for static assets which are not found, but consider setting up a custom error page.

server set web.errorPages.404=/404.html

app.cfengine

Consider pinning this to a specific version just so you don't get new releases without getting a chance to test them on your dev servers.

server set app.cfengine=lucee@5.3.3+62

debug / trace

Make sure you don't have the debug or trace flags enabled as they cause extra logging overhead and might unlock debugging features you don't want accessible like Tuckey's status page.

server set debug=false
server set trace=false

 

server.json

{                                     
    "app":{                           
        "cfengine":"lucee@5.3.3+62"   
    },                                
    "debug":"false",                  
    "trace":"false",                  
    "web":{                           
        "directoryBrowsing":"false",  
        "errorPages":{                
            "404":"/404.html"         
        }                             
    }                                 
}                                     

 

CF Engine Settings

You can automate your CF Engine's settings (Adobe, Lucee) with the CFConfig module.  These apply to any server, not just CommandBox, but here are some notable ones:

debuggingEnabled / robustExceptionEnabled

Toggle these to false.  They control "Enable Request Debugging Output" in Adobe and "Enable debugging" in Lucee.  Robust exceptions is an Adobe only setting.  

cfconfig set debuggingEnabled=false to=.cfconfig.json
cfconfig set robustExceptionEnabled=false to=.cfconfig.json

inspectTemplate

Set this to "never" if you'll not be doing any hot deploys of code, like Docker for faster performance.

cfconfig set inspectTemplate=never to=.cfconfig.json

adminPassword

Even if you block the web admin (which we'll cover below) make sure there is a solid, non-default password set in your web admins.  This can be exploited in Lucee by the CFAdmin tag for instance if someone guesses the password.

cfconfig set adminPassword=supersecure to=.cfconfig.json

generalErrorTemplate

Set to "secure" to enable the most secure error template for your engine.

cfconfig set generalErrorTemplate=secure to=.cfconfig.json

 

.cfconfig.json

{                                     
    "adminPassword":"supersecure",    
    "debuggingEnabled":"false",       
    "generalErrorTemplate":"secure",  
    "inspectTemplate":"never",        
    "robustExceptionEnabled":"false"  
}                                     

Secure Paths via Rewrites

Note: this section is now superseded by CommandBox's built-in security profiles.  There is no need to use the custom XML file below.  You can read about the secure profiles here: https://commandbox.ortusbooks.com/embedded-server/configuring-your-server/server-profiles

There are a lot of naughty things people can get to by guessing file paths that are web accessible.  CommandBox's URL Rewrite engine has an XML format you can use to block paths that hackers shouldn't be touching.  I'll cover each section, and then show the full file below.

Any references to /404.html would load a file of that name if you create it.  If 404.html doesn't exist, you'll simply get the default 404 handler in CommandBox.

Deny TRACE/TRACK HTTP Verb

The Trace/track HTTP verbs can be used for JS to access HTTP-only cookies by tricking the web server into reflecting the cookies back on a TRACE request. 

<rule>
    <condition type="method" casesensitive="false" operator="equal">TRACE|TRACK</condition>
    <set type="status">403</set>
    <to>null</to>
</rule>

Deny Administrative Access

Block all access to your web-based administrator.  This is where the majority of vulnerabilities have existed over the years.

<rule>
	<condition type="request-uri" casesensitive="false" operator="equal">/(CFIDE/administrator|CFIDE/adminapi|CFIDE/AIR|CFIDE/appdeployment|CFIDE/cfclient|CFIDE/classes|CFIDE/componentutils|CFIDE/debug|CFIDE/images|CFIDE/orm|CFIDE/portlets|CFIDE/scheduler|CFIDE/ServerManager|CFIDE/services|CFIDE/websocket|CFIDE/wizards|lucee/admin)/.*</condition>
	<from>^/(.+)$</from>
	<set type="status">404</set>
	<to type="passthrough" last="true">/404.html</to>
</rule>

Deny "hidden" files

Files starting with a period like ".htaccess" are meant to be "hidden" and your web server probably shouldn't serve them up.

<rule>
	<condition type="request-uri" operator="equal">.*/\..*</condition>
	<from>^/(.+)$</from>
	<set type="status">404</set>
	<to type="passthrough" last="true">/404.html</to>
</rule>

Deny common config files

There are a lot of common config files in your web root hackers may probe for.  Let's keep their hands off!

<rule>
	<condition type="request-uri" casesensitive="false" operator="equal">.*/(box.json|server.json|web.config|urlrewrite.xml|package.json|package-lock.json|Gulpfile.js|CFIDE/multiservermonitor-access-policy.xml|CFIDE/probe.cfm)</condition>
	<from>^/(.+)$</from>
	<set type="status">404</set>
	<to type="passthrough" last="true">/404.html</to>
</rule>

urlRewrite.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN" "http://tuckey.org/res/dtds/urlrewrite3.2.dtd">
<urlrewrite>

    <rule>
        <note>Deny TRACE/TRACK HTTP Verb</note>
        <condition type="method" casesensitive="false" operator="equal">TRACE|TRACK</condition>
        <set type="status">403</set>
        <to>null</to>
    </rule>

	<rule>
		<note>Deny Administrative Access</note>
		<!-- These are paths that don't exist on disk, but shouldn't get rewritten since the CF engine treats them special. -->
		<condition type="request-uri" casesensitive="false" operator="equal">/(CFIDE/administrator|CFIDE/adminapi|CFIDE/AIR|CFIDE/appdeployment|CFIDE/cfclient|CFIDE/classes|CFIDE/componentutils|CFIDE/debug|CFIDE/images|CFIDE/orm|CFIDE/portlets|CFIDE/scheduler|CFIDE/ServerManager|CFIDE/services|CFIDE/websocket|CFIDE/wizards|lucee/admin)/.*</condition>
		<from>^/(.+)$</from>
		<set type="status">404</set>
		<to type="passthrough" last="true">/404.html</to>
	</rule>

	<rule>
		<note>Deny "hidden" files</note>
		<condition type="request-uri" operator="equal">.*/\..*</condition>
		<from>^/(.+)$</from>
		<set type="status">404</set>
		<to type="passthrough" last="true">/404.html</to>
	</rule>

	<rule>
		<note>Deny common config files</note>
		<condition type="request-uri" casesensitive="false" operator="equal">.*/(box.json|server.json|web.config|urlrewrite.xml|package.json|package-lock.json|Gulpfile.js|CFIDE/multiservermonitor-access-policy.xml|CFIDE/probe.cfm)</condition>
		<from>^/(.+)$</from>
		<set type="status">404</set>
		<to type="passthrough" last="true">/404.html</to>
	</rule>

	<!-- Remove this if you don't need ColdBox-style rewrites in your app, or put your custom rewrite rules here. -->	
	<rule>
		<note>Generic Front-Controller URLs</note>
		<!-- These are paths that don't exist on disk, but shouldn't get rewritten since the CF engine treats them special. -->
		<condition type="request-uri" operator="notequal">^/(flex2gateway|flashservices/gateway|messagebroker|lucee|rest|cfide|CFIDE|cfformgateway|jrunscripts|cf_scripts|mapping-tag|CFFileServlet)/.*</condition>
		<!-- This is a special URL that can be enabled with debugging -->
		<condition type="request-uri" operator="notequal">^/tuckey-status</condition>
		<!-- Used for the Adobe CF 2018 performance monitoring service -->
		<condition type="request-uri" operator="notequal">^/pms$</condition>
		<!-- Browsers like to send this request and it will get rewritten to /index.cfm/favicon.ico when it really just needs to be a 404 -->
		<condition type="request-uri" operator="notequal">^/favicon.ico</condition>
		<!-- Ignore any path to a .cfm or .cfml file in a sub directory that has a path info attached. These won't trigger as "real" directories below
		since the rewrite filter doesn't know what part is the actual file name.  Note, the ses path info servlet filter hasn't fired yet. -->
		<condition type="request-uri" operator="notequal">^/.*\.cf(m|ml)/.*</condition>
		<!-- Do not rewrite paths that point to real files or directories -->
		<condition type="request-filename" operator="notdir"/>
		<condition type="request-filename" operator="notfile"/>
		<!-- Turn localhost/foo into localhost/index.cfm/foo -->
		<from>^/(.+)$</from>
		<to type="passthrough">/index.cfm/$1</to>
	</rule>

</urlrewrite>

You would use the previous file with this command:

server set web.rewrites.config=urlRewrite.xml

 

 

Add Your Comment

(5)

Nov 21, 2019 05:57:15 UTC

by George Murphy

Can we please update files for Lucee also? Not just CFIDE

Nov 21, 2019 08:38:13 UTC

by Brad Wood

George, these files do already include Lucee. If you look, you'll see part of the blocked paths include lucee/admin at the end of the list.

Jul 28, 2020 19:27:38 UTC

by David Levin

Is there a way to check the list or define static assets (like js or css files)? It appears that calling a static file that doesn't exist attempts to execute a ColdBox event and I get an "EventHandlerNotRegisteredException" exception. For example http://127.0.0.1:62680/idonotexist.js

Jul 28, 2020 19:54:08 UTC

by Bradley D Wood

David, that's just how the rewrites work. You can adjust the regex to not apply to those file types. Right now, if the file doesn't exist, we assume the rewrite needs to happen.

Dec 08, 2020 06:28:47 UTC

by Dan Card

You might also need to check if server set web.rewrites.enabled=true One other note in the "Deny Administrative Access" is to add "|lucee/doc" at the end of the list of conditions. This is a setting checked by HackMyCF so it will help get you a "clean bill of health".

Recent Entries

Must-See ITB 2025 Sessions for TestBox Users!

Must-See ITB 2025 Sessions for TestBox Users!

Are you a fan of TestBox or looking to level up your testing game in 2025? Whether you're just getting started with unit testing or you're already building advanced specs for ColdBox and BoxLang apps, Into the Box 2025 has an exciting lineup tailored just for you. Into the Box 2025 has an exciting lineup tailored just for you. With the recent launch of TestBox 6.3.0 we have amazing new tools, features and tips and tricks to get your testing experience to the next level, review our sessions and test like a pro efficiently and easy!

From hands-on testing strategies to BoxLang innovations, here are the sessions you won’t want to miss this May — and why they matter to you as a TestBox user.

Maria Jose Herrera
Maria Jose Herrera
April 17, 2025
The Into the Box 2025 Agenda is LIVE and Done!

The Into the Box 2025 Agenda is LIVE and Done!

The wait is over! The official Into the Box 2025 agenda is now live — and it's packed with high-impact sessions designed for modern CFML and BoxLang developers. Whether you’re building APIs, modernizing legacy apps, diving into serverless, or exploring AI integrations, this is the conference you’ve been waiting for.

Here’s a look at what you can expect — categorized by key topics to help you plan your learning journey, there’s something for everyone covering modern CFML tools and BoxLang:

Maria Jose Herrera
Maria Jose Herrera
April 15, 2025
Only 2 Days Left to Lock In Early Bird Pricing for Into the Box 2025!

Only 2 Days Left to Lock In Early Bird Pricing for Into the Box 2025!

The countdown is on. You have just two days left to secure your Early Bird ticket  for just $199 to Into the Box 2025 before prices increase on April 16.

We are proud to offer an engaging and high-value online experience for developers around the world. With a virtual ticket, you get more than just access — you get ongoing value that supports your growth long after the conference ends.

Maria Jose Herrera
Maria Jose Herrera
April 14, 2025