Broken Object Property Level Authorization

Broken Object Property Level Authorization and Laravel [CVE-2017-14775]

[Updated March 2026] Updated CVE-2017-14775

Overview

CVE-2017-14775 describes a real-world vulnerability in Laravel versions prior to 5.5.10 where the remember_me token verification path in the DatabaseUserProvider did not use a constant-time comparison. This is categorized under CWE-200 (Information Exposure). In practice, an attacker could exploit timing differences in string comparison to infer valid remember_token values, potentially enabling session hijacking by replaying a remembered login. The issue affects Laravel 5.x up to 5.5.9, i.e., versions before the 5.5.10 patch release. The vulnerability stems from how the server compared the token from the cookie with the one stored in the database during Remember Me authentication, allowing information leakage through timing side channels. This is especially dangerous for applications that rely on Remember Me for persistent authentication across untrusted networks or shared devices.

Affected Versions

Laravel 5.0.0 through 5.5.9 (i.e., before 5.5.10)

Code Fix Example

Laravel API Security Remediation
<?php
// Vulnerable pattern (timing attack risk)
$tokenFromCookie = isset($_COOKIE['remember_token']) ? $_COOKIE['remember_token'] : '';
$user = findRememberedUserFromCookie($tokenFromCookie);

if ($user && $tokenFromCookie) {
    // Vulnerable: non-constant-time comparison
    if ($user->remember_token == $tokenFromCookie) {
        authenticate($user);
    }
}

// Fixed: constant-time comparison
if ($user && $tokenFromCookie) {
    if (function_exists('hash_equals')) {
        if (hash_equals($user->remember_token, $tokenFromCookie)) {
            authenticate($user);
        }
    } else {
        // Polyfill: simple constant-time comparison
        $diff = 0;
        $len = max(strlen($user->remember_token), strlen($tokenFromCookie));
        for ($i = 0; $i < $len; $i++) {
            $a = $i < strlen($user->remember_token) ? ord($user->remember_token[$i]) : 0;
            $b = $i < strlen($tokenFromCookie) ? ord($tokenFromCookie[$i]) : 0;
            $diff |= $a ^ $b;
        }
        if ($diff === 0 && strlen($user->remember_token) === strlen($tokenFromCookie)) {
            authenticate($user);
        }
    }
}
?>

CVE References

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