Portcullis - Protect against SQL Injection and XSS

Apr 30, 2008

I recently released a public version of a CFC filter called Portcullis that can help protect your applications from SQL Injection and Cross site scripting attacks. It attempts to cover the areas that ColdFusion's script protect feature does not cover adequately.

http://labs.fusionlink.com/katapult/index.cfm?page=projects/portcullis

SQL Injection and XSS attacks have been the attacks du jour for hackers. They have also been in the OWASP's Top 10 most serious web application vulnerabilities for several years now (http://www.owasp.org/index.php/Top_10_2007). In fact, XSS (cross-site scripting) and injection attacks are ranked first and second respectively on the list.

Now since ColdFusion 7, we have had a functionality called "scriptprotect" that you can set in the cfapplication tag or in the application.cfc. There are several problems with this feature and to be honest I wish that Adobe rework their logic or make it very clear in the CFAdmin and documentation that this does not do very much. I see too many people turning this feature on and thinking their work is done.

If you do use ColdFusion's script protection, keep in mind a few things. Saying scriptprotect=true does NOT properly turn on script protection. It also does NOT error out, which it should due to the nature of this attribute. The setting should instead be a list of scopes you wish to protect. For example, scriptprotect="form,url,cookie" or scriptprotect="all". Secondly, the script protect feature is more geared towards XSS attacks. The thought being, I guess, that cfqueryparam and cfstoredproc will cover all the SQL injections? This is also a very bad assumption.

Unfortunately, their list of tags to strip is very easy for a hacker to walk around. To view and modify the settings for this, simply go to your neo-security.xml in the CFInstallDirectory\lib\..

At the bottom you will see..

<var name="CrossSiteScriptPatterns">
<struct type="coldfusion.server.ConfigMap">
<var name="&lt;\s*(object|embed|script|applet|meta)">
<string>&lt;InvalidTag</string>
</var>
</struct>
</var>

So ColdFusion's scriptprotect looks for tags in this list and replaces the bad tag with InvalidTag. Again this list is not very good. You should also include at the very least  "frame,iframe,frameset,layer,ilayer,form,input" to this list.

Another bad aspect to ColdFusion's script protect feature is that you have no log of the attacks or a methodology of stopping the attacker. There should be a method of logging these attacks and also to block the attacker's future requests. Hopefully, these items could appear in the next release of ColdFusion :)

Portcullis attempts to fill in these problems. With a more robust list of tags, keywords and SQL commands to filter out. It also logs the attempts and can temporarily block an IP that is sending the attacks.

Portcullis will work for ColdFusion versions 6 to 8. If you are using an older version of ColdFusion, I highly encourage you to use Shawn Gorrell's cf_xssblock tag. To be completely honest, Shawn's tag inspired Portcullis and he hits many of the same areas. You can find it at, http://www.illumineti.com/documents/xssblock.txt

Important Note:
If you are dealing with Ecommerce applications, bare in mind that PCI-DSS's requirement 6.6 is coming due on June 30th. You must have either a complete code review by a third-party that specializes in application security or have a Web Application Firewall (WAF) in place to protect your web-facing applications. Both are good, but in light of SQL Injection and XSS, having an application layer firewall provides another system to help filter and block these attacks and is highly encourage. FusionLink does provide WAF protection with their hosting.

Comments

Ed

Ed wrote on 05/05/08 5:16 PM

Isn't it something similar to cfFirewall? With the difference that cfFirewall allow you dynamically create protection rules, allow for IP blocking and more with it's special backoffice?
John Mason

John Mason wrote on 05/05/08 5:23 PM

First time I've heard of cfFirewall. It sounds interesting though. I'll take a look at it.
RebeccaST

RebeccaST wrote on 06/02/08 6:29 PM

Hi, can you explain a little further how Portcullis should work?

You said:
<cfset application.Portcullis.scan(url,"url",cgi.remote_addr)>
<cfset application.Portcullis.scan(form,"form",cgi.remote_addr)>
<cfset application.Portcullis.scan(cookie,"cookie",cgi.remote_addr)>

Do you have to put an explict URL in the "url"? Same with "form"? What goes in there? Can you do it globally? Ie. all urls...?

Thanks for any help.
Rebecca_ST
John Mason

John Mason wrote on 06/04/08 12:54 AM

The "url" is simlpy the scope you wish the information to be thrown back into. By default, it will scan all the variables in those scopes that you scan.
Marc

Marc wrote on 07/22/08 8:07 AM

I tried to add this to some of my sites, but noticed that traffic being referred to the sites from search engines (google, yahoo, etc) was being intercepted as "bad" traffic and it was blocked. Is this intended behavior or is there something I have misconfigured?
John Mason

John Mason wrote on 07/22/08 8:18 AM

@Marc

I'll email you directly. It really depends on how you configure things.
Chris Giaccone

Chris Giaccone wrote on 07/22/08 12:07 PM

Please email me as well. Any additional directions would be very helpful. I attempted to customize using the basic settings in the portcullis.cfc and they don't seem to be doing anything. Real world examples of proper entries for those settings would be great.
John Mason

John Mason wrote on 07/22/08 3:11 PM

@Chris..

I don't have your email. Feel free to email me at mason at fusionlink.com
James Moberg

James Moberg wrote on 08/06/08 3:59 PM

I found an issue. When scanning the cookie scope and using "domain" cookies, Portcullis incorrectly rewrites the cookies as "host" cookies. I was setting domain=".domain.com" and then watching as "www.domain.com"; cookies were being auto-generated by Portcullis with a "/" path and then another cookie created with a sub-directory path. When logging out, I'm deleting the domain cookie, but the unwanted host cookies linger and continue to work. Is there any way to fix this and determine cookie type and retain it? Thanks.
JoMo

JoMo wrote on 08/25/08 5:48 PM

Recently, a site we manage was hit with SQL injections, and Portcullis has done a great job stopping them.

However, this website has a form that uses htmleditformat to post blocks of HTML to the database. It seems that Portcullis is escaping characters (i.e. semi-colons) that are already escaped with htmleditformat.

E.g. < turns into <; So, I get an extra semi-colon...

If I toggled variables.instance.escapeChars to false, would it solve this problem? Would that seriously weaken the script?
John Mason

John Mason wrote on 08/25/08 8:38 PM

@JoMo, you have simply have Portcullis handle the htmleditformat. That way you wouldn't have it effectively running twice over and doing that.

@James, thanks for that note on the cookies. I'll have a fix for that in the next version.
John Mason

John Mason wrote on 08/25/08 9:14 PM

Correction, JoMo's initial comment was actually the easier option for this situation. Just turn the escapechars to false. The htmleditformat() is taking care of that job. It's important though to note that xmlformat() is actually slightly better. It escapes more stuff. Then the escapechars function in portcullis covers even more. Something to consider when refactoring things.
Catherine Mortali

Catherine Mortali wrote on 08/26/08 8:52 AM

John,
I've installed this on a couple of my smaller sites this morning to test. I'm also finding (as Marc) that search engine referrals as well as some other valid site links are causing an error/block.

I haven't made any modifications to the portcullis.cfc tag and thinking that I should. Still seeing a TON of cast attacks which is what I'm trying to avoid seeing!

Thanks.
John Mason

John Mason wrote on 08/26/08 11:45 AM

@Catherine, the default configuration for portcullis should be blocking the cast attacks. They will still try to hit the site though. They tend to roll through in waves. Unless you block ip addresses, you can't really block the attempts.

Portcullis can break some functionality of a site because it's looking for certain words to strip out. If you have reserved sql command words in your url like 'method=insert', then I would advise modifying your code a bit to do 'method=add' instead. You should avoid using key sql command words in any url statements. Feel me to email if you need any help with this at mason |at| fusionlink.com

Write your comment



(it will not be displayed)