Broken Authorization in PHP
Prevention
PHP does not provide any authentication and authorization mechanism that can be implemented using sessions.
The login.php
script checks that the credentials submitted by the user are saved to ensure the user role persists as a session variable in $_SESSION
.
<?php
session_start();
if ( isset( $_POST['username'] ) && isset( $_POST['password'] ) ) {
// If returns a string with the role name or NULL if the credentials are wrong.
$role = password_verify( $_POST['username'], $_POST['password']);
if ( $role ) {
$_SESSION['name'] = $_POST['username'];
$_SESSION['role'] = $role;
}
}
?>
Other pages check that the user is logged in before accessing any privileged parts of the code.
<?php
session_start();
if ( $_SESSION['role'] == "admin" ) {
// Administrative functionalities
} elseif ( $_SESSION['role'] == "user" ) {
// User functionalities
} else {
// Redirect to loing page
header("Location: /login.php");
die();
}
?>
Many PHP frameworks have authentication and autorization mechanisms already built-in.
Symfony
Symfony provides several authentication providers to manage the login process. The endpoint can be protected by authorization controls using access_control
in security.yaml
to protect URL patterns (e.g. /admin/
).
# config/packages/security.yaml
security:
# ...
firewalls:
# ...
main:
# ...
access_control:
# require ROLE_ADMIN for /admin*
- { path: ^/admin, roles: ROLE_ADMIN }
For more flexibility, the authorization can be written inside the controllers calling denyAccessUnlessGranted
. If the access is not granted, AccessDeniedException
is thrown, and no more code is executed.
public function adminDashboard()
{
$this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'User is not authorized to use this admin functionality');
}
The authorization on controllers can be also enforced using annotations:
/**
* Global control for *every* controller method in this class.
*
* @Security("has_role('ROLE_ADMIN')")
*/
class AdminController extends AbstractController
{
/**
* Control for only this controller method.
*
* @Security("has_role('ROLE_ADMIN')")
*/
public function adminDashboard()
{
}
}
References
PHP - Sessions Basic Symfony - Security Symfony - @Security & @IsGranted