Разработка программного обеспечения

Атаки по времени в PHP: Практический пример - почему `hash_equals()` имеет значение

Хочешь получить реалистичный пример тайминговой атаки на API-токены в Wordpress/Laravel/PHP? Мы расскажем об этом здесь, включая советы и лучшие практические меры против тайминговых атак.

Многие разработчики при проверке API-ключей, токенов и других секретных строк полагаются на простое сравнение с помощью === или ==. На первый взгляд, это выглядит разумно - но есть одна загвоздка: временные различия в сравнении могут быть использованы злоумышленниками.

В этой статье описан реалистичный пример того, как концептуально работает атака по времени.

Реальный сценарий (упрощенный пример)

Представь, что внутренний микросервис принимает запросы с токеном параметров запроса и сравнивает его с токеном API GitHub, хранящимся в среде.

Небезопасный код (упрощенный):

// insecure.php (упрощенный пример)$expected = getenv('GITHUB_API_TOKEN');// например, 'V1cHt2S67DADJIm9sX9yzCc272EkSC'$provided = $_GET['token'] ?? '';if ($provided === $expected) { // предоставляем доступ} PHP  

Я объясню, почему это проблематично, в следующем разделе.

Как работает атака по времени?

Если реализация сравнения токенов сравнивает символ за символом и прерывается сразу же при первой ошибке, то запрос с правильным первым символом в среднем занимает немного больше времени.

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

Злоумышленник использует это преимущество, тестируя все возможные символы для каждой позиции, измеряя время отклика очень часто и анализируя его статистически. Символ с наибольшим средним/пропорционально большим временем, вероятно, является правильным. Таким образом, токен восстанавливается шаг за шагом.

Почему hash_equals() - правильный выбор

PHP предоставляет функцию сравнения строк с постоянным временем - hash_equals(). Она гарантирует, что время выполнения сравнения не зависит от общих префиксов - до тех пор, пока обе строки имеют одинаковую длину.

Безопасная альтернатива (для Laravel, PHP, Wordpress):

// secure.php$expected = getenv('GITHUB_API_TOKEN'); $provided = $_GET['token'] ?? '';if (hash_equals($expected, $provided)) { // предоставляем доступ} PHP  

Примечание: hash_equals() является "независимой от времени" только в том случае, если длины равны. Хорошей практикой является разработка токенов таким образом, чтобы их длина была постоянной (например, HMAC, UUID фиксированной длины или случайные строки Base64 фиксированной длины).

Знаешь ли ты? Только UUID-V4 генерируется полностью случайным образом, поэтому его часто используют для токенов безопасности. Поскольку он не содержит никакой информации о времени или устройстве, он обеспечивает высокий уровень непредсказуемости и тем самым защищает от атак, основанных на шаблонах или предсказаниях. Именно поэтому UUID-V4 является предпочтительным выбором, когда речь идет о безопасных, трудноугадываемых идентификаторах.

Дополнительные меры защиты - больше, чем просто hash_equals()

  1. Постоянная длина токена
    Используй токены с фиксированной длиной, например UUID-V4. Если злоумышленник угадает длину, это будет не так полезно, пока сами символы безопасны.
  2. Ограничение скорости
    Ограничь количество запросов на один IP или на один аккаунт. Атаки по времени требуют множества измерений; ограничение скорости значительно увеличивает усилия и затраты атакующего.
  3. Ведение логов и мониторинг
    Распознавай необычные паттерны (много попыток ввода токена, систематическое изменение определенных параметров) и реагируй автоматически.
  4. Соль / HMAC / подписи
    Используй подписанные токены (HMAC с секретным ключом) или OAuth-токены вместо открытого сравнения необработанных статических ключей.
  5. TLS/HTTPS
    Шифрование защищает каналы связи - хотя оно и не предотвращает временные атаки на внутренности сервера, это базовое требование.
  6. Ротация токенов
    Короткий срок жизни токенов уменьшает пользу от скомпрометированного токена.

Заключение

Тайминговые атаки не являются чисто теоретической проблемой - они были исследованы на практике и могут иметь серьезные последствия, особенно для общедоступных конечных точек. Хорошая новость: для разработчиков PHP/Laravel/Wordpress первая контрмера очень проста:

  • Замени прямые сравнения чувствительных строк на hash_equals().
  • Обеспечь постоянную длину токенов, ограничение скорости, ведение логов и безопасное управление токенами.
Об авторе
Основатель и генеральный директор компании Langmeier Software
Я не хочу ничего усложнять. Я не хочу разрабатывать идеальное программное обеспечение для бизнеса. Я не хочу попасть в список лучших технологий. Потому что дело в бизнес-приложениях не в этом. Речь идет о том, чтобы убедиться, что твои данные надежно защищены. И чтобы все работало гладко, а ты сохранял полный контроль и мог сосредоточиться на развитии своего бизнеса. Простота и надежность - мои главные принципы, которые вдохновляют меня каждый день.
 
Смотри дальше:
PHP, Осознание безопасности, Кибербезопасность
Статьи, относящиеся к теме