Scope Injection in CFML
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:
What happens when the above code example is run:
- CF checks to see if
session.isAdminis defined in the
- The variable
session.isAdminwas not defined in the
sessionscope, so it starts searching other scopes, such as the
- CF finds
url.session.isAdmindefined and uses that value to evaluate the if statement as
- 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
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
this.scopeCascading = "strict";
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:
You can also ignore a variable a-la-carte like this:
- CFSummit 2016 Slides - October 17, 2016
- Disable Flash Remoting on ColdFusion Servers - September 3, 2015
- J2EE Sessions in CF10 Uses Secure Cookies - April 5, 2013
- Session Loss and Session Fixation in ColdFusion - March 1, 2013
- Adobe eSeminar on FuseGuard - October 26, 2011
I was skeptical that Adobe ColdFusion would behave in such a flawed manner. So I whipped up a little demonstration:
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.
- ColdFusion returning empty response with server-error: true
- Careful applying CF11u16, CF2016u8, CF2018u2
- Sessions don't work in Chrome but do in IE
- csrfVerifyToken does not invalidate the token
- The cf_sql_ is optional in cfqueryparam
- Cookie Expires / Max-Age 1969-12-31T23:59:59.000Z
- Burst Throttling on AWS API Gateway Explained
- How to Resolve Java HTTPS Exceptions