Security Tip: Fail securely

Failing securely is one of those things where, when you think about it, you say "duh". But I, for one, did not realize until it was pointed out to me that I was not always doing it. Let's look at an example of failing insecurely.

In this example, we have an application that has three types of user roles. The three roles are "admin", "superuser" and "user". Let's say we have a piece of content that we don't want regular users to access, so we do this:


<cfif user.inRole("user")>
<!--- Deny Access --->
<cfelse>
<!--- Allow Access --->
</cfif>

This is an example of failing insecurely. It may be subtle, so I will explain. Here we are checking to see if the user is in the "user" role. If they are, we deny them access. That seems pretty straight forward. Until we realize that in ANY OTHER CASE we are granting access. So this condition fails in a way that grants the most privilege.

What happens if we have an anonymous user trying to access it? Will the inRole() method function the same for an anonymous user? What if we add another type of user but we still don't want to give them access to this content or other similarly protected content? Well, unless we remember to go through our code and change every piece of content that is protected this way, then we will have a gaping security hole.

This can be easily rewritten to fail securely.


<cfif user.inRole("admin") OR user.inRole("superuser')>
<!--- Allow Access --->
<cfelse>
<!--- Deny Access --->
</cfif>

Now, unless the user is explicitly in one of the allowed roles, they will be denied access. Additionally, if we do come across an anomaly where the code fails for some reason, the ELSE case will always deny them access.

Here is another example of failing insecurely:


<cfset authorized = true />

<cftry>
<cfset authorized = user.inRole("admin") />
<cfcatch>
<cflog text="Application Error, oops" />
</cfcatch>
</cftry>

This is very contrived example, imaging code like this that is considerably more complex. As you can see, if an attacker can force that try/catch block to throw an exception, then the "authorized" variable will remain set to true. Again, this is a weak example, but this could certainly happen in a more complicated block of logic that spans several methods and access checks.

Additional Resources

OWASP article on failing securely
Failing Securely - Department of Homeland Security - National Cyber Security Division

Comments
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1. Contact Blog Owner