ColdFusion session fixation and jsessionid

A web application is vulnerable to a session fixation attack if an unauthenticated user’s session ID does not change after authentication. A malicious user could start an unauthenticated session and give the associated session ID to the victim. Once the victim authenticates, the malicious user now shares that authenticated session.

ColdFusion introduced SessionRotate in CF10 to mitigate such attacks. However, it only applies to CFID and CFTOKEN (ColdFusion sessions). If you are using J2EE sessions, there is no SessionRotate. This is unfortunate, as the ColdFusion documentation has stated for years that J2EE sessions have advantages over ColdFusion sessions (see Configuring and using session variables), the foremost being that J2EE sessions are not persistent. It’s also unfortunate, because this is an important security-related tag that only works under certain server configurations–and fails silently under others!

As a side note, J2EE has been called JEE (Java Enterprise Edition) since Java 1.4. The ColdFusion administrator continues to refer to it as J2EE, but you are likely to see references to JEE in reference material online.

Session rotation basically consists of:

  • Deleting the user’s current session
  • Creating a new session containing the same data, but with a different ID

Jason Dean at 12robots.com wrote about mitigating session fixation on ColdFusion in Session token rotation REVISITED and other articles. His posts were helpful in explaining the issue and offering a solution for rotating ColdFusion sessions on pre-CF10 systems. However, he posted no solution for JEE sessions.

But according to the CF documentation on Ending a session: You cannot destroy the session and create a session on the same request, as creating a new session involves sending session cookies back.

That’s problematic. Once a user authenticates, we can destroy the user’s session. But how do we create the new, authenticated session?

An answer posted in response to ColdFusion Session Fixation on StackOverflow suggests the solution is to store necessary data in a secure way and pass the data, or a token associated with that data, on to a new HTTP request. I considered, for example, generating a UUID as a nonce and storing it in a database along with the username and a near-future timestamp. The user would then be directed to a URL with the nonce appended as a token, which could be validated against the database to authenticate the user.

Fortunately, a simpler solution exists. Pete Freitag posted SessionRotate solution for JEE Sessions in March, 2014. By accessing properties of the Java servlet session running under ColdFusion, his methods perform the following steps:

  • Copy the session scope into a temporary variable
  • Remove the ID and URL tokens from the temporary variable
  • Invalidate the existing session
  • Create a new session
  • Copy the attributes of the temporary variable into the new session

The final step is somewhat more complicated, as the new session is apparently not immediately available, and copying the attributes happens in the Application.cfc’s OnSessionStart. Still, it can happen in a single request! The JEE documentation on Creating and Managing User Sessions has more information about the underlying JEE sessions.

When I implemented Pete Freitag’s solution, I made the following modifications:

  • I created a jeeSession.cfc containing:
    1. rotate (originally named jeeSessionRotate)
    2. copy (containing most of onSessionStart)
  • I created jeeSecureApp.cfc containing:
    1. onSessionStart
    2. an instance of jeeSession.cfc

I can modify the cfcomponent tag in the Application.cfc of any app to include:
extends="jeeSecureApp"

Then jeeSession.rotate() is available.

Caveats:

  • If your application already extends a CFC, you’d have to adjust this approach.
  • If your application already defines an onSessionStart, you’d want to add a call to super.onSessionStart

createDateTime is not a valid date format

While transferring an application from a ColdFusion 9 server to a ColdFusion 10 server, it produced the following error:
createDateTime is not a valid date format

I was able to trace the error to the following line:
parseDateTime(myDate, 'yyyymmdd')

(Of note is that the troublesome line does not actually call createDateTime. Maybe it does under the hood?)

The myDate variable was the result of a createDate call, and looked like this:
{ts '1985-10-26 00:00:00'}

I have no idea why ‘yyyymmdd’ was specified as the expected format, nor do I know why CF9 was more forgiving about it than CF10. If you run into this error, the format parameter is definitely something to check.

As an aside, the Adobe documentation is terrible as usual: https://wikidocs.adobe.com/wiki/display/coldfusionen/ParseDateTime

It lists 2 parameters, date/time string and pop-conversion, but gives no examples of the latter. And of course there is a 3rd parameter, the date format. This is the documentation for CF11–as far as I can tell there is no pop-conversion parameter in CF10 or earlier–but the page does not clearly indicate which version it covers, nor does it provide a link to the same content for earlier versions.

Converting lines to a list in ColdFusion

I’m so used to dealing with comma-delimited lists in ColdFusion that I would sometimes take a data file that had one item per line and replace the newline characters with commas.

It’s easy to use the carriage return [chr(13)] and line feed [chr(10)] characters as list delimiters, though, and remove the intermediary step. Here’s a quick example:

<cfsavecontent variable="data">
this
is
a
list
with
one
word
per
line
</cfsavecontent>

<cfoutput>
    <ol>
        <cfloop list="#data#" delimiters="#chr(13)##chr(10)#" index="line">
            <li>#line#</li>
        </cfloop>
    </ol>
</cfoutput>

Which produces the following:

  1. this
  2. is
  3. a
  4. list
  5. with
  6. one
  7. word
  8. per
  9. line

(I can’t believe I didn’t think of this until today!)

Set operations in ColdFusion

Today I needed to get all the elements in one list that were not members of a second list. That may ring a bell — it’s known as a set difference, or a relative complement.

Although it would have been simple to loop through first the list and add only the elements not present in the second list to a new list, I thought I would look around to see if anyone had already implemented set operations in ColdFusion, e.g. on cflib.org. I was surprised that I didn’t find anything, so I decided to create my own, as much as an exercise as anything, and posted it to Bitbucket:
arraySet: ColdFusion set operations

I included the following operations:

  • union
  • intersection
  • set difference
  • subset
  • equality
  • size

In the process, I experimented with MXUnit, a unit testing suite for ColdFusion that integrates with Eclipse. (I am currently taking a Scala programming course that emphasizes Test-Driven Development, or TDD, so I thought I should try it in CF as well.)

Since I was implementing sets using arrays as the underlying data structure, I also decided to use cfinterface to define a set interface, which arraySet implements. I had never used cfinterface before, and although its usefulness has been questioned, it seemed more appropriate than extending a base set class.

Using a lightweight web server to debug requests

I’ve been working a lot with the Canvas API lately. One task was to add communication channels (e-mail addresses) to user accounts. I was able to add them successfully following the documentation’s cURL example using the skip_confirmation flag:

curl 'https://mycanvas.instructure.com/api/v1/users/[user id]/communication_channels'
-H "Authorization: Bearer [...]"
-d 'communication_channel[address]=chris@osric.com'
-d 'communication_channel[type]=email'
-d 'skip_confirmation=1'

However, when I ran the ColdFusion script I wrote, the user received notification of the addition even though the skip_confirmation flag was set:

<cfhttp url="https://mycanvas.instructure.com/api/v1/users/[user id]/communication_channels" method="post">
<cfhttpparam type="header" name="Authorization" value="Bearer [...]" />
<cfhttpparam type="formfield" name="communication_channel[address]" value="chris@osric.com" />
<cfhttpparam type="formfield" name="communication_channel[type]" value="email" />
<cfhttpparam type="formfield" name="skip_confirmation" value="1" />
</cfhttp>

Why didn’t the latter work as expected?

I needed to be able to tell what was different about the 2 requests, but it would be difficult to capture that outbound requests. Tools like Fiddler and WireShark could help, but I was sending one request from my local machine and another from a remote web server.

My idea for capturing the request data was to send the request to a server under my control. I grabbed a Python echo server and modified it slightly to print the data received. Then, instead of sending the requests to the Canvas API I sent them to the echo server. Here are the results of the 2 requests:

cURL
POST / HTTP/1.1
User-Agent: curl/7.24.0 (i686-pc-cygwin) libcurl/7.24.0 OpenSSL/0.9.8t zlib/1.2.5 libidn/1.22 libssh2/1.3.0
Host: osric.com:50000
Accept: */*
Authorization: Bearer [...]
Content-Length: 100
Content-Type: application/x-www-form-urlencoded

communication_channel[address]=chris@osric.com&communications_channel[type]=email&skip_confirmation=1

ColdFusion
POST / HTTP/1.1
User-Agent: ColdFusion
Content-Type: application/x-www-form-urlencoded
Connection: close
Authorization: Bearer [...]
Content-Length: 118
Host: osric.com:50000

communication%5Fchannel%5Baddress%5D=chris%40osric%2Ecom&communications%5Fchannel%5Btype%5D=email&skip%5Fconfirmation=1

I noted the different content lengths for the same data, and upon closer inspection, ColdFusion was URL-encoding characters. I added the encoded attribute to the cfhttpparam tags with a value of “no”, and then the request bodies were identical:

<cfhttp url="https://mycanvas.instructure.com/api/v1/users/[user id]/communication_channels" method="post">
<cfhttpparam type="header" name="Authorization" value="Bearer [...]" />
<cfhttpparam type="formfield" encoded="no" name="communication_channel[address]" value="chris@osric.com" />
<cfhttpparam type="formfield" encoded="no" name="communication_channel[type]" value="email" />
<cfhttpparam type="formfield" encoded="no" name="skip_confirmation" value="1" />
</cfhttp>

Not surprisingly that solved the problem.

Balancing Tags in HTML and XHTML Excerpts

It is fairly common to want to take an HTML source of variable length and display an excerpt. Although some formats, such as Atom and RSS, anticipate this and create a separate summary element, we don’t always have the luxury of using such a data source.

Creating an excerpt introduces a problem, though: if we create an excerpt based on a number of words or characters, we may end up with unbalanced HTML or even broken tags.

One solution is to discard all tags and display plain text, but this is often unsatisfactory.

Here is my method of balancing tags. It assumes that the input is an excerpt of a valid XHTML snippet. The reason for this requirement has to do with self-closing tags, which I hope will be apparent from the description:
Continue reading Balancing Tags in HTML and XHTML Excerpts

Oracle stored procedures and ColdFusion

I’ve heard for years that using Oracle’s stored procedures is both more efficient and more secure than writing queries against the database. It turns out, not everyone agrees with that and there is quite a bit of room for debate (most of the articles focus on MS-SQL Server and T-SQL, not Oracle and PL/SQL, although some general principles still apply):

I was still interested in how to use Oracle stored procedures with ColdFusion, though.
Continue reading Oracle stored procedures and ColdFusion

CFFTP Transfers a Zero-Byte File and Throws a Timeout Error

Although I’ve used ColdFusion for 7+ years now, I’ve never used the cfftp tag before. Yesterday, I found a reason to try it out. I figured it would be as simple as cfhttp–and it was, with one exception (no pun intended).

Here is my sample code:

<cfftp action="open" 
    connection="test"
    server="ftp.osric.com"
    username="chris"
    password="********************"
    timeout="60"
    stoponerror="yes">
<cfftp  
    connection = "test" 
    action = "getFile"  
    name = "downloadFile"  
    transferMode = "binary"  
    localFile = "S:\chris\handlebar-moustache.jpg"  
    remoteFile = "handlebar-moustache.jpg"
    timeout="60">

Here’s the error message it produced:
An error occurred during the FTP getFile operation.
Error: getFile operation exceeded timeout.

However, the local file was still created (as a zero-byte file).

The solution, in my case, was to turn on passive mode (add attribute passive="yes" to the cfftp tag).

Active FTP vs. Passive FTP, a Definitive Explanation has a brief explanation of the differences between active and passive FTP.

Joes Goals Runs on Cold Fusion

I use a pretty nifty little website called joe’s goals to track some of the things in my life. It ties in rather nicely with the google personal homepage, and has served me well for more than two years. It’s crashing today, and from the look of it, it runs on cold fusion. I must admit, I’m a little surprised. (Not that I have anything against cold fusion, you just don’t see it that often these days)

Code Reviews

I recently attended a code review at Wharton. We’ve put together some code reviews at my job, but I know that Wharton has been doing formal code reviews for years and I wanted to check out their process to compare notes. For this particular code review they were looking at a small ColdFusion application developed using Squidhead.
Continue reading Code Reviews