OWASP Top 10 2021 - New Leader
OWASP stands for Open Web Application Security Project. The OWASP Top 10 is a standard awareness document for developers and web application security. It represents a broad consensus about the most critical security risks to web applications.
OWASP Top 10 helps minimize web application security risks by changing the culture of software development to create more secure code.
Top 10 has not changed for many years. But we have a lot of changes this year. Some of them are very interesting and important.Here is how it looks now (image taken from https://owasp.org/Top10):

We can see that according to the list, Injection category is not a leader and Broken Access Control is the most serious web application security risk this year.
The fall of Injection category from 1st to 3rd place may indicate that companies are beginning to adopt static security code analyzers, automated scanners, third-party “black box” security testing and “bug bounty” programs. Mentioned security practices handle Injection vulnerabilities pretty well. And that is a really good thing, because it looks like companies are becoming more and more aware of cybersecurity. However, it is still high on the list, it have just become less acute. But what are possible reasons could we have for elevating the current leader? From my perspective, this is mainly because developers simply don’t design with security in mind, skip threat modeling in development, and don’t think about future scalability. But most importantly, if Broken Access Control is the leader, then web applications are statistically more likely to have problems in this category. (According to OWASP 94% of applications were tested for some form of broken access control). In addition, the consequences of an authentication breach can be extremely high.
So, let’s take a closer look at this category and try to understand exactly what it means and how to protect ourselves.
The name of the category is already self-descriptive enough. However here is detailed description from OWASP page:
Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification, or destruction of all data or performing a business function outside the user’s limits. (https://owasp.org/Top10/A01_2021-Broken_Access_Control)
And here are some common examples of vulnerabilities from the same page:
- Violation of the principle of least privilege and/or deny by default
- Bypassing access control by modifying requests in different ways
- Insecure direct object references
- API with missing access controls for POST, PUT and DELETE.
- Elevation of privilege
- Metadata manipulation (JWT etc.)
- CORS misconfiguration
- Force browsing
Below are some best practices for Access Control system design.
Deny by default
Deny by default meaning the prohibition of any action that was not specifically mentioned. This principle does not only work in software development. It also applies to things like firewalls and OS configurations. An example for software development would be a whitelist. Another example is Strong Parameters in Ruby on Rails framework. Also, when creating a new feature for your app, it’s good practice to disable it for users until they explicitly enable it.
Least privilege
Least privilege is the concept and practice of restricting access rights for users, accounts, and computing processes to only those resources absolutely required to perform routine, legitimate activities. Privilege itself refers to the authorization to bypass certain security restraints. (https://www.beyondtrust.com/blog/entry/what-is-least-privilege)
This concept can be applied not only to people, but also to software components. Here are examples of application of that principle in web development:
- Don’t use users with administrator rights for routine activities.
- Run your application from regular user account in OS.
- Create DB user with least rights required for you application.
Design Access Control up-front
Finished Access Control system is difficult and time-consuming to refactor. Usually at the beginning of a project developers prefer simple solutions, but when the product grows, they find themselves in a very difficult situation. Trying to make simple decisions in complex cases leads to increased risks. Next practice shows more concrete example of bad design decision.
Prefer ABAC/PBAC over RBAC
Role Based Access Control (RBAC) is a model for controlling access to resources where permitted actions on resources are identified with roles rather than with individual subject identities. Role based programming of this nature is fragile. It is easy to create incorrect or missing role checks in code. It doesn’t allow multi-tenancy and data-specific or horizontal access control rules. In addition, RBAC typically has multiple access control checks. This can make it difficult to audit or verify the overall access control policy.
Attribute Based Access Control (ABAC) will grant or deny user requests based on arbitrary attributes of the user and arbitrary attributes of the object, and environment conditions that may be globally recognized and more relevant to the policies at hand.Attribute or feature-based access control checks of this nature are the starting point to building well-designed and feature-rich access control systems. This type of programming also allows for greater access control customization capability over time.
Policy Based Access Control (PBAC) is an approach in which roles and attributes are combined with logic to create flexible, dynamic control policies. Like ABAC, it uses a number of attributes to determine access rights.
Policy Based Access Control is generally considered the most flexible Authorization solution because it basically adds more features to ABAC.
Review the authorization logic of chosen tools
Do not design the capabilities of any library or framework guide your authorization requirements. Authorization logic provided by the component may be insufficient. The main frameworks and libraries were created to be flexible and suitable for as many cases as possible. So custom authorization logic may be necessary to meet an app’s security requirements. For the same reasons do not rely on default configurations.
Third-party components may work not as expected in your environment. Also Documentation can be outdated or not accurate. So make sure to check/test that your framework/library/tool works as configured and as intended.
Even well known mainstream libraries can have vulnerabilities. It is worth including dependency checking subsystems in the development lifecycle and performing regular dependency updates.
Also, knowing how your tools work will help you avoid misconfiguration or misuse.
Access control checks should be performed for all requests and in the right location
Force all requests go through access control. Access control is only effective in trusted server-side code, at the gateway, or server-less API, where the attacker cannot modify the access control check or metadata. Implement access control mechanisms once and re-use them throughout the application. Minimize Cross-Origin Resource Sharing (CORS) usage and properly configure it if using.
Avoid Insecure direct object references
Implement strict access control checks and ensure lookup IDs are not accessible even when guessed. Also lookup IDs should me generated in unpredictable manner so they can’t be easily guessed. Furthermore, the authorization system should not allow you to guess whether a search ID exists or not when the authorization control is checked.
Authorization Checks on Static Resources
Make sure that static resources are included in the access control policy. When possible and appropriate, protect static resources with the same access control logic, methods, and tools that you use in your main application. Be aware of the type of data exposed and whether the storage of static resources is properly configured.
Implement Appropriate Logging
Logging is very important for application security. Logs help in detecting malicious activity, auditing security, investigating incidents, troubleshooting access control and other security issues. Here is a couple of recommendations to follow for better logs:
- Use format easy to parse and analyze
- Carefully determine the amount of information to log. Avoid including sensitive info in logs
- Ensure timezones are synchronized across systems
- Consider incorporating application logs into a centralized log server.
Disable web server directory listing
Disable web server directory listing and ensure file metadata (e.g., .git) and backup files are not present within web roots.
Implement session invalidation
Stateful session identifiers should be invalidated on the server after logout. Stateless JWT tokens should rather be short-lived so that the window of opportunity for an attacker is minimized. For longer lived JWTs it is highly recommended to follow the OAuth standards to revoke access.
Test Cases for Authorization Logic
When writing tests for a new feature, add scenarios for checking authorization logic. Here is good authorization testing guide from OWASP: https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing/README
Just look at how much interesting stuff there is here. No wonder Broken Access Control tops the list. Indeed, it is very complex category. So it’s easy to make a mistake and introduce a vulnerability. But this is only one item from the list. I highly recommend checking other items as well on OWASP Top 10 official page: https://owasp.org/Top10.