Correctly applied access control rules are key to keeping your data secure. Almost all applications need to protect sensitive data and operations, so putting careful thought into how to restrict access is important when designing a system.
Depending on the sensitivity of the data that your application handles, the repercussions of broken access control can be very severe. Data leaks can cause reputational damage, cost your business financial penalties, make your customers vulnerable to fraud, and even endanger national security (if you work for a government agency).
There is no one-size-fits-all solution to correctly implement access control. Generally speaking, your access control strategy should cover three aspects:
- Authentication - correctly identifying a user when they return to the application.
- Authorization - deciding what actions a user should and should not be able to perform once they have been authenticated.
- Permission Checking - evaluating authorization at the point-in-time when a user attempts to perform an action.
Authorization is often implemented by granting each user a specific role. (Administrative users are frequently differentiated from regular users, for instance.) More granular permissioning schemes need to be implemented if individual documents or data items need to have separate privileges.
Authorization schemes often implement an idea of ownership. Certain resources can belong to a user or group of users, and may not be accessible to others without their permission.
Finally, access control schemes are often declared as policies that white-list or black-list specific entities and groups against certain actions.
Given this complexity, designing correct access control takes time and careful thought. There are a few guidelines you need to follow:
Decide what the biggest risks are to your organization, and focus on mitigating those risks.
Design and document your access control scheme upfront. Access control needs to be implemented correctly throughout your system. Without an agreed upon set of rules, it is hard to define what a “correct” implementation looks like.
Attempt to centralize access control decisions in your codebase. This doesn’t necessarily mean having all access decisions flow through one code-path, but you should have a standard method of evaluating access control decisions. This might consist of function decorators, web access path checking, a stored procedure layer in your database, inline assertions in the code, or calls out to a dedicated permissioning component or in-house API.
Test access control critically. Make sure your testing procedures genuinely attempt to find holes in your access control scheme. Treat it like an attacker would, and you will be better prepared when your first real attack occurs. If you have the time and budget, consider employing an external team to perform penetration testing.
Below are some useful libraries and tools that can be used to implement access control in various languages.
Most web-frameworks in Python (Django, Flask, Tornado etc.) route web requests to individual classes or functions. When evaluating whether a user should have access to a given resource, decorators provide a very useful syntax. They can be used to check permissions before a function is called, and can be added to the code in a unobtrusive, declarative manner.
The devise gem is a very comprehensive authentication solution that allows you to pick-and-choose the features you want. It offers helper methods to perform access control decisions in controllers, in routing logic, or within template files, with the minimum of fuss.
Java Authentication and Authorization Service (JAAS) is the industry standard for access control in Java. Permissions can be described dynamically or declaratively, and evaluated against URL paths or in code.
JAAS is comprehensive, though relatively heavyweight. You may want to also evaluate the Apache Shiro project, and Spring Security.
ASP.NET comes with a comprehensive authorization and authentication framework, that can be used to make access control decisions globally, on specific controllers, on particular functions within a controller, or at ad-hoc locations within the code.
MustBe and ACL are mature libraries that focus on different aspects of access control: web server routing and the evaluation of access control rules, respectively.
Content Management Systems
If your site deals heavily in documents, like in our example exercise, consider using a content management system. Complex rules – like embargoing a document until a pre-agreed point in time – can often be implemented very easily.
If you need to share role- and group-based authorization across multiple applications, you may want to look into investing in a Lightweight Directory Access Protocol (LDAP) solution. LDAP servers – the most well-known of which is Microsoft’s Active Directory – store user and group information in a tree structure, using a flexible schema, and allow searches to be run in a dedicated query language (also called LDAP, confusingly.)
In addition to Microsoft, Oracle and IBM all offer mature LDAP implementations. LDAP is designed to make access control and identity management decisions very quickly, and at scale, but can require a large upfront investment.
Missing Function Level Access Control Vulnerabilities in Maian Support Helpdesk Allow Complete Take Over of the System
AWS Identity and Access Management – an example of a very granular, policy-based access control system, that covers all of the Amazon Web Service offerings.