I have contested lately that RBAC (Role Based Access Control) just flat out doesn't work in today's world. There was once upon a time, when applications were much simpler that this concept fit very well in the application security world, but we no longer live in that world.
The problem with RBAC is that it is a big hammer. It is what I like to refer to as an all-or-nothing solution to a problem that deserves a much finer grained answer. To elaborate on this, let me first explain the concept of RBAC.
1. Applications have users.
2. Users need to be be able to perform actions.
3. Actions are associated with Roles that are allowed to perform said actions.
4. Users belong to one or more Roles.
This is a very *simple* solution to the problem of access control in an application, and in simple applications, it works quite well. RBAC is widely supported by vendors and comes built in to most web application containers. It also happens to be the access control mechanism used by most OS vendors (Replace Role with Group and Voila!). There are tons of implementations for J2EE applications such as Spring ACEGI, JAAS, etc.
When you want to check if a user can perform some action you simply use a quick check
if ( user.isInRole( Roles.ADMINISTRATOR ) ) {
doAdminStuff();
}
So what is the problem with this simple, widely supported, very popular means of access control? It's simple really, RBAC has no awareness of the context request for access.
To illustrate this point, consider the following situation.
You have just completed coding a wonderful project management application for Big Humungous Inc. that filled all the requirements, is unhackable, and even has a list of features far exceeding the clients requests. One day you recieve a call that your client is creating a special group of representatives that need to have administrative access to customer accounts that belong to Group A between 2pm and 3pm every Monday, Wednesday, and Friday.
Now you have a problem. A role is an all-or-nothing access mechanism. So you can't just add the users to the Administrator Role, so your only option is to go back into the code and add a new check in the code that says am I in this role, and do I meet all these other requisites to do the requested action. Then you need to implement that code in every place where you would normally ask is the user an administrator?
Now let me introduce to a different approach to Access Control. It goes by many names. Some call it Activity Based Access Control, I call it Context Based Access Control. The concept is simple.
Make your Access Control mechanism aware of context!
There are any number of ways to do this, but I will address that in a subsequent article as this is more about the interface it provides. Adding context can allow you to specify any number of dynamic situation that are taken into account when determining whether a user has access to perform an action. Consider the following:
public interface AccessContext {
boolean isAllowed( User u );
}
public interface AccessRole {
// Some methods
}
public interface User {
// ... Other user'ish stuff
}
public interface AccessController {
boolean canUserPerformAction( User u, Context c, Action a );
}
public interface Action {
void performAction();
}
This is a simple outline of how a Context Based Access Control API might look. Now in your code you might have something that looks like this:
User user = RequestHelper.getUser(); Context requestContext = RequestHelper.getContext(); if ( accessController.canUserPerformAction( user, requestContext, new Action( "Delete User" ) );
Of course this is a very simple and open ended example, but it gets the point across rather well and illustrates the ability to solve problems in a manner that allows the AC layer to be as fine-grained or big hammer as it needs to be in any given situation.
To summarize:
1. Role Based Security doesn't address the problems of today's applications.
2. Context or Activity Based Security has the power to address those problems, but there is no force driving it forward.
I have proposed to the ESAPI team that we are in the perfect position to address this problem at the API level. Designing a clean interface that addresses the simple as well as complex control situations is really the difficult part in this concept.
An interesting read if you have a second - it looks like Microsoft had the same idea 2 years ago, too bad they patented it and did absolutely nothing with it.
http://www.freepatentsonline.com/y2007/0143823.html
I would love to hear what the 'verse has to say about this so let's get some conversation going around this topic and see what we can come up with!
As a followup - just found this on the interwebz. XACML from Oracle aims to be a Markup Language to define access control policies and uses some of the same concepts that I have highlighted in my post. The idea of context representing a more complex business specific decision making object that builds on the existing security mechanism.
ReplyDeletePretty cool stuff...
http://www.oasis-open.org/committees/document.php?document_id=33416
Interesting post. I just finished a project which does something similar. We used code access security with our own custom CodeAccessSecurityAttribute and IPermission implementations as a hook and then verify permissions based on the user, the access requested (ex. Read/Write) and a key - much like your action.
ReplyDeleteIf the user attempts something they have no permission for an exception is thrown. Then the onus is on the developer to wrap calls with a "soft" request:
if(CanUser(user, AccessLevel.Write, "ACTION_KEY")) {
// do it
}
We even created a utility library which uses expression trees to wrap the request and the action into a single call:
TryThis(() => SomeMethod(), user, AccessLevel.Write, "SOME_KEY");
We use it for actions as well as securing data at the field level, in which case we omit the key and use the fully-qualified name of the property as the key. We obtain the property's FQN by reading the expression tree.
Administrators can then grant/revoke user access to specific actions on an as needed basis. The only thing missing from what you've suggested is the ability to provide an expiration window for elevated access to a specific feature.
The whole thing is working really well. We can be as flexible as needed w/o affecting the actual business logic of the application. If we needed to add the features you mention then we just update the security layer and leave the application alone. The only time it affects the application logic is if we need to secure something that wasn't secured before.
@Mark - That sounds like a good start. The unfortunate thing is that you had to *brew your own* solution to this problem. Authorization can be a tricky thing to get right sometimes, and having to spend time figuring out every way that someone could exploit a bug in your authorization scheme can be a serious issue on applications with strict timelines that need to be adhered to. If you are spending all of your time tweaking and perfecting your own home-brewed authorization and access controls, well than you are not spending that time on getting the features and bugs addressed in the application itself. I would love to see the ESAPI team in a position where we could design the API and push it out to the experts to implement in their respective frameworks. This way, developers can spend their time focusing on the application they are working on instead of trying to build a framework that may or may not solve all of their problems, and may or may not be secure in itself.
ReplyDeleteIt's about time!
ReplyDeleteI've been saying pretty much the same thing - down to the same term Context Based Access Control - for a few years, and I always get responses ranging from:
- blank stares
- incredulous, non-understanding looks
- "weeelll.... our IDM/AD/frameworks already give us access control, we dont have to worry about it"
- "Naaah, we'll just code up a simple add-on application that will give us everything we need - or, maybe just what is simple enough to do quickly"
- "So, Role based access control, huh?"
RBAC is a compromise. Albeit, a sometimes necessary one, and a sometimes acceptable one - but not always both together.
Acceptable - for simple applications.
Necessary - there are simply no frameworks or supporting infrastructure that provide this now, in a scalable way. This WILL change, and soon (I'm also working on this right now ;-) ).
Btw, scalable is also a big part of the picture, so while ESAPI might be a good idea (as far as standardizing the interfaces), it wont help the big picture, since creating it in a generic-enough manner is no simple task.
Another side note, XACML is not really an Oracle creation... but you're right, it is in the right general direction, taking context into account... I dont think the specifics are the best they can be, but anyway...
ReplyDeleteThe difference between XACML and anything ESAPI would include, is XACML as a markup language cannot be used directly. Perhaps ESAPI could be the front-end API that produces and consumes XACML? (With XACML being one specific implementation for ESAPI, obviously generic frameworks are the way to go...)
That is precisely where ESAPI has the power to make these kinds of changes real is in the interface. Ultimately it is up to the users themselves and the people writing the auth(entication)/(orization) libraries to provide their implementations with support for CBAC - Spring, Struts and JAAS (which are probably the big 3) could write a provider class for the ESAPI using their libraries and voila! We would have solid implementations that are already being used by a good share of the Java Webapps on the 'net today. Unfortunately - I think this is a bit of a pipe dream until we can really start getting a lot of marketing momentum behind the ESAPI and getting it's adoption rate up, but that is not to say that it isn't something that could be done. I know that there are a lot of people getting very interested in ESAPI 2.0 so with it's pending release (very very soon) I think we could absolutely start pushing the envelope soon enough to start making more impactful changes in the world of appsec.
ReplyDeleteChris, while I definitely commend the idea, I think you're underestimating the complexity of what such a generic interface would entail, assuming it's done right.
ReplyDeleteMoreover, even if hypothetically you manage to get the frameworks guys to supply implementation providers (and here you're just looking at the Java fws, of course... bigger picture is needed :) ), that is STILL only half the way there, if that.
The reason I say this? Simply performing the authZ checks amounts to little - even if hypothetically this is done as granular as possible - without a solid management system behind it. ESAPI obviously is not going to provide that part of it, and neither are the Java frameworks.
Therefore, you really need to be looking towards IdM/IAM/EAM vendors, to provide the pluggability you would need to put the Enterprise back into *E*SAPI.
As one of them myself, and with a personal interest in all OWASP works as a member, I would be glad to be the first - however, as a small startup (still in stealth) I'm afraid I dont carry much weight :(.
Still, if you're interested maybe I can provide some benefit, when it comes around to that...
Avi -
ReplyDeleteThat is a very good point. There is an addage that goes something like "Your security is only as good as the implementation" (or maybe I just made that up) and I think your point here is very valid. Really, the ESAPI team can only provide the framework for a good security system and some examples of how that security should work in your implementation. But first and foremost, the ES*API* is just that, an API, and as such, we really don't have much foresight into how the real-world controls will be implemented. There needs to be strong vendor participation in the development of the API and that is an area that I feel we have been lacking. Right now, we ship the ESAPI with a very basic FileBasedAuthenticator which would *hopefully* never be used in a real world app, unless the needs of that app are particularly simple. Most web applications already have some sort of identity and access management platform in place (whether it be homebrewed or otherwise) and regardless of the strength of that platform, they are responsible to maintaining the management interface for identity and access control in their application. If we were able to get buy in from some of the bigger frameworks out there like JAAS and Spring, and also be able to tie this into management solutions for identity and access control, it would make it very easy for people to implement and could provide a reference implementation of what an authenticator should look like that is usable in real-world applications.
Well, I implemented such a mechanism back in 1999 for a corporate intranet.
ReplyDeleteThe solution worked fine for *static* contexts. However, contexts are often dynamic, and that is more difficult to implement (e.g. a department manager can manage content of his own department, but only view content from another one). We finally managed to implement this, but it required a lot of custom implementation on top of acegi.`
The example user.isUserInRole() is already bad, and not really RBAC. Ideally, it should be user.hasPermission(). By using user.isUserInRole(), you are hard-coding the permissions that a certain role has right into the code. And that is really a bad thing. We also had to code around that. We ended up with a nice user management, where roles could be managed through the web interface (including assigning permissions to roles in specific context). To check for permissions, we only had to call user.hasPermission(context, permission).
The implementation specifics were not the main point of what I was trying to get acrossed with this post. The main point was that RBAC is well beyond it's years of usefulness and a decent replacement is yet to be released to the general population. I think Context Based Access Control is the answer to this problem. I think you illustrate this as your opinion as well in your comment. You are absolutely right that a CBAC system needs to be accepting of both static and dynamic contexts as well, and yes, this is a very tricky thing to do. I believe that in a way I addressed this in my followup post More on Context Based Access Control.
ReplyDeleteZed Shaw has a great speak on this.
ReplyDeleteBuilt a DSL for an app as a result of this understanding.
http://blog.cusec.net/2009/01/05/zed-shaw-the-acl-is-dead-cusec-2008/
All the best Chris!
MarkT
Access control is a system which enables an authority to control access to areas and resources in a given physical facility or computer-based information system. An access control system, within the field of physical security, is generally seen as the second layer in the security of a physical structure.
ReplyDeleteI believe that one other layer needs to be added to this. WHEN in the web/application stack to check. From a recent Spring 3.0 tutorial, it seems that object access (dbase, et al), and 'point of system departure', i.e. an API or web interface are required. Generically, this is: At the 'Safe/Repository', and at the structure exits/windows/doors. ANYTHING Can happen in between the safe in the floor and the doors, and it will be irrelevant, if the Safe can't be opened and no valid information can be taken outside by unauthenticated persons or authenticated persons under unauthorized circumstances.
ReplyDelete