Scope Injection in CFML
By Pete Freitag
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:
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:
- Fixinator and Foundeo Security Bundle
- OpenSSL and ColdFusion / Lucee / Tomcat
- Spring4Shell and ColdFusion
- Log4j CVE-2021-44228 Log4Shell Vulnerability on ColdFusion / Lucee
The FuseGuard Web Application Firewall for ColdFusion & CFML is a high performance, customizable engine that blocks various attacks against your ColdFusion applications.