Enhancing ColdFusion Script Protection - Security Series #10
So anyone that has ever turned on Script Protection has either been annoyed by something that it does, or by something that it doesn't do. For me, it was both. I recently spoke with someone at bFlex about it, and he was having some of the same issues I had had with ColdFusion Script Protection. So, I finally decided to dig into it and see what could be done.
The Problem
There are two problems with ColdFusion Script Protection:- It covers too much
- It doesn't cover enough
Well, that weird, isn't it? Yes, it's true. Script Protection is too strong and too weak at the same time.
Too Strong
"Too strong" might no be exactly the right way to describe this behavior in script protection, but this behavior bugs me none-the-less.Let's say that someone tries to inject some Cross-Site Scripting code into the comments section of your blog. Something like:
<script type="text/javascript>
alert("pown'd");
</script>
Well ColdFusion Script Protection would turn that little diddy into this:
<InvalidTag type="text/javascript>
alert("pown'd");
</script>
That's exactly what we want. This part of script protection is great. It would do the same thing with the Object, Embed, Applet, and Meta tags.
Now, let's pretend that someone (maybe even me) wants to put something on my blog about Transfer-ORM configuration files. Which look like this:
<?xml version="1.0" encoding="UTF-8"?>
<objectDefinitions>
<package name="pages">
<InvalidTag name="page" table="pages">
<id name="pageid" type="UUID" />
<property name="pagename" type="string" nullable="false" />
<property name="pagetitle" type="string" nullable="true" />
...
<onetomany name="section" lazy="true">
<link to="pages.section" column="fkpageid"/>
<collection type="array">
<order property="sortno" order="asc"/>
</collection>
</onetomany>
</object>
...
</objectDefinitions>
</transfer>
Well, you see that <objectDefinitions> tag? It has the pattern "<object" in it. That means Script Protection is gonna see it as a threat.
So my Transfer config example is going to look like this.
<?xml version="1.0" encoding="UTF-8"?>
<InvalidTagDefinitions>
...
</objectDefinitions>
That sucks. And since the <objectDefinitions> is harmless when displayed, there is no reason for it to get filter like this.
This is the same issue that I heard about at bFlex, though a different tag was being filtered.
Too Weak
ColdFusion Script Protection is also too weak. It does not catch enough troublesome scripts. One of the biggies that it doesn't get, and I really can't understand why, is <iframe>.IFrames are incredibly dangerous and can be used for some pretty nefarious stuff. Granted, if you are properly escaping your user-generated output with HTMLEditFormat() this shouldn't be a concern, but it is a dangerous assumption to believe we are perfect. There may be some other tags or patterns we would like to see removed as well.
The Solution
So, it turns out that changing this behavior in ColdFusion Script Protection is pretty easy. There is an XML config file that contains patterns that are compared to the incoming data. If a match is made, then the replacement value is inserted. The patterns are simple Regular Expressions (RegEx).So not being an expert in Regular Expressions, I asked Ben Nadel to help me figure this out. He helped me find the RegEx solution I needed very quickly. Thanks Ben!
In your ColdFusion installation you will find a /lib folder.
Windows users: C:\ColdFusion8\lib Mac Users: /Applications/ColdFusion/lib *nix: /opt/coldfusion/lib (I think)
In the /lib folder you will find a file called neo-security.xml. Near the bottom of this file you'll see something that looks like:
<var name='CrossSiteScriptPatterns'>
<struct type='coldfusion.server.ConfigMap'>
<var name='<\s*(object|embed|script|applet|meta)'>
<string>
<InvalidTag
</string>
</var>
</struct>
</var>
What this is saying is, if you come across something that matches the RegEx Pattern "<\s*(object|embed|script|applet|meta)", then replace those characters with &lt;InvalidTag.
Now, normally I would think that this is fine, but like I said, I do not want <objectDefinition to be turned into <InvalidTagDefinition.
So, how do I stop this? Well first, I take the "object" text out of the existing patterns and make a new pattern with it. And I add a little extra.
<var name='CrossSiteScriptPatterns'>
<struct type='coldfusion.server.ConfigMap'>
<var name='<\s*(embed|script|applet|meta)'>
<string>
<InvalidTag
</string>
</var>
<var name='<\s*object(?!Definitions)'>
<string>
<InvalidTag
</string>
</var>
</struct>
</var>
So here, I have added another pattern for the XSS filter to try to match. This patterns says to match <object unless it is <objectDefinitions.
This could also be expanded to include additional patterns that begin with "<object".
<var name='CrossSiteScriptPatterns'>
<struct type='coldfusion.server.ConfigMap'>
<var name='<\s*(embed|script|applet|meta)'>
<string>
<InvalidTag
</string>
</var>
<var name='<\s*object(?!(Definitions|ive))'>
<string>
<InvalidTag
</string>
</var>
</struct>
</var>
Here, it will not match "<objectDefinitions" or "<objective".
Very nice.
Now to discuss adding the <iframe> tag. This is actually even easier.
<var name='CrossSiteScriptPatterns'>
<struct type='coldfusion.server.ConfigMap'>
<var name='<\s*(embed|script|applet|meta)'>
<string>
<InvalidTag
</string>
</var>
<var name='<\s*object(?!(Definitions|ive))'>
<string>
<InvalidTag
</string>
</var>
<var name='<\s*iframe'>
<string>
<InvalidTag
</string>
</var>
</struct>
</var>
Simply by adding another <var> to the <struct> I can add this pattern "<\s*iframe" which will find <iframe.
UPDATE: I forgot to mention in this post, after you change the neo-security.xml that you must restart the ColdFusion Application Server for the changes to take effect.





Rather than have a list of exceptions, it's simpler to only match where object (and all the other keywords) are the whole word - that is, they are terminated by a word boundary.
i.e.
<\s*(embed|script|applet|meta|object|iframe)\b
That still prevents <InvalidTag..> and so on, but gives more flexibility for safe stuff.
I agree that it would be simpler to only block <object rather than to block everything and add a list of exceptions. However, when it comes to blocking HTML and javascript, I believe erring on the side of caution is the right way to go. Also, hackers are a clever lot. They might figure out how to get past the block for <object with something like:
<script%20type="text/javascript">
or
<script%00%20teype="">
So in this case, I think the "Default Deny" mentality where we keep it closed and make exceptions is better than "Default Allow" where we open it up and add things to exclude.
That is a thought, however, there are SO many different types of attacks that could be used. I think it might be inefficient to use Script Protect.
It might be worth looking into an running some benchmarks on, but I suspect this is a job for something like a .htaccess file. As Luis Majano describes here: http://tinyurl.com/5cuzw5
Of course, erring on the side of caution, you should be escaping ALL tags, and then whitelisting acceptable ones, rather than blacklisting the six known/current risks.
Perhaps you are right and blocking only those tags is the better solution. I am trying not to deviate too much from the model that Adobe/Macromedia already had set up. Instead of redoing it completely, I am adding exceptions to it. To me, it seems the safer course. It is certainly possible Adobe/Macromedia knows something about XSS that I don't. Perhaps there are hacks that are possible even without using Null-characters or White-space characters.
Or possibly they just wrote bad regex to start with an never got around to fixing it.
That sure would be nice. I may have to submit that feature request. Thanks for the idea.
Also, thanks, you reminded me that I need to update my post. I forgot to mention that after you change the neo-security.xml that you must restart the ColdFusion Application Server.
I tried out scriptProtect in Railo (Barry) and in the few minutes I played with it seems to work similarly to ColdFusion's script Protect, except that it DOES block <iframe> tags. I did not test extensively enough to say otherwise.
I could not find a way to customize the scriptProtect feature of Railo, which is disappointing. If the code is buried in a jar somewhere, I would hate to have to recompile just to improve that support.
As for assumption, many of my security posts apply to Railo and OpenBD just as they would apply to PHP or Java. Most application security topics span all languages. But as for specific server features, like script protect or session management for example, do not assume that they work the same way in Railo or OpenBD. If I test either of the other engines, I will say so, but typically I work with Adobe ColdFusion, so that is my primary test bed.
Also, take a look at my recent post about scriptProtect which, likely, applies to Railo and OpenBD as well.
http://www.12robots.com/index.cfm/2010/3/1/A-warni...
I've read you Security series and "I liked it a lot" ;-)
Have made the switch to Railo last year and am developing for that CF-engine at the moment. It's free, it's wicked fast and it has those really nice administrators that I can use per client and one for the whole server. Furthermore it does most things CF8 does, and all the fuss about CF9 being so incredibly fast compared to CF8 - looking at the testdata I have my doubts (they use two different JRE's in the test, hopefully it's a typo but Adobe wasn't sure...).
As for the recent article, that was how I came upon this article ;-)
http://evgenwatch.com/