Как сравнение HMAC может никогда не быть постоянным в Python?
В Python есть метод, специально предназначенный для сравнения HMAC для предотвращения временных атак: https://docs.python.org/3.7/library/hmac.html
И я читал о времени атаки здесь: https://security.stackexchange.com/questions/74547/timing-attack-against-hmac-in-authenticated-encryption
Мой вопрос: как это могло быть когда-либо не постоянным временем? Было бы необходимо рассчитать фактическое значение HMAC, чтобы сравнить его, и это не значит, что вы можете рассчитать дайджест по 1 символу за раз, верно? В конце концов, это будет простое сравнение строк, которое на 2 порядка быстрее, чем фактический расчет HMAC в моих тестах. Так где же здесь находится поверхность атаки? Может кто-нибудь привести пример того, где именно находится уязвимость, если я не использую hmac.compare_digest()
?
1 ответ
В конце концов, это будет простое сравнение строк, которое на 2 порядка быстрее, чем фактический расчет HMAC в моих тестах.
Но это не постоянное время. То, что они сделаны быстро, не означает, что разница не измерима. За bytes
значения, Python сначала проверяет одинаковую длину и равные первые байты перед использованием memcmp
проверить остальное. Для строк Python сравнивает длину, затем вид (если строка использует 1, 2 или 4 байта на символ), затем также использует memcmp
,
Справочная страница Linux для memcmp
прямо заявляет:
Не использовать
memcmp()
сравнивать критически важные для безопасности данные, такие как криптографические секреты, поскольку требуемое время ЦП зависит от количества равных байтов. Вместо этого требуется функция, которая выполняет сравнение в постоянное время. Некоторые операционные системы предоставляют такую функцию (например, NetBSDconsttime_memequal()
), но в POSIX такая функция не указана. В Linux может быть необходимо реализовать такую функцию самостоятельно.)
Достаточно решительный злоумышленник может использовать эту слабость, чтобы выяснить, какой хеш вы сохранили, по сравнению с хешем данных, которые он отправляет.
Сроки атаки позволяют подделывать подписи. Скажем, сервис хранит информацию авторизации в токене, который используется клиентом. Если бы клиент мог изменить этот токен, он мог бы получить доступ, которого у него не было бы в противном случае. Для защиты от этого токен подписывается с использованием подписи HMAC, что позволяет серверу проверить возвращенный токен, прежде чем принять его как действительный. Если данные авторизации не совпадают с подписью, токен отклоняется.
Если сервер делает это:
auth_data, signature = split_token(token)
expected = hmac_signature(auth_data)
if signature == expected:
# ...
Затем злоумышленник может определить, сколько символов поддельной подписи соответствует ожидаемой подписи, и соответствующим образом настроить. Они начинают с XXXXX:000000...
тогда попробуй XXXXX:1000000...
и т. д., пока время, затраченное службой, не увеличится, указывая на то, что у них совпадает первый символ. Затем второй символ может быть изменен, пока полная подпись не совпадет.