0

Here is the code which potentially can allow a timing attack

$user = getUserFromDatabase($input_username);

if ($user === false) { // potential timing attack
    // user not exist
    http_response_code(401);
    echo json_encode(["message" => "invalid authentication"]);
    exit;
}

if ( ! password_verify($input_password, $user["password_hash"])) { // potential timing attack
    
    http_response_code(401);
    echo json_encode(["message" => "invalid authentication"]);
    exit;
}

ref. https://www.netguru.com/blog/authentication-with-login-and-password

I changed the code by checking the hash before checking if the user exists as suggested by above article.
I assigned an empty string as default hash in case the user doesn't exist.
The code works as expected but below post said empty hash is not a good idea.
Is using password_verify($password, "") to block access to an account secure?

$user = getUserFromDatabase($input_username);
$password_hash = $user["password_hash"] ?? "";

if ( ! password_verify($input_password, $password_hash) || $user === false) {

    http_response_code(401);
    echo json_encode(["message" => "invalid authentication"]);
    exit;
}

Any suggestion how to fix this?

guntbert
  • 1,825
  • 2
  • 18
  • 21
JoJo
  • 11
  • 3
    The [documentation of password_verify](https://www.php.net/manual/en/function.password-verify.php) clearly states that the function is safe against timing attacks if a password hash is given. So just create a password hash using a long random string for comparison. – Steffen Ullrich Jan 04 '22 at 18:03
  • I mean timing attack against this 2 line: #1 if ($user === false) {...} #2 if ( ! password_verify($input_password, $user["password_hash"])) {...} attacker can check if user exist or not, since if user does exist it will take significantly more time since it need to perform password_verify on the next step – JoJo Jan 04 '22 at 18:24
  • 2
    As Steffen has said, just create a password hash using a long random string for comparison. The `password_hash()` and `password_verify()` take the same amount of time to run. You've already identified where you need to put it, too. (Also, don't spend too much time on this. You'll improve your auth system more by implementing rate limits and 2fa, anyways.) – Ghedipunk Jan 04 '22 at 18:33
  • @Ghedipunk got it, thank you – JoJo Jan 04 '22 at 18:39

0 Answers0