Как думаете, сколько времени занимает такая проверка?
if token == "secret_key":
allow_access()
Почти за мгновение. Но иногда эти миллисекунды могут выдать секрет.
🔍В чем дело
Во многих реализациях строки сравниваются посимвольно.
Алгоритм обычно выглядит так:
1) Сравнить первый символ
2) Если совпал - второй
3) Если совпал второй - третий
И так далее
Если символ не совпал, тогда сравнение заканчивается.
📝Где появляется проблема
Предположим секретный токен
A9F4K2
Если атакующий отправит
BXXXX
Сравнение закончится на первом символе.
Если отправить AXXXX, то проверка пройдет чуть дальше.
В результате время выполнения будет немного отличаться.
Если отправить много запросов и измерять время ответа, можно постепенно угадывать символы по одному.
✔️Как решают проблему
Используют сравнение за константное время.
Алгоритм сравнивает все символы, даже если первый уже не совпал.
Для этого во многих языках есть специальные функции, например:
GO
subtle.ConstantTimeCompare(a, b)
JavaScript
crypto.timingSafeEqual(a, b)
😎Как часто вы видели проверки секретов через обычное ==?
