Requirements
 
Prerequisite knowledge
Basic knowledge of web application development with ColdFusion
 
User level: All
 
 
 
 
Required products
 
 
Sample files
 

 
Introduction

One of the main design considerations for ColdFusion platform is to provide a secure environment for web applications.  We always focus on security by providing the right tools for developers and administrators to protect their web applications & servers from emerging security vulnerabilities and attacks. Also, there were many security enhancements and bug fixes provided in ColdFusion 11. ColdFusion 11 Standard Edition now allows creating multiple sandboxes.
 
This article will provide an overview of various vulnerabilities handled in ColdFusion 11. After reading this article and applying some of the tips mentioned here, you will be able to write more secure and safe web applications.
 

 
Features and Enhancements

 
Concurrent logins for same user
Using ColdFusion 11, we can configure whether to restrict a user to one login session or to allow multiple login sessions. Also, we can configure for same user, whether to allow concurrent logon sessions or to restrict him to a single session when using the Administrator console. ColdFusion by default allows concurrent logins using the CFLogin tag.
 
ColdFusion 11 added a new attribute allowConcurrent for this purpose. Setting this to true allows any number of sessions from the end user whereas setting it to false restrict users to have only one logged in session. What happens to the first login session when allowConcurrent is set to true and when the user is trying to make a second login from another browser? In this case, the first session gets logged out and the user login succeeds. To see this in action, setup the authentication example from here and In Application.cfc set cflogin allowConcurrent attribute to true/false for observing concurrent logins and a single login restriction.
 
Using ColdFusion 11, you can even allow/disallow multiple logins to the Administrator console for the same user. The setting can be found at the Security > Administrator page. When secure profile is enabled, the Administrator console will be restricted to allow only one login session from a user.
 
Concurrent logins for ColdFusion Administrator
Figure 1. Concurrent logins for ColdFusion Administrator
 
Two new methods have been added to the admin API, security.cfc to get and set the concurrent login setting of the administration console.
 
isAllowConcurrentAdminLogin() – Returns true if concurrent login can be enabled from the Administrator console.
 
setAllowConcurrentAdminLogin – Enable/Disable concurrent login session setting from the Administrator console.
 
In ColdFusion 11, we have added a new attribute 'session' to cflogout tag to enumerate the sessions to be logged out. It gives logout control over the other login sessions of the same user. This attribute takes 3 values:
 
  • Current: Logs out the current user active login session.
  • Others: Logout all other active sessions other than the current login session.
  • All: Logs out all the user active sessions.
<cflogout session="all|current|others">
If the session attribute is not used, ColdFusion logs you out from the current user login session.
 
In ColdFusion 11, we added a new attribute useBasicAuth to the cflogin tag which takes a Boolean value. Default value of this flag is true. When set to false, cflogin ignores checking authorization header while validating the login.
 
 
Secure Profile changes
ColdFusion 10 introduced secure profile that can only be enabled during the installation. The purpose of secure profile is to apply more secure defaults to the server configuration instead of adding them manually. ColdFusion 11 provided a facility to enable/disable the secure profile using the ColdFusion Administrator post installation. When secure profile is enabled, values for the list of settings will be updated with the secure defaults and a snapshot of the current values for the list of settings is stored.
 
When secure profile is disabled using ColdFusion Administrator, the list of settings will be updated with the values from the snapshot. However, there is one difference. If secure profile is enabled during ColdFusion standard installation, then the directory browsing gets disabled on the built-in web server. Directory browsing can’t be enabled/disabled when secure profile is enabled/disabled from the Administrator console. When secure profile is enabled, the default value for the cflocation tag addToken attribute will be false. You can disable directory browsing by setting the listings (search for it in the file) parameter value to false in
 
<CF_HOME>\runtime\conf\web.xml file.
 
New methods have been added to the admin API security.cfc to enable/disable and get the secure profile:
 
  • enableSecureProfile () – Enables secure profile and applies all secure defaults to the settings.
  • disableSecureProfile() – Disables using secure profile and updates the settings with the values stored in the snapshot.
  • getAllSecureProfileSettingsInArray– Returns an array of structures that contains the secure profile settings. Each such structure contains the following fields:
    • name – Name of the secure profile setting
    • securedefault – Secure Default value for the setting
    • currentdefault – Current Value of the secure profile setting
    • default – Value of secure profile setting when secure profile is enabled.
Secure Profile setting from administrator
Figure 2. Secure Profile setting from administrator
 
ColdFusion 10 provided an IP-based restriction for the ColdFusion Administrator. In ColdFusion 11, the same IP Address restriction has been extended to other ColdFusion internal components as well. The IP address restriction applies to the below list of URLs. To view/change these settings, navigate to Security > Allowed IP Addresses > Allowed IP Addresses for ColdFusion internal Components.
 
  • CFIDE/main/*
  • CFIDE/adminapi/*
  • CFIDE/administrator/* (Admin Console)
  • CFIDE/componentutils/*
  • CFIDE/wizards/*
  • CFIDE/servermanager/*
 
Server Installation Profiles
Using server profiles, you can enable/disable some configuration settings based on how you are deploying the ColdFusion Server. The installer allows ColdFusion to be installed in one of these server profiles.
 
Server Profiles while installation
Figure 3. Server Profiles while installation
 
  • Development profile
    Development profile is useful when you are setting it up for development purpose. Selecting this profile gives you an environment suitable for debugging and logging and with very limited security settings. Suitable for development environments.
  • Production Profile
    Production profile is useful when you are installing ColdFusion for production environment. Selecting this profile disables RDS, enforces complex passwords, and provides options to disable some of the servlets with some medium security settings.
  • Production Secure Profile
    This profile is same as production profile but the only difference is selecting this profile enables secure profile adds secure defaults to the settings specified in the secure profile. Highly recommended for production environments.
Here is a table of comparison between these profiles:
 
Development Profile Production Profile Production Secure Profile
Enable all types of Debugging Yes No No
Remote Inspection of Mobile Application Yes No No
Disabling unused Servlets (e.g. Flashforms) No Yes Yes
Complex Password Enforcements No Yes Yes
Installation of Weinre and node.js servers Yes No No
Secure Profile is Enabled No No Yes
 
Before Installing the ColdFusion 11 in production environments, it is recommended that you go through the instructions specified in the lockdown guide and follow the same to completely lockdown your server.
 
 
Improvements to CfHttp tag
Server profiles allow you to enable/disable some configuration settings based on how you are deploying the ColdFusion Server. The installer allows ColdFusion to be installed in one of these server profiles.
 
ColdFusion 11 made some improvements around CFHTTP tag. Now, using ColdFusion 11, you can access the URLs protected using the NTLM authentication.  NTLM is a proprietary Microsoft protocol suite that can be used for HTTP-based authentication.
 
Follow these steps to access the content of URLs which are protected using the NTLM authentication.
 
  1. Set the authType tag attribute to NTLM
  2. Provide username and password through username and password tag attributes.
  3. If the target server uses domain level authentication, set the domain name with which the server will authenticate the given user credentials. If the target server uses local account authentication, set the workstation name with which the server authenticate the given user credentials.
Also, CFHTTP tag allows server name indication TLS extension when accessing the HTTPS URL’s on a server on which virtual hosting is enabled. It is useful when the hosting server uses only 1 IP address and hosts many virtual hosts each with its own SSL certificate. The SNI extension, which is sent by the client in a TLS handshake, contains the server name from the URL being requested. Based on the URL the server can select the virtual and send that certificate to the client. SNI is supported only if your ColdFusion server is running on Oracle 1.7+ JVM.
 

 
Cryptography related enhancements

Cryptography is the heart of the security for providing privacy, secrecy, and integrity for the data and for identifying the entity interacting with the system. We always look out for the opportunities to improve our crypto eco–system.
 
 
Email Encryption using CFMail tag
ColdFusion 11 added required necessary attributes to the CFMail tag in order to send an encrypted mails using Public key cryptography (PKI) infrastructure. Set the encrypt tag attribute to true then provide the recipient email certificate file path using recipientCert tag attribute, select the encryption algorithm to use from the list of supported algorithms and set it to encryptionAlgorithm attribute.
 
The list of supported encryption algorithms are DES_EDE3_CBC, RC2_CBC (default), AES128_CBC, AES192_CBC, AES256_CBC.
 
Here is a simple example which shows how to encrypt the emails using the given PKCS#7 format certificate and the encryption algorithm.
 
<cfset path = GetDirectoryFromPath(getCurrentTemplatePath())> <cfset algorithms = "DES_EDE3_CBC, RC2_CBC, AES128_CBC, AES192_CBC, AES256_CBC"> <cfloop index="algo" list="#algorithms#"> <cfmail to="user@org.com" from="manager@org.com" subject="Testing Encrypted Algorithm : #algo#" encrypt="true" ENCRYPTIONALGORITHM = "#algo#" recipientcert="#path#cert.p7c"> This message is encrypted using the algorithm: #algo#.Let me know if you can read it!! </cfmail> </cfloop>
 
Key Derivation from Password using PBKDF2
PBKDF2 is a key derivation function standard which is used to derive a cryptographically strong random key of any desired size from the humanly manageable password or passphrase. The key generated from this function can be used as an encryption key to the encryption algorithms and message authentication code (HMAC) algorithms. This is basically a password based encryption standard. As it can generate any size key the derived encryption key can be used along with any encryption/HMAC algorithm.
 
Along with the password or passphrase the function also requires few other parameters Salt and Iteration count. Salt is used to reduce the ability to use dictionary tables against the data encrypted using the derived from the password using PBKDF2. Adding Salt to the password enforces all the passwords present in the dictionary table to be rehashed using Salt which slows down the attack process. Recommended salt length is of 64 bits (8 characters). Iteration count is to specify how many times the given PBKDF2 algorithm need to perform on the given input password in order to derive the encryption key. Having higher iteration count further slows down the process of cracking the password. Recommended iteration count is 1000.
 
Here is a simple example which shows how to encrypt or decrypt the input data from the user given password. Every time we encrypt the data using the PBKDF2 generate salt of some size using a pseudo-random function and store it along with the encrypted data. The Salt generated during the encryption is required to decrypt the same data with the user given password using PBKDF2.
 
<!--- Encryption using PBKDF2 ---> <cfscript> // store the salt salt= Rand("SHA1PRNG"); writeOutput("Salt: " & salt & "<br/>"); // get the password from a form parameter password = "Password@123"; PBKDFAlgorithm = "PBKDF2WithHmacSHA1"; dataToEncrypt= "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"; encryptionAlgorithm = "AES"; derivedKey = GeneratePBKDFKey(PBKDFAlgorithm ,password ,salt,4096,128); writeOutput("Generated PBKDFKey (Base 64) : " & derivedKey & "<br/>"); writeOutput("Data Before Encryption: " & dataToEncrypt & "<br/>"); encryptedData = encrypt(dataToEncrypt, derivedKey, encryptionAlgorithm, "BASE64"); writeoutput("Data After Encryption: " & encryptedData & "<br/>"); </cfscript> <!--- Decryption using PBKDF2 ---> <cfscript> // get Salt from the data and store it in salt variable // get the password from a form parameter password = "Password@123"; PBKDFAlgorithm = "PBKDF2WithHmacSHA1"; derivedKey = GeneratePBKDFKey(PBKDFAlgorithm ,password ,salt,4096,128); decryptedData = decrypt(encryptedData, derivedKey, encryptionAlgorithm, "BASE64"); writeoutput("Data After Decryption: " & decryptedData); </cfscript>
The supported algorithms are PBKDF2WithHmacSHA1, PBKDF2WithSHA1, PBKDF2WithSHA224, PBKDF2WithSHA256, PBKDF2WithSHA384, PBKDF2WithSHA512
 
Note: Any time while using cryptographic related functions/ tag attributes if you receive an error message like “Illegal key size or default parameters” make sure to install the unlimited strength jurisdiction policy files to your JRE.
 

 
New APIs to validate and sanitize the input

Secure Input Validation and Output sanitization is one of the secure programming technique which to be followed when the web application handles the input supplied from users, browsers, clients etc. The thumb rule is to validate the input prior to use and sanitize the output before flushing it to the user. ColdFusion 10 already provides major set of validation and sanitization functions in different areas like HTML, CSS and JavaScript. ColdFusion 11 extended this set further by providing the APIs for XPath, XML and AntiSamy.
 
 
AntiSamy Support
Any time if your website is displaying some text on a page that may possibly have the end user control over it, you should be concerned about the possibility of Cross Site Scripting (XSS). XSS is usually caused when the user input contains malicious JavaScript and it is echoed back on the user’s browser.  If you think the input which comes from user should not be containing any HTML/CSS/JavaScript content you can simply escape/encode the input using the encoding functions EncodeForXXX provided by ColdFusion. If you are dealing with a forum kind of website then there is a need to accept HTML/CSS content from user in order to facilitate rich text formatting and interactive data. In this case we can’t escape the input as this needs to be rendered in the browser. But leaving this leaves the website for numerous possibilities of XSS.
 
AntiSamy provides an answer to this question of how can I accept HTML/CSS content without causing XSS. AntiSamy is named after the Myspace worm developed by Samy.  AntiSamy validates using a policy file in which we can specify which HTML tags, attributes, CSS properties are allowed in the input (whitelisting).  AntiSamy gives more flexibility over validation/sanitization on the given input by providing rules, directives, validating tag attributes or CSS properties using regular expressions. AntiSamy validates/sanitizes the input based on the policy file configuration and also provides user friendly error message as feedback when the input given is not following the rules specified in policy file.
 
ColdFusion 11 provides two functions isSafeHTML, getSafeHTML to validate and sanitize the given HTML markup against a policy file. Check the documentation for the complete function syntax.
 
IsSafeHTML can be used to know whether the given input markup follows the rules specified in the policy. It returns true/false. If the input contains an html tag which is not allowed/present in the policy file (or) an html tag attribute or CSS property value which is not in the list of valid values the function returns false. Simply if the input doesn’t stick to the rules specified in the policy returns false, else true.
 
GetSafeHTML can be used to clean the given dirty HTML markup by running through the rules specified in the policy and returns clean HTML which is valid according to the policy and considered to be safe. It runs the rules specified in the policy file by removing the tags which are set to be removed/ not present in the policy, removing the tag attributes which are not having valid values etc. Setting throwOnError argument to true throws an exception through which you can access user friendly error messages which specifies what went wrong with the input if the input doesn’t stick to the rules.
 
ColdFusion ships a default AntiSamy policy file which can be located at <CF_HOME>\cfusion\lib\antisamy-basic.xml. Default AntiSamy policy file for these functions can be set at application level using the key this.security.antisamypolicy in application.cfc and the value must be an absolute path or relative to the application CFC.  If the functions are not provided with a policy file makes use of the application level policy file for validation/sanitization if present, otherwise uses the server level default policy.
 
Below is a simple example which shows how to use these functions to perform AntiSamy style of validation on the given input which can contain potential malicious HTML/CSS/JavaScript.
 
<!-- this input ideally comes from user replace it with form parameter name --> <cfsavecontent variable="dirtyInput" > <b style="color:#ff0000">Bold Input</b> <script>alert(document.cookie);</script> </cfsavecontent> <cfoutput > <b>Original String:</b> #Encodeforhtml(dirtyInput)# <br/> </cfoutput> <cfoutput> <b>isSafeHTML:</b> #isSafehtml(dirtyinput)# <br/><br/> </cfoutput> <cfoutput> <b>Safe HTML (AntiSamy Clean):</b> #getSafehtml(dirtyInput)#<br/> <b>Safe HTML (AntiSamy Clean):</b> #Encodeforhtml(getsafehtml(dirtyInput))#<br/><br/> </cfoutput> <cftry> <!--- uses application level antisamy policy if configured otherwise server level one ---> <cfoutput> <b>Safe HTML (AntiSamy Clean):</b> #getSafehtml(dirtyInput,"",false)#<br/></cfoutput> <cfcatch name="cleanErrors" type="application" > <cfoutput > Errors in the input: #cleanErrors.detail# </cfoutput> </cfcatch> </cftry> <cfoutput > <b>Safe HTML (AntiSamy Clean):</b> #getSafehtml(dirtyInput,"c:\test\antisamy-custom.xml",true)#<br/> </cfoutput>
 
New Encoding Function for XML, XPATH
XPath Injection
 
XPath is a query language used to navigate through the elements and attributes in an XML document and to extract the data within them. If web applications uses XML documents to store the data they construct XPath queries to access the data in XML document in response to the user supplied input. If the given user input is injected into the XPath query without performing any validation/sanitization, the attacker can be able to manipulate the query and access the data for which he/she is not authorized.
 
In most cases XML documents won’t be used for storing application data instead they will be used for storing application configuration metadata which may contain admin user credentials, roles and access permissions. A simple example would be tomcat-users.xml which tomcat uses as a user data store for authentication. From a conceptual point of view, XPath injection is very similar to SQL injection. XPath injection (Blind XPath injection) can also be caused even when the attacker has no knowledge about the structure of the xml document by using the XPath functions which provides the metadata about the XML elements.
 
Consider a web application that uses XPath to query an XML document where one must provide their username and password to retrieve their stored credit card information.
 
<datastore> <users> <user firstname="Steve" lastname="Tucci" password="Password123" username="steve" creditcard=”1234 5678 1234 5678”/> <user firstname="Alice" lastname="Guy" password="PKIGuy90" username="alice" creditcard=”5678 1234 1234 5678”/> <user firstname="Bob" lastname="Partner" password="SquareBob45" username="bob" creditcard=”5968 1234 1251 5679”/> <user firstname="Mallory" lastname="Eaves" password="IamBad420" username="mallory" creditcard=”5679 4301 0321 4314”/> </users> </datastore>
The below example code is used shows retrieving the credit card information based on the given user and password over a login form.
 
<cfset authQuery = "//user[@username='#form.name#' and @password = '#form.password#']/@creditcard"> <cfset creditCard = xmlsearch("users.xml","#authQuery#")>
The above code is vulnerable to XPath injection. The attacker can cause XPath injection by passing the username value as steve’ or ‘1’=’1 and any value in password. Using these strings attacker can by-pass authentication and will be able to retrieve any credit card information.  ColdFusion 11 provides a new encoding function encodeForXPath which can be used to prevent XPath injection attacks. Before passing any user supplied input to the XPath query sanitize it using encodeForXPath function. To make the above code immune from XPath injection change it to below
 
<cfset authQuery = "//user[@username='# encodeForXPath(form.name#)' and @password = '#encodeForXPath(form.password)#']/@creditcard"> <cfset creditCard = xmlsearch("users.xml","#authQuery#")>
A cleaner approach would be to use parameterized xpath queries where the input is substituted with a parameter placeholder and values will be supplied for those parameters. This approach is same as SQL prepared statements. ColdFusion 10 already incorporated this facility in xmlSearch function where we can specify a parameterized xpath query and values for those can be specified using the params argument.
 
<cfset authQuery = "//user[@username=$username and @password = $password]/@roles"> <cfset params = structNew()> <cfset params[‘username’]=form.name> <cfset params[‘password’]=form.password> <cfset creditcard = xmlSearch(“users.xml”,”#authQuery#”,params)>
Always use parameterized XPath queries against to encoding the input. Use this encoding method in case to retrofit any legacy code where you can not change the dynamic xpath queries to parameterized one.
 
XML Attribute Injection
 
When any user supplied given user placed into the XML attribute value without proper encoding will lead to vulnerabilities and allows the user input to inject not only value for the attribute and also gives access to further modify the XML document. ColdFusion 11 added a new encoding function encodeForXMLAttribute which needs to be used before substituting the user given input into the XML attribute.
 
A simple example would be an Application using XML document as a user & admin store and receives new user/admin account requests through XML messages which in-turn will be constructed by a trusted system. The trusted system constructs those messages from the user supplied input. Assume the XML document user store looks like below.
 
<store> <users> <user isAdmin="true"> <firstname>Kelly</firstname> <lastname>Brooks</lastname> <password>Hola1Vista</password> <username>kellyb</username> </user> <user> <firstname>Marvel</firstname> <lastname>Madman</lastname> <password>Bonjour!2</password> <username>mmadman</username> </user> </users> </store>
To create the users/admins the trusted system must send account create request using XML message. It constructs the XML message using the user supplied input as below.
 
<cffunction name="getCreateUserXML" output="true" > <cfargument name="username" required="true" type="string" > <cfargument name="password" required="true" type="string" > <cfargument name="isAdmin" required="false" type="boolean" default="false"> <!--- Get User Element XML---> <cfsavecontent variable="userXML" > <CreateUser> <user username="#username#" password="#password#" <cfif isAdmin> <cfoutput>isAdmin="true"</cfoutput> </cfif> > </user> </CreateUser> </cfsavecontent> <cfreturn userXML> </cffunction> <!--- Logic for creating normal users ---> <cfif structkeyExists("form","username") and structKeyExists("form","password")> <cfset createUser= getCreateUserXML(form.username,form.password)> <!--- logic to send this message to the end system which will create these users ---> </cfif> <!--- Logic for creating admin users ---> <cfif structkeyExists("form","username") and structKeyExists("form","password")> <cfset createUser= getCreateUserXML(form.username,form.password,true)> <!--- logic to send this message to the end system which will create these users ---> </cfif>
The constructed message for both admins and users is same except that the attribute is Admin. Now an attacker can go through the normal user registration user process still can get admin privileges by sending the password as
 
Password” isAdmin=”true
To get protected from such type of attacks wherever you are trying to substitute xml attribute value with user supplied input make sure to use encodeForXMLAttribute function. Changing the code to use this encoding function will prevent the vulnerability. Use decodeForHTML method to get the real value which is encoded using this method.
 
<cfsavecontent variable="userXML" > <CreateUser> <user username="#encodeforxmlattribute(username)#" password="#encodeforxmlattribute(password)#" <cfif isAdmin> <cfoutput >isAdmin="true"</cfoutput> </cfif> > </user> </CreateUser> </cfsavecontent>

 
Where to go from here

Now you have an understanding of how to secure your applications and also about the new security features in ColdFusion 11. To understand more about antisamy, creating policies and few example policies, check OWASP AntiSamy project. ColdFusion 11 provides a few more tools to secure your applications. I have written some blog entries explaining these features in detail. See the resources below for more information: