When granting users access to resources of an application, such an authorization should be based on strong decisions. For instance, a user may be authorized to access a resource only if they are authenticated, or if they have the correct role and privileges.
Access control is a critical aspect of web frameworks that ensures proper authorization and restricts access to sensitive resources or actions. To enable access control, web frameworks offer components that are responsible for evaluating user permissions and making access control decisions. They might examine the user’s credentials, such as roles or privileges, and compare them against predefined rules or policies to determine whether the user should be granted access to a specific resource or action.
Conventionally, these checks should never grant access to every request received. If an endpoint or component is meant to be public, then it should be ignored by access control components. Conversely, if an endpoint should deny some users from accessing it, then access control has to be configured correctly for this endpoint.
Granting unrestricted access to all users can lead to security vulnerabilities and potential misuse of critical functionalities. It is important to carefully assess access decisions based on factors such as user roles, resource sensitivity, and business requirements. Implementing a robust and granular access control mechanism is crucial for the security and integrity of the web application itself and its surrounding environment.
Not verifying user access strictly can introduce significant security risks. Some of the most prominent risks are listed below. Depending on the use case, it is very likely that other risks are introduced on top of the ones listed.
As the access of users is not checked strictly, it becomes very easy for an attacker to gain access to restricted areas or functionalities, potentially compromising the confidentiality, integrity, and availability of sensitive resources. They may exploit this access to perform malicious actions, such as modifying or deleting data, impersonating legitimate users, or gaining administrative privileges, ultimately compromising the security of the system.
Theft of sensitive data can result from incorrect access control if attackers manage to gain access to databases, file systems, or other storage mechanisms where sensitive data is stored. This can lead to the theft of personally identifiable information (PII), financial data, intellectual property, or other confidential information. The stolen data can be used for various malicious purposes, such as identity theft, financial fraud, or selling the data on the black market, causing significant harm to individuals and organizations affected by the breach.
The vote method of a VoterInterface implementation is not compliant
when it returns only an affirmative decision (ACCESS_GRANTED):
class NoncompliantVoter implements VoterInterface
{
public function vote(TokenInterface $token, $subject, array $attributes)
{
return self::ACCESS_GRANTED; // Noncompliant
}
}
The voteOnAttribute method of a Voter class is not compliant when
it returns only an affirmative decision (true):
class NoncompliantVoter extends Voter
{
protected function supports(string $attribute, $subject)
{
return true;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token)
{
return true; // Noncompliant
}
}
The vote method of a VoterInterface type should return a negative
decision (ACCESS_DENIED) or abstain from making a decision (ACCESS_ABSTAIN):
class CompliantVoter implements VoterInterface
{
public function vote(TokenInterface $token, $subject, array $attributes)
{
if (foo()) {
return self::ACCESS_GRANTED;
} else if (bar()) {
return self::ACCESS_ABSTAIN;
}
return self::ACCESS_DENIED;
}
}
The voteOnAttribute method of a Voter type should return a negative
decision (false):
class CompliantVoter extends Voter
{
protected function supports(string $attribute, $subject)
{
return true;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token)
{
if (foo()) {
return true;
}
return false;
}
}
The define, before, and after methods of a Gate are not compliant when they return only an affirmative decision (true
or Response::allow()):
class NoncompliantGuard
{
public function boot()
{
Gate::define('xxx', function ($user) {
return true; // Noncompliant
});
Gate::define('xxx', function ($user) {
return Response::allow(); // Noncompliant
});
}
}
The define, before, and after methods of a Gate should return a negative decision (false or
Response::deny()) or abstain from making a decision (null):
class CompliantGuard
{
public function boot()
{
Gate::define('xxx', function ($user) {
if (foo()) {
return true;
}
return false;
});
Gate::define('xxx', function ($user) {
if (foo()) {
return Response::allow();
}
return Response::deny();
});
}
}