Securing your applications URL variables

Article on how you can create tamper proof urls for your website or application using ColdFusion

2006-08-30 11:23:00.0

Securing your applications URL variables

On my current project, security is top priority. The application is working with sensitive financial data so I really have to lock things down. Like most of my solutions ideas, this idea spawned while in the shower and thinking of how I was going to secure my URL variables.

To give a bit of background on the problem:

The framework we are using is our in-house application framework powered by ColdFusion which we have improved over the last 5 or 6 years. The security lies in the actual framework but my project uses quite a bit of AJAX so my ajax calls need to be secured in someway. Why not use the existing framework security I hear you cry? Well I do...to a point. But this is more of an extension to it. Typically an ajax call is done via URL GET and normally to a small action file. This call could easily be called and modified by an unscrupulous person as the main framework security is sometimes bypassed.

The solution:

In my application I have users logged in and I hold their userId in the session variable session.userId

My url would typically look like:

The problem with this is that on the EditTimeSheet page you must in someway check that the user calling the url is valid and that the timeSheetId passed is actually the intended record.

Knowing that I am storing the current users ID in session.userId I reckoned I could use this variable to encode the URL and decode it automatically on the receiving end, again using the users session.userId as the decoding key.

When this link is now click on in the browser, it looks like:

The next thing we have to do is write some code to decrypt this URL on the receiving end. This is the code that does it:

What this code does is check to see if only one URL var is passed. Then it checks to see if has a & or a =. It then attempts to decrypt it using the session.userId and recreates the ColdFusion structure URL[]

In a simple example of the output, have a look at the screen below:

Now, the above is a simple example of the whole concept and I have hard coded USERID in place of SESSION.USERID.

The overall aim is to build 2 UDFs to do all the work and make it nice and reusable and cut down on duplicate code.

Problems with the solution:

One thing you may have asked yourself is what if someone tacks on another variable name/pair value? Will the whole thing be bypassed? Yes and No.
Not only are you masking the variables, your also masking the way your app is working so on the receiving end you could check to see if the first element of the new URL structs value is blank, then ignore the rest of the vars in the struct. This though assumes that you are always using this encoding method in your URLS and that the first element will always be an encrypted string.

One interesting thing of note:

ColdFusion has 2 inbuilt and not widely documented functions called cfusion_encrypt() and cfusion_decrypt() which are exactly the same as encrypt() and decrypt() except that the encoded string they produce is alphanumeric as opposed to all ASCII chars of the latter functions. This makes them perfect for what I need as we are passing and dealing with URL variables.

Download the example files as a ZIP file

I'd love to hear other peoples views and ideas on it, so drop me an email, skype me or simply comment :-)

Add to your del.icio.us    DIGG This!    Technorati Cosmos Link    Post to Reddit    Add to your Furl    Add to Blinklist
Comments [8] - Leave a comment

Comments

Hi Dan,

Love it and hate it in equal measure!!!

I love the simple, elegant approach to encrypting the data (if you wanted to be really fancy, you might want to add a seed to the user ID, but that's neither here nor there). On the other hand I hate the fact that it makes the URI's completely non-discoverable.

For me, the ideal solution is completely exposed, tranparent URIs with user security behind the scenes to make sure user X can do method y to record Z of object q. That way your app is accessible and discoverable while still being secure.

That said, if you want to obfuscate the URL variables, it is a cool approach! Of course, you also need to add the same for forms, and as for additional URl pairs, I'd just set it up as index.cfm?request_state=AE637HE9.... and would just decrypt URL.request_state into some kind of input struct, completely ignoring the rest of the URL.

Best Wishes,
Peter
I know you explained cfusion_encrypt/decrypt, but I don't think you were clear enough. These are NOT "official" functions. While they may work, there is no gaurantee that they will work in the future. In general, I recommend folks do not use these "hidden" functions as it could come back to bite you in the rear.
Daniel,

You might want to give the encrypt() and decrypt() functions in CF MX 7.x a look. They've added in several new encryption menthods, one of which may better suit your purpose without having to use the undocumented functions.
Hi All, thank you for taking the time to read it and share your thoughts.

Peter,

I agree about the discoverable aspect and I like your idea of the request_state and may actually adopt that method. I am particularly interested in not destroying the original URL Struct but to have my own info struct.

One of the main reasons for the non-discoverable aspect though was that it hides the mechanics of the application, which in the case of AJAX requests or quick actions I wouldnt necessarily want a discoverable URI as the communication is meant to be internal application communication (if that makes sense ;-) )

Raymond,

I thought that was coming ;-) I actually used Encrypt/Decrypt first and swapped in the cfusion_encrypt/cfusion_decrypt afterwards. The code is using CFEncodedFormat and so will also work with CFEncrypt/CFDecrypt. I am glad Rob posted too, I had missed the changes to the CFEncrypt function....

Rob,

Thank you for your tip on the new encryption methods. I missed those and am looking through them now to see if I can achieve an alpha/numeric encrypted URL.
Ryan McIlmoyl said:
You could also use the ToBase64, ToBinary and ToString functions when encrypting/decrypting to make the encrypted values URL safe.
Michael said:
Much thanks for this post... this was exactly the example I was looking for! My usage will be even simpler :)
Kathy said:
Just one quick note...

in your loop you are evaluating the length of the array on each pass through the loop.

It would be more efficient to set a variable to the array length before the <cfloop> and use that variable for the "to" value.
Robert Creedy said:
Works well. Saved me a lot of work. Thanks