Pete Freitag Pete Freitag

Scope Injection in CFML

Updated on October 28, 2022
By Pete Freitag
coldfusion

Here is an interesting vulnerability that I have come across several times in real CFML code during code reviews, I have spoken about it at conferences but have never written about it. Since it doesn't really have a name, I call it Scope Injection, you'll see why in a minute.

We have the following code:

<cfif session.isAdmin>
    Do something only an admin can do...
</cfif>

Now lets suppose that this session.isAdmin is set upon a successful authentication, but for unauthenticated sessions isAdmin is undefined in the session scope (onSessionStart does not initialize it).

Now suppose a request to the above code like this:

/admin/something.cfm?session.isAdmin=1

What happens when the above code example is run:

  • CF checks to see if session.isAdmin is defined in the session scope
  • The variable session.isAdmin was not defined in the session scope, so it starts searching other scopes, such as the url scope.
  • CF finds url.session.isAdmin defined and uses that value to evaluate the if statement as true.
  • Code that should only be executed by an admin can actually be executed by anyone.

Mitigating Scope Injection in CFML

To mitigate this, you should make sure that variables are initialized properly, a good place to do this is in your Application.cfc event lifecycle methods, onSessionStart for session scoped variables, onApplicationStart for application scoped variables, onRequestStart for request scope variables, etc.

So to mitigate this issue, we simply need this:

<cffunction name="onSessionStart">
    <cfset session.isAdmin = false>
</cffunction>

If you are extra paranoid you can also use StructKeyExists to make sure the variable is defined:

<cfif StructKeyExists(session, "isAdmin") AND session.isAdmin>
  do admin stuff
</cfif>

ColdFusion 2016 Enhancement

The ColdFusion 2016 release added a new Application.cfc level setting this.searchImplicitScopes which defaults to true for backwards compatibility. If you set it to false it will only search the variables, local and arguments scopes when a scope is unspecified on a variable.

Scope Injection in Railo / Lucee

This particular example is not vulnerable in the version of Railo / Lucee I tested, apparently because it does not allow cascading on builtin scopes. You can still have a scope injection issue on variables that are not in a builtin scope, consider this:

<cfif IsUserInRole("admin") OR IsUserInRole("superuser")>
   <cfset isAdmin = true>
</cfif>
<cfif isAdmin>
  do admin stuff
</cfif>

There is also a setting in the Railo / Lucee administrator that allows you to turn off cascading (under scopes) by setting it to strict. You can also do this in your Application.cfc:

this.scopeCascading = "strict";

When the scopeCascading setting is set to strict it removes the possibility of a scope injection vulnerability, and may also improve performance.

How FuseGuard protects from Scope Injection

FuseGuard customers have been enjoying protection from scope injection for the past 3 years. It operates in a strict mode by default which prevents inputs like url.one.two, with strict mode off it only looks at valid scope names (like session, application, etc).

As of version 2.3 you can also set a prefix to ignore, for example fusebox apps commonly have url's like ?fusebox.action=foo so you can tell FuseGuard to allow that by adding:

filter.setIgnorePrefixList("fusebox");

You can also ignore a variable a-la-carte like this:

filter.ignoreVariable("url", "one.two");


security cfml coldfusion railo lucee session fuseguard

Scope Injection in CFML was first published on March 03, 2015.

If you like reading about security, cfml, coldfusion, railo, lucee, session, or fuseguard then you might also like:

FuseGuard Web App Firewall for ColdFusion

The FuseGuard Web Application Firewall for ColdFusion & CFML is a high performance, customizable engine that blocks various attacks against your ColdFusion applications.

CFBreak
The weekly newsletter for the CFML Community


Comments

Hi Pete.

I was skeptical that Adobe ColdFusion would behave in such a flawed manner. So I whipped up a little demonstration:
https://github.com/ecivis/miniapp

Sure enough, ACF 10 is vulnerable, exactly as you wrote above. I tried the miniapp in Railo 4.2.1.008 with strict scope cascading enabled, and it worked as expected.

Thanks for the post.
by Joseph Lamoree on 03/26/2015 at 11:29:41 PM UTC
I had no idea that either ACF or Lucee had settings for scope traversal. This is cool, not only for security, but also for performance!
by Ben Nadel on 07/19/2020 at 10:22:52 AM UTC