Это мой персональный дневник. Пишу, по большей части, про историю, свою жизнь и немного про программирование.

CVE 2023-0567

В ПХП нашли достаточно серьёзный, на мой взгляд, баг — на некоторых повреждённых хешах функция password_verify возвращает true на любой пароль. Получается, хитрый хакер может оставить себе тайный ход — поменять в базе хеш на битый, и пользователь ничего не заметит — пароль-то по-прежнему подходит.

Вот как это выглядит:

var_dump(password_verify("foo", '$2y$04$00000000$')); // true
var_dump(password_verify("bar", '$2y$04$00000000$')); // true

Удивляет, что один из разработчиков попытался защитить текущее поведение интерпретатора:

The documentation for password_verify() clearly states that the $hash has to be valid:

> hash
> A hash created by password_hash().

I fail to see how this is a bug if you feed it garbage; also the documentation to crypt states:

> Using characters outside of this range in the salt will cause crypt() to return a zero-length string. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithm and must be in range 04-31, values outside this range will cause crypt() to fail.

PHP clearly behaves as described.

Что бы ни было написано в документации, возвращать true на любой пароль из функции проверки правильности пароля — очень плохая идея, как мне кажется, это должно быть довольно очевидно.

При анализе оказалось, что баг занесён ещё в 2008-м году (!), причём исследовавший эту историю разработчик хоть и осторожен в выражениях, всё же похоже считает, что уязвимость появилась неслучайно:

PHP’s implementation of crypt_blowfish differs from the upstream Openwall version by adding a «PHP Hack», which allows one to cut short the BCrypt salt by including a $ character within the characters that represent the salt.

Hashes that are affected by the «PHP Hack» may erroneously validate any password as valid when used with password_verify and when comparing the return value of crypt() against the input.

The PHP Hack exists since the first version of PHP’s own crypt_blowfish implementation that was added in 1e820ec.

No clear reason is given for the PHP Hack’s existence. This commit removes it, because BCrypt hashes containing a $ character in their salt are not valid BCrypt hashes.