Monday, June 21, 2021

Two One-liners for Quick ColdFusion Static Analysis Security Testing

 I want to find all of the security bugs.  I'm sure you do too.  

(Click here to skip all the background info and just jump to the two one-liners.) 

Some security bug classes are easy to find at scale through automated dynamic security scanning.  Maybe you're also doing some manual application penetration testing.  And maybe you can invest the time to perform in-depth manual code review of important portions of an application, such as core libraries and high-value actions.  But a high-impact vulnerability -- such as remote code execution -- in an insignificant, overlooked portion of your codebase can ruin your day.  Automated code review needs to play a part in any software security effort.

There are a handful of static analysis tools available that support ColdFusion and CFML.  While some of them performed very well in benchmark testing, I found that these tools did not consistently flag some basic vulnerable code statements, even when the "alert on everything" knobs were turned to 11.

I had a collection of grep, awk, and Perl one-liners living in my shell history for quick-and-dirty CFML code reviews.  Most of them had to do with searching for various tags and functions that could be dangerous, and doing further manual review of the results.  But every time I wanted to do some quick automated code review, I had to find them and re-remember how to run and tweak them.  I wanted something that was a little more repeatable, so I wound up building some custom CFML static analysis tooling.  The full toolset isn't being released at this time, but I am releasing two one-liners.  They won't find all of the bugs, hopefully they help you find some bugs.

At its core, it's a "smart" grep that can be used to search for user-controlled input in dangerous tags and functions.  Many dangerous CFML tags and functions are well-known and have been documented elsewhere.  For example, maybe you want to look for tags and functions that can lead to SSRF.  Examples of user-controlled data can include any of the following:

  • Variables in the URL Scope
  • Variables in the FORM Scope
  • Some Variables in the CGI Scope
  • Cookies (Variables in the COOKIE Scope)
I wound up using pcregrep, since it was "good enough" for a functional proof-of-concept and offered easy multi-line matching support.  ColdFusion and CFML support various syntaxes and styles, with both tags and function statements.  These regexes have tended to work for me, though you may want to tweak them further if your code style is significantly different.  

I'll also mention that I am okay with a higher false-positive rate if it means a much lower false-negative rate.  I don't want to miss any security bugs that simple greps can find.  I'll happily spend some time reviewing potential false-positives if it means more thorough automated code coverage.  (For example, the regexes below treat the entire CGI scope as tainted, and don't account for the CGI variables that the user can't directly control.  And we'll also miss cases where input validation of user-controlled input actually happens elsewhere in the code.)  This process hopefully gives us a funneled data set, where we take a very large amount of information and are left with a smaller amount of manageable, actionable items after some human review.


With that long introduction, I offer the two one-liners below.  Consider the following contrived vulnerable code:


[...]

<dangerousTag 

arg="#url.foo#">

</dangerousTag>

[...]

<cfscript>

dangerousFunc(url.foo,#url.bar#);

</cfscript>

[...]


Sample usage below.  You'll need to change dangerousFunc and dangerousTag to the actual function or tag you want to search for, and /path/to/code/ to your actual source path.

% pcregrep --include=.{cfc,cfm} --color=always -Minr '(?s)(?<!\w)(dangerousFunc\()([^\)]*)(?<!\w)(url\.|form\.|cookie\.|cgi\.)([^\)]*)\)'  /path/to/code/


Output: 

/path/to/code/oops.cfm:12:dangerousFunc(url.foo,#url.bar#);


pcregrep  --color=always -Minr '(?s)<dangerousTag\s([^>]*)(?<!\w)(url\.|form\.|cookie\.|cgi\.)([^>]*)>'  /path/to/code/


Output:

/path/to/code/oops.cfm:2:<dangerousTag 

arg="#url.foo#">


Using these one-liners is still a somewhat manual process, since you need to check tags and functions individually, but they provide the foundation for something that can be expanded upon, in areas in such as:

  • Additional automation
  • Support for tainted variables (i.e., those derived from user-controlled input sources)
  • Regex cleanup
  • Dealing with de-duplication of findings
  • Permanent suppression of false-positive findings
  • Report generation
  • Integration with CI/CD pipelines
  • Integration with ticketing workflows
  • Enhancements with IAST (Interactive Application Security Testing) and runtime analysis
Though these items are left as a topic for another day, or an exercise for the reader ...as is fixing all the bugs that you find. :)



No comments:

Post a Comment