Предотвращение временных сбоев

Кажется, что какое-то время, утилита входа в систему Unix рассчитала только хэш, когда существовало действительное имя пользователя; это открыло дефект безопасности, который позволил использовать временную атаку, так как пользователь мог определить, когда было найдено имя пользователя на время, необходимое для генерации хэшированного ключа для сравнения.

Это имеет смысл для настольных приложений, но может ли это иметь смысл и для веб-приложений? Я склоняюсь к этому, но нужно ли это исправление?

Например, в модуле Django auth:

class MyBackend(ModelBackend):

    def authenticate(self, email=None, password=None):
        try:
            user = User.objects.get(email=email)
            return user if user.check_password(password) else None
        except User.DoesNotExist:
            User().check_password(password) # is this line necessary?
            return None

Будет ли дополнительный хеш-расчет иметь смысл для этого сценария? Если я использую ограничение скорости при вызовах auth, уменьшает ли вероятность тактирования тактирования?

Ответ 1

Первоначальная атака по времени, атака Tenex, не имела никакого отношения к хэшированию - она ​​работала путем позиционирования пароля, чтобы он пересек границы страницы, что приводит к провалу кеша виртуальной памяти. Злоумышленник может попробовать серийные пароли, расположенные так, чтобы только первый символ находился на первой странице, и он знал бы, что первый символ соответствовал, когда проверка прошла достаточно долго, чтобы пропустить кеш. Злоумышленник может повторить это для каждого символа в пароле.

Если злоумышленник не имеет контроля над мелкозернистым позиционированием входов в памяти, нет, точные атаки на пароли не являются проблемой, но любой секретный алгоритм проверки, который является суперлинейным w.r.t. длина тайны ( >= O (длина тайны)) может утечка информации о длине пароля.

Если вы стараетесь сравнивать все символы в пароле независимо от успеха, то вы также можете победить атаку:

boolean match = true;
for (int i = 0; i < min(salted_from_db_length, salted_from_user_length); ++i) {
  if (salted_from_db[i] != salted_from_user[i]) {
    match = false;
    //break;  // Stopping early leaks info.
  }
}
match = salted_from_db_length == salted_from_user_length && match;

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

Примечание. Термин "временная атака" также используется в других контекстах, и это может повлиять на веб-приложения. Например, когда системные часы используются для создания скрытого канала между двумя процессами, которые не могут сговориться - javascript загружается в два разных происхождение может установить канал с низкой пропускной способностью, используя интервал для проверки времени и цикла для потребления процессора или не для передачи бит.

Ответ 2

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

Временные атаки использовались в том случае, когда имя пользователя известно для обнаружения хэша и, в конечном счете, самого пароля, путем анализа количества времени, которое требуется серверу для сравнения строк, следовательно, использование функция "slow_equals" для сравнения хэшей и которая не выходит на раннем этапе поиска несоответствия.

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

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

Рассмотрим процесс: 1. Запрос базы данных для извлечения хеша и соли; 2. Хеш-пароль с солью; 3. Сравните полученный хэш с сгенерированным хешем из предоставленного пароля.

  • Запускается ли запрос раньше, когда он находит соответствующую запись? Это может произойти, если мы укажем UNIQUE KEY для столбца имени пользователя, поэтому мы, вероятно, не должны этого делать, и вместо этого есть другие механизмы, чтобы избежать дублирования при изменении БД.

  • Выполняем ли мы эти последующие шаги, если запрос БД не нашел записи? (Делает ли ваш процесс хеширования немного времени?) Таким образом, следует использовать хэш и соль по умолчанию, если имя пользователя не соответствует, чтобы завершить процесс в постоянное время [и это является причиной код обработчика исключений в Q].

  • Используйте здесь "slow_equals".

Ответчик здесь предположил, что отклонение в сетевой латентности делает это проблемой без проблем. Я утверждаю, что злоумышленнику не нужен 100-процентный шанс успеха, и статистический анализ будет выявлять. Вы не можете быть слишком осторожны.

Ответ 3

Не может быть окончательного ответа, но похоже, что вы могли бы обеспечить, чтобы все операции проверки имени пользователя занимали одинаковое количество времени. Заставьте их перейти в состояние ожидания после того, как они закончатся, пока не пройдет предопределенное количество времени.