A warning about ColdFusion's scriptProtect

It's not very often that you will hear me badmouth ColdFusion, but in this case, I feel compelled. ColdFusion has some truly fantastic features and in many ways make securing web applications easier, but in this case, it has provided little but a false-sense of security.

What is scriptProtect?

In case you are not familiar with ColdFusion's scriptProtect feature, it is a pattern matching utility that automatically checks all of the ColdFusion scopes over which an end user has control looking for what it deems is malicious script. It is designed to stop Cross-site scripting (XSS) attacks from being used against your application.

In other words, it checks the CGI, COOKIE, FORM and URL scopes looking for <script>, <meta>, <object>, <embed>, and <applet> tags. When it finds them, it replaces them with <InvalidTag>.

Just as with any countermeasure, scriptProtect is not perfect. The purpose of application security countermeasures is to mitigate risk. Risk can never be completely eliminated, so instead we talk about mitigating risk. This means that we reduce the risk to an acceptable level. So while it is true that scriptProtect does mitigate some risk, it does not reduce it enough to call it an adequate defense for even the most trivial applications.

Examples

First we'll look at some examples where scriptProtect does help.

When testing an application to XSS vulnerability, the first thing most penetration testers will do is try to pass in this value in a URL param or a form field.


<script>alert(123)</script>

If the script fires and an alert box appears, then an XSS vulnerability has been found. This may be harmless JavaScript, but if this JS will fire, then any will.

So let's use the following CFML document as an example of a vulnerable web page.


<html>
    <head>
        <title>XXS Tests</title>
    </head>
    
    <body>
        <cfparam name="url.name" default="" />
        <cfoutput>
            Hello #url.name#
        </cfoutput>
    </body>
</html>

This code is completely vulnerable to XSS attack. But we are not here to look at how to secure this page, right now we are looking at how well scriptProtect can stop attacks against this page.

Let's say that I use the following URL to request the page.


http://www.12robots.com/xsstest.cfm?name=Jason

This request would result in a page that says "Hello Jason". How very nice of it :)

But what if I requested the page with this URL?


http://www.12robots.com/xsstest.cfm?name=<script>alert(123)</script>

Now we would get a page that said "Hello alert(123)". And if we looked at the source code we would see:


<html>
    <head>
        <title>XXS Tests</title>
    </head>
    
    <body>
        
        
        Hello <InvalidTag>alert(1)</script>
        
    </body>

</html>

The InvalidTag would only show up in the source because it is surrounded by <>, so the browser would treat it as HTML, the alert function would simply be rendered as text on the page because it is not in an executable context. The InvalidTag tag succeeded in breaking the executable context that was injected.

This is a situation where scriptProtect works. It blocked the attack and rendered the script useless. It would do the same thing if someone tried to inject an <object> tag to add malicious Java to the page or a nefarious SWF.

But that is where scriptProtect stops being useful. These attacks above (which are what we would expects from complete amateur script-kiddies) are as basic as XSS gets. scriptProtect does nothing against even slightly more advanced attacks. Like these:


http://www.12robots.com/xsstest.cfm?name=<a href="" onmouseover="alert(123)">what am I?</script>


http://www.12robots.com/xsstest.cfm?name=<iframe src="http://someevilsite.com/exploit.php"></iframe>


http://www.12robots.com/xsstest.cfm?name=<body onload="alert(123)"></body>


http://www.12robots.com/xsstest.cfm?name=<a href="javascript:alert(123);">test</a>

ColdFusion's scriptProtect feature would not stop any of these attacks and these will all work in one browser or another, so even though most of them fail in the most recent version of Google Chrome, they all work in FireFox 3.5. So we need to realize that we cannot count on browser defenses to protect our users.

Options

Don't get me wrong, I am not telling you to run out and turn off scriptProtect. Some defense is better than none. My point is that if you are counting on scriptProtect to keep your application safe, then you need to stop.

The most important thing to do (but also the hardest) is to go and fix the code in your site that allows for user-generated output to be displayed unmodified. This is where the vulnerability comes from and by removing the vulnerability you will mitigate the risk. I have a post on mitigating XSS risk using HTMLEditFormat(), but it is a bit dated, and I have learned a lot since then. I will need to add more on XSS in the future. I also have an article coming in a future issue of FAQU that goes into great depth on XSS prevention.

Another option you have is to improve the regular expression matching in ColdFusion's scriptProtect. Both Pete Freitag and I have posts on doing this. Even if you opt to do this, it is still not enough. scriptProtect uses blacklist validation, which is never enough.

A third option is to implement a more robust Web Application Firewall (WAF). ColdFusion's scriptProtect is "kind of" a VERY simple WAF. There are MUCH better options out there including:

  • Foundeo Fuseguard - FuseGuard, created by Pete Freitag, is a commercial WAF written in CFML and designed for use with ColdFusion applications. It is unique because it works at the application level instead of the web server level. Working at the application level allows you to have different settings for different applications on the same server.
  • ModSecurity - ModSecurity, created by Ivan Ristic, is an open-source WAF that has been around for a long time. It has an pretty incredible feature set. It works at the web server level and can be deployed as an embedded proxy or reverse proxy.
  • Numerous others commercial and free OSS options are available.

Conclusion

Like I said, I do not like to badmouth ColdFusion. I LOVE ColdFusion and CFML. But the more I have looked at scriptProtect and learned about security, the more I realize that scriptProtect just doesn't cut it. And since it has not improved since version 7, I suspect it is not high on Adobe's list of things to look at. I intend to bring this up with Adobe in the future, but for right now, I felt it important for you to realize the shortcomings of this feature.

I have not looked at the implementation of scriptProtect in OpenBD or Railo. I suspect they work similarly.

Comments
RyanTJ's Gravatar There a project on RIAForge with lots of nice features called Portcullis that might help. http://portcullis.riaforge.org/
# Posted By RyanTJ | 3/1/10 12:43 PM
Jason Dean's Gravatar @ryan,

Thanks for brining up Portcullis. I have not looked at it, but I hear it is much improved from previous version where I think it was over-zealous in its filtering. I will take a look. I see that John did a Connect preso for the CFMeetup group.

UGTV
http://www.carehart.org/ugtv/index.cfm

Portcullis Presentation
https://admin.na3.acrobat.com/_a204547676/p2372238...
# Posted By Jason Dean | 3/1/10 1:03 PM
Ben Nadel's Gravatar I have become a huge fan of htmlEditFormat() for this very purpose.
# Posted By Ben Nadel | 3/1/10 6:16 PM
Adrian Lynch's Gravatar A great read as I'm shoring up an old CF application against XSS and I needed details on why SP isn't up to the job.

It's worth noting that ESAPI is now the go to for all your XSS escaping needs: http://damonmiller.github.io/esapi4cf/
# Posted By Adrian Lynch | 4/28/15 7:36 AM
Adrian Lynch's Gravatar A great read as I'm shoring up an old CF application against XSS and I needed details on why SP isn't up to the job.

It's worth noting that ESAPI is now the go to for all your XSS escaping needs: http://damonmiller.github.io/esapi4cf/
# Posted By Adrian Lynch | 4/28/15 7:36 AM
Branden deBuhr's Gravatar XSS says it right in the name. The simplest solution to the issue that I can see is to protect the sites from any POST that comes from a different site. So set a sitename variable at the top of the page execution, and below that look at the referrer to see if it's defined as the actual site in question. Most programmers do not set up their sites to maliciously attack themselves. Another issue that i've recently noticed in our logs is that the real bad attacks don't seem to have an ip address in the request that appears in the logs. If a form post or information that would be submitted to a page is being executed but has no IP, then again, stop it dead in it's tracks with a cflocation and an abort.

Am I looking at this wrong?

BTW, Nice information in this page. Very good food for thought...
# Posted By Branden deBuhr | 3/8/16 4:13 PM
Branden deBuhr's Gravatar XSS says it right in the name. The simplest solution to the issue that I can see is to protect the sites from any POST that comes from a different site. So set a sitename variable at the top of the page execution, and below that look at the referrer to see if it's defined as the actual site in question. Most programmers do not set up their sites to maliciously attack themselves. Another issue that i've recently noticed in our logs is that the real bad attacks don't seem to have an ip address in the request that appears in the logs. If a form post or information that would be submitted to a page is being executed but has no IP, then again, stop it dead in it's tracks with a cflocation and an abort.

Am I looking at this wrong?

BTW, Nice information in this page. Very good food for thought...
# Posted By Branden deBuhr | 3/8/16 4:13 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1. Contact Blog Owner