Broken Function Level Authorization

Broken Function Level Authorization in Laravel [Dec 2017] [CVE-2017-14775]

[Fixed Dec 2017] Updated CVE-2017-14775

Overview

Broken Function Level Authorization (BFLA) vulnerabilities occur when an application uses token-based checks for access control but relies on non-constant-time comparisons, enabling timing-based information exposure. CVE-2017-14775 documents such a flaw in Laravel before 5.5.10, where the remember_me token verification performed by the DatabaseUserProvider did not use a constant-time comparison, creating a CWE-200 information exposure risk that could aid token guessing and unauthorized access. Impact and exploitation: An attacker who can observe requests involving the remember_me cookie could measure tiny timing differences when comparing tokens and gradually narrow the space of possible tokens, potentially impersonating a user without reauthenticating. This undermines the trust boundary between authenticated and unauthenticated requests and can be used to bypass login controls. Fix approach: Upgrade Laravel to 5.5.10 or later (or apply the patched DatabaseUserProvider) so that remember_token verification uses a constant-time comparison such as hash_equals. In PHP, avoid direct string equality and replace with hash_equals, after ensuring the PHP version supports it. Also rotate remember_token values after login or when tokens may have been compromised. Additional mitigations: use HTTPS for all sessions, mark cookies Secure and HttpOnly, set reasonable remember_me lifetimes, keep dependencies up to date, and add tests to verify that token comparisons are performed in constant time and that remember-me tokens are properly invalidated on rotation or logout.

Affected Versions

Laravel <= 5.5.9 (before 5.5.10)

Code Fix Example

Laravel API Security Remediation
<?php
// Demonstration of vulnerable token check and a constant-time fix
class User {
    public $remember_token;
    public function __construct($token) {
        $this->remember_token = $token;
    }
}
function verifyRememberTokenVulnerable($providedToken, $user) {
    // Vulnerable: non-constant-time comparison
    if ($providedToken !== $user->remember_token) {
        return false;
    }
    return true;
}
function verifyRememberTokenFixed($providedToken, $user) {
    // Fixed: constant-time comparison using hash_equals
    if (!is_string($providedToken) || !is_string($user->remember_token)) {
        return false;
    }
    return hash_equals($user->remember_token, $providedToken);
}
// Demo
$user = new User('abcd1234efgh5678');
$provided = 'abcd1234efgh5678';
var_dump(verifyRememberTokenVulnerable($provided, $user));
var_dump(verifyRememberTokenFixed($provided, $user));
?>

CVE References

Choose which optional cookies to allow. You can change this any time.