Recently, I have read many articles on security architecture, and many experts have also discussed authentication, authorization, and authentication, including the numerous data leakage incidents in the industry, many of which are caused by unauthorized access. Then, from the perspective of development, how can we develop authorization functions more securely besides doing well in daily API management?
Authorization can be defined as the process of 'verifying whether a specific entity is approved to perform the requested action or service' (NIST). It is different from authentication, which is the process of verifying the identity of an entity; authorization is the process of matching corresponding permissions after verification. A user who has passed authentication (possibly by providing a username and password) usually does not have access to all resources in the system or the ability to perform all actions. For example, an application may have both regular users and administrators; administrators can perform actions that regular users are not authorized to perform, even though they have passed authentication. In addition, access to resources does not always require authentication; unauthenticated users may be authorized to access certain public resources, such as images or login pages, etc.

Vulnerabilities in the authorization class are very harmful; attackers may be able to read, create, modify, or delete resources that should be protected (thus threatening their confidentiality, integrity, or availability); however, the actual impact of these actions is related to the importance and sensitivity of the resources destroyed. Therefore, the commercial cost of successfully exploiting authorization defects can vary from very low to extremely high. While conducting authorization vulnerability testing through routine security tests (penetration testing, vulnerability scanning, special inspections, code audits, etc.), in line with the philosophy of secure development, from the perspective of R&D, the following points can be considered:
Implement the principle of least privilege
As a security concept, the principle of least privilege is also one of the principles of security design. The principle of least privilege refers to the principle of assigning only the minimum permissions necessary for users to complete their work. Although this principle is most commonly applied to system management, it is also relevant to software developers (after all, the code is written for development). The principle of least privilege must be applied both horizontally and vertically. For example, by analogy with daily management, accountants and sales representatives may be at the same level in the organizational hierarchy, but both need to access different resources to perform their work. Accountants may not be granted access to the customer database, and sales representatives should not be able to access salary data. Similarly, the sales department manager may need higher-level permissions than their subordinates.
How do developers carry out minimum privilege design? Corresponding roles: architects, security designers, and the implementation of security development processes.
- In the design phase, ensure that trust boundaries are defined. List the types of users who will access the system, the exposed resources, and the possible operations that may be performed on these resources (such as read, write, update, etc.). For each combination of user type and resource, determine what actions the user (based on roles and/or other attributes) should be able to perform on the resource (if any). For ABAC systems, ensure that all categories of attributes are considered. For example, sales may need to access the customer database from the internal network during working hours, but not during off-hours, from the external network, etc.
- Create tests to verify that the permissions established during the design phase are correctly executed.
- After the application is deployed, regularly review the permissions in the system; that is, ensure that the permissions of users in the current environment do not exceed the permissions defined during the design phase.
- The principle of least privilege needs to be embedded in advance. Early planning and implementation in the early stages of the SDLC are the most cost-effective.
Default rejection access
Even if there are no explicit access control rules that match, when an entity requests access to a specific resource, the application cannot remain neutral. The application must make a decision, either implicitly or explicitly, to either reject or allow the requested access. Access control may contain errors, especially when access requirements are complex; logical errors are a vulnerability; therefore, one should not rely solely on clearly defined rules to match all possible requests. For security reasons, the application should be configured to default to rejecting access.
How do developers design default rejection access? Corresponding roles: architects, security designers, and the implementation of security development processes.
- During the initial development period and when the application publicly releases new features or resources, the 'default rejection' strategy should be adopted. It should be able to clearly demonstrate why specific permissions are granted to certain users or groups, rather than assuming that access permissions are implicitly granted.
- Even though some frameworks or libraries may adopt default rejection strategies themselves, explicit configuration should be prioritized over relying on the default settings of frameworks or libraries. The logic of third-party code and default settings may evolve with the complexity of the project over time, and developers may not fully understand or comprehend the impact of changes on specific projects.
Verify permissions on each request
Regardless of whether the request is initiated by a script, server-side, or any other source, each request's permissions should be verified correctly. The technology used for such checks should be globally configured, rather than needing to be applied separately to each method or class. From the perspective of offense and defense, the attacker only needs to find one method. Even if only one access control check is 'missed', the confidentiality and/or integrity of the resources may be threatened. It is not enough to correctly verify permissions on most requests.
Specific technologies that can help developers perform this consistent permission check include:
- Java/Jakarta EE filters, including the implementation in Spring Security
- Middleware in the Django framework
- .NET Core filters
- Middleware in the Laravel PHP framework
ForThe internal authorization logic of the selected tools and technologiesSelf-inspectionImplement custom logic when necessary
Developers can access a large number of libraries, platforms, and frameworks, which provide convenience while complex logic can easily be implemented through various libraries and frameworks. However, these frameworks and libraries should not be regarded as a shortcut to solving all development problems; developers are responsible for using these frameworks securely. For authorization vulnerabilities, two key points are developers' incorrect configuration/lack of configuration, and vulnerabilities in the components themselves.
Here, let's focus on open source component governance (supply chain security is becoming increasingly popular)
- Create, maintain, and follow the process for detecting and responding to vulnerabilities in components - open source component security management process
- Integrate tools such as Dependency Check into the SDLC and consider subscribing to data sources from suppliers, NVD, or other relevant sources.
- Implement deep defense. Do not rely on any single framework, library, technology, or control to perform appropriate access control.
Configuration issues (or complete lack of configuration)
These components are usually intended to be relatively general-purpose tools, but they must be customized or supplemented with additional logic when used to meet the unique needs of specific applications or environments. Especially for security needs
Consideration factors for authorization configuration include:
- A thorough understanding and analysis of the technology for building authorization logic, whether through review or refactoring, can help developers gain a deeper understanding of authorization, and in order to meet specific needs, some authorization logic may need to be refactored or customized. Therefore, it is not to say that using others' frameworks and components is a one-time solution, but to design the most suitable authorization logic by standing on the shoulders of giants.
- Do not let the functions of any library, platform, or framework guide your authorization needs. On the contrary, you should first determine the authorization needs, and then analyze third-party components based on these needs. This means that we need to use tools better, rather than being dominated by tools
- Do not rely on default configurations.
- Do a good test! This is a bottom-line issue and is very important
Compared to RBAC, it is more inclined towards access control based on features and attributes
In software engineering, two basic forms of access control are widely used: Role-Based Access Control (RBAC) and Attribute-Based Access Control (ABAC). From my perspective, ABAC should generally be prioritized over RBAC.
RBAC:
RBAC is an access control model that grants or denies access permissions based on the roles assigned to users. Permissions are not directly assigned to entities; instead, permissions are associated with roles, and entities inherit the permissions assigned to any roles they are assigned. Typically, the relationship between roles and users can be many-to-many, and roles may be hierarchical.
ABAC:
Compared to RBAC, ABAC can be defined as an access control model where 'the request of a subject to perform an operation on an object is based on the attributes assigned to the subject, the attributes assigned to the object, environmental conditions, and a set of policies specified by these attributes and conditions to grant or deny access.' Defined in NIST SP 800-162, attributes are simply characteristics that can be represented as name-value pairs and assigned to subjects, objects, or environments. Work roles, time of day, project name, MAC address, and creation date are just a small part of the possible attributes that can be used to implement ABAC flexibility.
Why do I think ABAC is safer than RBAC?
- Support fine-grained, complex Boolean logic.
- Robustness in large projects or when there are many roles.
- Support multi-tenancy and cross-organizational requests.
- Management convenience.
Ensure that the lookup ID does not have accessibility even if it is guessed or cannot be tampered withThe scenarios paired with this are common resource convenience and unauthorized access vulnerabilities. Many vulnerabilities have been discovered from the attacker's perspective, but I find it difficult to describe. Scenarios include guessing an ID value and obtaining the person's information, but the ID can be traversed, and nothing is authenticated with the ID as an index, leading to vulnerabilities. Here, I directly provide the answer to the developers:
Ensure the security of the lookup ID
- Minimize the exposure of identifiers to users. For example, it should be possible to retrieve certain objects, such as account details, based solely on the identity and attributes of the currently authenticated user (for example, through JWT implemented securely or information contained in the server-side session).
- Implement user/session-specific indirect references using tools such as OWASP ESAPI
- Perform access control checks for specific objects or functions on each request. Just because a user can access a type of object does not mean they should be able to access every object of that type.
Perform authorization checks on static resources
When protecting static resources, the following considerations should be taken into account:
- Ensure that static resources are included in the access control strategy. The type of protection required for static resources necessarily depends heavily on the context. For some static resources, complete public access may be perfectly acceptable, while other resources can only be accessed when there is a strict set of user and environmental attributes. Therefore, it is crucial to understand the type of data exposed in the specific resources being considered. Consider establishing a formal data classification scheme and incorporating it into the application's access control logic.
- Ensure that any cloud-based services used to store static resources use the configuration options and tools provided by the vendor for security protection. Refer to the cloud provider's documentation (please refer to AWS, Google Cloud, and Azure guidelines) for specific implementation details.
- Use the same access control logic and mechanisms that protect other resources and functions of the application to protect static resources as much as possible.
Ensure that authorization checks are performed at the correct location
Developers should never rely on client-side access control checks. Client logic is usually easy to bypass. Access control checks must be executed on the server side and can be implemented through gateways or backend functions
Securely exit when authorization check failures occur
Authorization check failures are a normal phenomenon in secure applications; therefore, developers must plan for such failures and handle them securely. Specific recommendations include:
- Ensure all exceptions and failed access control checks are handled
- Centralize the logic for handling failed access control checks.
- Verify the handling of exceptions and authorization failures. Prevent the bypassing of change return values (low-end vulnerabilities)
Implement appropriate log recording
In my view, log recording is a safety net after going online; the recommendations for log recording include:
- Standardize the log recording format and record essential information
- Determine carefully the amount of information to be recorded. This should be determined based on the specific application environment and requirements. Both excessive and insufficient recording may be considered as security weaknesses. Insufficient recording may lead to malicious activities going undetected, greatly reducing the effectiveness of post-incident analysis. Excessive recording may not only consume resources excessively and lead to too many false positives but may also result in sensitive data being unnecessarily recorded.
- Ensure synchronization of clocks and time zones between systems. Accuracy is crucial for the sequence of attacks during and after an incident response.
- Consider incorporating application logs into a centralized log server or SIEM.
Create unit and integration test cases for authorization logic
Unit and integration tests are crucial for verifying whether the application executes as expected and consistently across changes. Defects in access control logic may be subtle, especially when the requirements are complex; however, even minor logic or configuration errors in access control may lead to serious consequences. While they cannot replace specialized security testing, automated unit and integration tests for access control logic can help reduce the number of security vulnerabilities that enter production.
Unit and integration tests should incorporate all the security requirements (points) mentioned earlier. For example, is access denied by default? Can the application safely terminate even if the access control check fails under abnormal conditions? Is the ABAC policy being executed correctly, etc.?

评论已关闭