Scope Injection in CFML

March 03, 2015
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");


Related Entries

2 people found this page useful, what do you think?

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.

Post a Comment




  



Spell Checker by Foundeo

Recent Entries



foundeo


did you hack my cf?