Mistakes Frequently Encountered in Access Control Implementation

Effective access control is essential for securing your application, but implementing robust access control can sometimes be challenging and problematic. This is precisely why Broken Access Control is listed as the number one issue in the OWASP TOP 10. Below, we’ll highlight some common access control errors identified through code reviews and penetration testing experience.

Common Errors in Access Control Implementation

OAuth2 implementation mistakes 

OAuth2 has become a fundamental component in numerous applications as part of their authentication and authorization processes by providing secure designated access capabilities to these applications.  Despite OAuth2 emerging as the dominant industry-standard authorization framework following its replacement of OAuth1 in 2012, it has been noted that the complexity of OAuth2 and misunderstandings surrounding its implementation have led to it becoming a significant factor contributing to broken access control. 

In a previous article, we listed the common mistakes when implementing the OAuth2 in your organization. 

  •  Missing validation in redirect_uri leads to access token takeover
  •  Missing state parameter validation leads to a CSRF attack
  •  Client_secret mistakenly disclosed to the public
  •  Pre-account takeover
  •  OAuth2 access_token is leaked through the referrer header
  •  OAuth2 login bypass due to lack of access_token validation

In addition to the aforementioned errors mentioned in the blog, Overly permissive scope grant and Opting for an in-house, less mature OAuth2 service instead of a battle-tested OAuth2 solution are two other common mistakes reported against OAuth2 implementation.

  • Overly permissive scope grant 
  • Unmature self-developed OAuth2 server

In most cases, the overly permission scope grant issues comes when the application itself has a very granular control of access, but the scopes defined are not sufficient to match with the granular control. As a consequence, a broader scope could be granted to a user.  In some cases, an attacker might have the opportunity to enhance an access token (whether acquired through theft or by using a malicious client application) by exploiting inadequate validation performed by the OAuth service.

Certain organizations opt to create their own OAuth2 service rather than utilizing a well-established and secure OAuth2 server. In some instances, these internally developed OAuth2 services may lack rigorous testing, potentially harboring security vulnerabilities that could result in access-related problems.

Role-Based Access Control alone may not suffice for a complex system

Role-based access control relies on the users’ role to grant the corresponding permissions to the users. It has been widely used as it is simple to implement and less prone to errors. Below is a piece of sample codes with simple role-based access controls.

However, it has been demonstrated that role-based access control falls short of meeting the needs of complex systems. In the above given example, the author_user can edit any post because it only checks whether the user has the :edit_post permission without validating whether the user is the author of that specific post. The absence of proper validation to check whether a user really owns a specific resource serves as a fundamental reason for numerous access-related problems, including instances of Indirect Object Reference (IDOR) issues. 

For a complicated system with a very granular access control, a more advanced Attribute-based access control could be implemented to ensure the object/resource could be consumed by the users with the right permission. Attribute-based access control leverages multiple dimensions of the data’s and data consumer’s unique attributes to determine whether to grant or deny data access.  

In a well-established application,  it has been approved that using both RBAC and ABCA could be a highly efficient way to perform access control. An illustrative example involves using RBAC as middleware to initially validate whether a role is authorized to access a specific endpoint, followed by the application of ABAC for a final validation once RBAC authorization is confirmed.

Authorization Token or Passcode is improperly handled

Passcodes, stateful sessions, stateless JWT tokens, and Authorization Tokens are very sensitive and play critical roles when implementing a robust access control.  But sometimes, these could be mishandled when implementing access controls. 

Following typical mishandling instances often surface when performing source code reviewing during our development lifecycle.

  • JWT Tokens have a very long expiration time
  • A one-time used JWT Token does not expire once consumed
  • Lack of revocation method when a JWT Token is used
  • Sessions are valid for too long a time, and the session could be reused due to session-fixation issues.
  • Authorizations and JWT tokens are leaked to the log file 
  • Token validation is not robust enough
  • Hard sensitive access token in the source codes

Mishandling such sensitive data can undermine the effectiveness of your access control system and potentially result in authorization bypasses.

Lack of Authentication and Authorization between microservice communication

Microservice architecture brings many benefits, including scalability, flexibility, and ease of deployment and testing.  But it also brings up some security challenges as all the microservices are running independently and they need to communicate with each other, increasing the attaching surfaces from security perspectives. 

On the one hand, there is a shortage of research concerning security within the context of microservices architecture, and this scarcity becomes more pronounced when focusing on practical aspects of authentication and authorization. To compound the issue, certain developers mistakenly assume that implementing authentication between these microservices is unnecessary when they are deployed within an organization’s internal network or infrastructure and the requests from an internal resource should be trusted.

During source code reviews or design assessments, it’s often observed that the authentication and authorization practices between microservices are loosely defined. For instance, many microservices tend to inherently trust requests from any other microservice if both operate within the organization’s internal network. This can be likened to a “Wild West” scenario, where security controls may be lax or insufficiently enforced.

An example might help us to understand: suppose that we have three microservices run internally: a “payment” microservice to handle payment,  an “order” micro-service responsible for handling orders, and an  “inventory” microservice to handle the product inventory. The payment microservice should exclusively accept requests originating from the order service and must reject any requests from the inventory microservice. Additionally, within the “order” microservice, various roles may be assigned specific payment responsibilities. Without proper authentication and authorization mechanisms between these microservices, there is no assurance that the payment service will only handle requests from trusted services and authorized users.

Misunderstanding of Authentication/Authorization

Although it may come as a surprise, developers still encounter misunderstandings regarding Authentication and Authorization. As a consequence, it leads to broken access control issues when implementing access controls. 

Consider a basic web application featuring a Login Form based on Username and Password and various user roles. In this context, the authentication process occurs when a user attempts to log in using the Login Form. Essentially, authentication verifies your identity to confirm whether you are who you claim to be. Authorization, on the other hand, is the subsequent step, ensuring that you possess the necessary permissions to perform actions after being authenticated. Nevertheless, there are cases where developers may overlook the authorization component, mistakenly assuming that once a user logs in, they should automatically be granted all permissions.

Final Remarks

Access control continues to be a crucial element in the realm of cybersecurity and data protection within application security. The task of implementing robust authentication and authorization mechanisms to establish a robust access control system can be intricate and fraught with potential issues, which may result in unintended errors.

For an organization, establishing a strong access control system necessitates a comprehensive approach that includes meticulous design assessments, secure code implementation, rigorous security code reviews, and robust security testing, including function access control unit tests and penetration testing verification. 

Leave a Reply

Your email address will not be published. Required fields are marked *