Coldfusion Muse
Posted At : July 28, 2008 8:29 AM | Posted By : Mark Kruger

A Better Blacklist Function for SQLi

Please note - I have not changed my stance on the use of CFQUERYPARAM. The real "fix" for injection is validation routines for form inputs and binding variables using Cfqueryparam. A blacklist function (a function that checks for "known bad" input) is useful in that it provides protection on the perimeter. It can help you intercept hack attempts before they reach your DB - where presumably they would fail in any case. They are also useful for thwarting immediate threats if you discover a security flaw that might take some time to fix. The recent spate of attacks caused a proliferation of blacklist techniques from simple to complex. In my own post on the vulnerability of using string concatenated SQL I published a snippet that made use of the iSQLInject function from CF Lib. There is a better approach however.

Now it turns out that Mary Jo Sminkey (creator of the popular CF Webstore) has a regular expression that she uses for this purpose. Gabriel Read (of Evolution 7) has added to it and I think the result is a better approach than the isSQLInject( ) function (which can generate false positives rather easily). The link to Mary Jo's Regex and function can be found here. In fact, Mary Jo has provided an include that you can just drop into your Application.cfm page (or you might need to fiddle with OnRequest() if you are using application.cfc). It will automatically examine the URL, Form, CGI and Cookie Scopes for you.

Mary Jo's function utilizes ColdFusion's "ReFindNoCase()" function against a complex regex pattern. Gabriel Read took it a step futher and is using a Java class - java.util.regex.Pattern. Here's his approach.

<cfscript>
// Short list of db objects to protect
DBObj.short = 'database|function|procedure|role|table|trigger|user|view';
               
// Sql Threat Indicators
blackList = '@@|' &
'(?:alter.*?(#DBObj.short#))|' &
'cast.*?\(|' &
'char.*?\([\w]{2}\)|' &
'(?:create.*?(#DBObj.short#))|' &
'(?:declare.*?@|cursor)|' &
'delete.*?from.*?_|' &
'(?:drop.*?(#DBObj.short#))|' &
'exec.*?\(|' &
'insert.*?values.*?\(+?|' &
'schema[^\w]+?|' &
'sysObjects|' &
'truncate.*?table|' &
'update.*?set+?|' &
'[sx]p_[\w_]+?|' &
'\''.*?-{2}|-{2}.*?\''' &
'/\*.*?\*/';

// Build the java pattern matcher
rePattern = createObject('java', 'java.util.regex.Pattern');
rePattern = rePattern.compile(blackList);
reMatcher = rePattern.matcher('');
result = reMatcher.reset(lcase('truncate')).find();
</cfscript>

The "result" in the code of above returns either YES or NO. Why would you use this approach? Without testing I can't be sure, but I suspect that this approach might be beneficial in that this fairly large regex does not have to be compiled with each new check. Once the pattered has been added to the matcher object you can just use the reset().find() function as many times as needed for form, url, cgi and cookie variables - like so:

<cfloop collection="#url#" item="uItem">
   <cfif reMatcher.reset(lcase(url[uItem])).find()>
      <h4>Intruder... exterminate...exterminate....</h4>
      <cfabort>
   </cfif>
</cfloop>
You would want to test this of course, but it's possible that this approach would have less overhead than the one using ColdFusion's native ReFindNoCase. It could also be a negligible difference as well. I'm going to run a few tests myself and see what I can find out.

Related Blog Entries

Comments
Hi Mark...just to correct you, the RegEx was *always* Gabriel's work, not mine. Regular expressions give me headaches. ;-) I just used what he posted to CF-Talk to create a complete tool from it that made it easy to just drop right into an application to use as a scope scanner. Just to give proper credit where it is due! I'll update it later today with his new version, once I run some tests on it.
# Posted By Mary Jo Sminkey | 7/28/08 10:02 AM
Version 2 of the SQL Injection scanner is now available here:

http://www.cfwebstore.com/index.cfm?fuseaction=pag...

I loaded the scanner object into Application scope, so it will need that available in order to work. I've not done a ton of testing on this just yet, so use at your own risk!
# Posted By Mary Jo Sminkey | 7/28/08 11:13 AM
There was a little mistake in the scanner I posted earlier that could cause it to hang, if anyone downloaded it before, please grab the updated copy.
# Posted By Mary Jo Sminkey | 7/28/08 12:56 PM
I switched to using the java pattern matcher from the native cf refind due to an issue with long strings and excessive backtraces overflowing the java stack and causing CF to sporadically hang. Someone can correct me if they think that I'm wrong, but I've found CF's regex capabilities quite poor.

(and thanks to Mark & Mary Jo for the credits)
# Posted By Gabriel Read | 7/28/08 6:16 PM
I can say that in some basic iteration tests I found your new version much more efficient. I'm sure a good deal of this also had to do with my loading the whole thing into application scope so the RegEx search didn't have to be recompiled each time, but the difference was more than a factor of 6, so a pretty obvious improvement.
# Posted By Mary Jo Sminkey | 7/29/08 1:18 PM
Just a quick note to anyone that is using this RegEx, or my tool, that I have still been seeing a number of false positives with it. I've passed on an example to Gabriel (let me know if you didn't get it!) so if he's able to address that, I'll update the tool and post a note here when/if it is available. One of my customers using it mentioned a problem with it blocking a string with some single quotes in it, but I personally haven't been able to reproduce that myself. In any case, if you use this, do be aware that it still may block some legitimate content.
# Posted By Mary Jo Sminkey | 8/4/08 12:02 PM
I've noticed a lot of people dropping by my site to download the SQL injection tool, so wanted to let you know that a new version is available. This uses a new RegEx provided by Luis Melo which in testing seems to have far fewer false positives than I was seeing before. I've also made some modifications to address a possible thread safety issue, and I changed the output message to address any possible false positives (which hopefully won't occur, but if they do, I prefer to give the user some useful information for what to do next). As before, you can just cfinclude the file wherever is appropriate for your application. Just be sure you are adding those cfqueryparams as well! Download is here:

http://www.cfwebstore.com/index.cfm?fuseaction=pag...
# Posted By Mary Jo Sminkey | 8/20/08 1:51 PM



Blog provided and hosted by CF Webtools. Blog Sofware by Ray Camden.