DEV Community

Cover image for areBracesValid UDF for ColdFusion/CFML
James Moberg
James Moberg

Posted on

areBracesValid UDF for ColdFusion/CFML

Useful to determine if braces are correctly matched before processing. Helps reduce SQLi.

I was using a version of smartSearch from CFLib.org that I had updated with some simple regex detection for SQLi strings, but it wasn't catching everything. I considered disabling the bracket matching feature and rejecting any query search terms that attempted to use ( or ), but then considered that I should validate so that the feature could still be used since it is beneficial when not being exploited.

I couldn't find any UDFs on CFLib or other ColdFusion/CFML snippets to validate brackets in a string. (If there's existing code, let me know. I wasn't able to find it.) I read a couple recommendations on StackOverflow indicating that it shouldn't be validated using regex, so I wrote a UDF that reduces & validates braces in a string and returns a Boolean response. This allows us to determine whether we can safely use the string when generating a SQL search string (or use 1=0 as a fallback).

Source Code

https://gist.github.com/JamoCA/a35ffaabc00e0339a9996e27825159a7

<!--- areBracesValid ColdFusion/CFML UDF (2022-09-16)
Useful to determine if braces are correctly matched before processing. Helps reduce SQLi.
By James Moberg - SunStar Media https://www.sunstarmedia.com/
Gist: https://gist.github.com/JamoCA/a35ffaabc00e0339a9996e27825159a7
Blog: https://dev.to/gamesover/arebracesvalid-udf-for-coldfusioncfml-21fg
Tweet: https://twitter.com/gamesover/status/1570911352138641408
20220918 Updated to use single refind/replaceAll expressions
20221108 Updated to use "while" instead of cfloop/condition (which isn't supported by Lucee in cfscript.)
--->
<cfscript>
boolean function areBracesValid(required string string) hint="Validates if braces are correctly matched" {
local.string = javacast("string", arguments.string).replaceAll("[^\[\]\{\}\(\)]", "");
if (!len(local.string)) return true; // no braces
if (len(local.string) mod 2) return false; // odd number of braces
local.bracketFound = 1;
while (local.bracketFound) {
local.bracketFound = refind("(\(\))|(\[\])|(\{\})", local.string);
if (local.bracketFound){
local.string = local.string.replaceAll("(\(\))|(\[\])|(\{\})", "");
}
}
return (len(local.string)) ? false : true;
}
</cfscript>
<cfset tests = [
"1') AND 5410=3868 AND ('tVgF'='tVgF"
,"1') AND 3265=DBMS_PIPE.RECEIVE_MESSAGE(CHR(90)||CHR(76)||CHR(98)||CHR(98),5) AND ('wIxt'='wIxt"
,"(1=0) and (R.ID = 2)"
,"(([R].[Name] LIKE '%a%') OR ([R].[First] LIKE '%a%') OR ([R].[Last] LIKE '%a%') OR ([R].[Company] LIKE '%a%')) AND (([R].[Name] LIKE '%b%') OR ([R].[First] LIKE '%b%') OR ([R].[Last] LIKE '%b%') OR ([R].[Company] LIKE '%b%')) AND (([R].[Name] LIKE '%c%') OR ([R].[First] LIKE '%c%') OR ([R].[Last] LIKE '%c%') OR ([R].[Company] LIKE '%c%')) AND (([R].[Name] LIKE '%d%') OR ([R].[First] LIKE '%d%') OR ([R].[Last] LIKE '%d%') OR ([R].[Company] LIKE '%d%'))"
]>
<cfoutput>
<cfloop array="#tests#" index="test">
<fieldset>
<legend>#encodeforhtml(test)#</legend>
VALID = #areBracesValid(test)#
</fieldset>
</cfloop>
</cfoutput>

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (3)

Collapse
 
bennadel profile image
Ben Nadel

I was about to ask if you were using cfqueryparam for your search; but, I just looked at the Smart Search UDF, and it looks like it uses some SQL generation, which somewhat rules-out the parameterization.

Collapse
 
gamesover profile image
James Moberg

I use an internally updated version of SmartSearch. I've added logic to identify SQLi and return 1=0 if any is detected. (I'm planning on sharing my UDF updates, but will be releasing it on a new CFML resource website that I'm building.)

Collapse
 
bennadel profile image
Ben Nadel

Sounds exciting! Looking forward to seeing what you've got in store.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay