Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що таке атака за часом (timing attack) і навіщо hash_equals?

Атака за часом - зловмисник вимірює, скільки часу сервер обробляє запит, і з різниці робить висновки про секрет.

Класичний приклад - порівняння рядків:

if ($providedToken === $storedToken) { ... }

Звичайне порівняння зупиняється на першому символі, що не збігся. Токен, у якого правильні перші 10 символів, перевіряється трохи довше, ніж токен з неправильним першим символом. Вимірюючи час тисяч запитів і усереднюючи шум, теоретично можна підбирати токен посимвольно: замість 62^32 варіантів - 62 × 32 спроби.

hash_equals($known, $user) порівнює рядки за постійний час - незалежно від того, де саме відрізняються символи:

if (hash_equals($storedSignature, $providedSignature)) { ... }

Порядок аргументів важливий: перший - відоме (секретне) значення, другий - від користувача.

Де потрібне порівняння в постійному часі:

  • підписи вебхуків і запитів (HMAC);
  • API-ключі й токени, якщо порівнюються як рядки;
  • коди підтвердження, CSRF-токени;
  • підписані URL.

Laravel використовує hash_equals для перевірки CSRF-токенів, підписаних маршрутів, токенів Sanctum.

Інші джерела витоку через час:

  • перевірка пароля лише для існуючих користувачів: для неіснуючого email сервер відповідає миттєво, для існуючого - після bcrypt (сотні мілісекунд). Це дає перелік облікових записів. Захист - виконувати хешування завжди;
  • різна робота залежно від результату: відправка листа лише якщо обліковий запис існує, запит до бази лише для певних випадків;
  • пошук у базі за секретом: WHERE token = ? - час пошуку за індексом теоретично теж може залежати від значення. Тому надійніше шукати за ідентифікатором, а секрет порівнювати окремо через hash_equals (так зроблено в Sanctum: токен має вигляд id|секрет).

Наскільки це реально в інтернеті: мережевий шум у мілісекунди набагато більший за наносекундні різниці порівняння рядків, тож атака на сирі рядкові порівняння через інтернет складна. Але з тисячами вимірювань і статистикою вона можлива, а в межах одного хмарного регіону шум значно менший. Порівняння в постійному часі коштує нічого - немає причин ризикувати.

Не лише рядки: криптографічні реалізації мають бути «constant-time» загалом - тому використовують перевірені бібліотеки (sodium_*, openssl_*), а не власні реалізації алгоритмів.

Докладніше в документації: PHP: hash_equals

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання