Раньше для предотвращения повторных атак всегда использовались метки времени, но это не гарантировало, что каждый запрос был одноразовым. Сегодня я видел статью, в которой используется одноразовый номер (число, используемое один раз), чтобы гарантировать, что он будет эффективным один раз.Я чувствую, что их комбинация может дать очень хороший эффект.
Атака с повторным воспроизведением является одним из распространенных методов атаки хакеров в компьютерном мире.Так называемая атака с повторным воспроизведением заключается в том, что злоумышленник отправляет пакет, который был получен хостом-получателем, для достижения цели обмана системы.Он в основном используется в процессе аутентификации личности.
Прежде всего, необходимо уточнить одну вещь: повторная атака является вторичным запросом, хакер получает запрошенное HTTP-сообщение, перехватывая пакет, а затем хакер пишет аналогичный HTTP-запрос и отправляет его на сервер. То есть сервер обработал два запроса: сначала обычный HTTP-запрос, а затем поддельный HTTP-запрос, отправленный хакером.
Решение на основе временных меток
Для каждого HTTP-запроса необходимо добавить параметр метки времени, а затем метку времени и другие параметры подписать цифровой подписью. Поскольку обычный HTTP-запрос обычно не превышает 60 с с момента его отправки на сервер, после того, как сервер получает HTTP-запрос, он сначала определяет, превысил ли параметр метки времени по сравнению с текущим временем 60 с. считается незаконным.
Если хакер получит URL-адрес нашего запроса, перехватив пакет:
Посмотри на него. Сайт / индекс / информация? ...
в
$sign=md5($uid.$token.$stime);
// 服务器通过uid从数据库中可读出token
При нормальных обстоятельствах хакеру требуется гораздо больше 60 секунд, чтобы воспроизвести запрос из захваченного пакета, поэтому параметр stime в запросе в настоящее время недействителен. Если хакер изменит параметр stime на текущую метку времени, цифровая подпись, соответствующая параметру знака, будет недействительной, поскольку хакер не знает значение токена и не может сгенерировать новую цифровую подпись.
Однако лазейки в этом методе также очевидны: если повторная атака выполняется после 60 с, то сделать это невозможно, поэтому этот метод не может гарантировать, что запрос действителен только один раз.
решение на основе nonce
Значение nonce — это случайная строка, которая действует только один раз. Требуется, чтобы параметр был разным для каждого запроса, поэтому этот параметр, как правило, связан с меткой времени. Ради удобства мы напрямую используем шестнадцатеричный код отметка времени и фактическое использование. Вы можете добавить IP-адрес клиента, MAC-адрес и другую информацию в качестве одноразового параметра после хеширования.
Мы сохраняем параметр nonce каждого запроса в «коллекцию», которая может храниться в базе данных или кэшироваться в формате json.
Каждый раз, когда обрабатывается HTTP-запрос, сначала определяется, находится ли параметр nonce запроса в «наборе», и, если он существует, считается недопустимым запросом.
Если хакер получит URL-адрес нашего запроса, перехватив пакет:
Посмотрите на него site/index/info?…
в
$sign=md5($uid.$token.$nonce);
// 服务器通过uid从数据库中可读出token
Параметр nonce был сохранен в «коллекции» на сервере при выполнении первого запроса, а второй запрос будет распознан и отклонен. В рамках цифровой подписи параметр nonce не может быть изменен, поскольку хакер не знает токен, поэтому новый знак не может быть сгенерирован.
С этим методом также связана большая проблема, то есть «набор», в котором хранится параметр nonce, будет становиться все больше и больше, а время, затрачиваемое на проверку существования одноразового номера в «наборе», будет становиться все длиннее и длиннее. Мы не можем сделать «коллекцию» одноразового номера бесконечно большой, поэтому «коллекцию» необходимо периодически очищать, но как только «коллекция» будет очищена, мы не сможем проверить очищенный параметр одноразового номера. То есть, если предположить, что «коллекция» очищается в среднем один раз в день, URL-адрес, который мы захватили, не может быть воспроизведен в это время, но мы все равно можем воспроизводить его через день. Более того, хранение параметров «nonce» всех запросов в течение 24 часов также требует больших накладных расходов.
Схема на основе метки времени и одноразового номера
Итак, если мы используем параметры TimeStamp и Nonce при использовании TimeStamp? Однократный одноразовый номер может решить проблему с параметром TimeStamp 60s, а TimeStamp может решить проблему с «набором» параметра Nonce.
Основываясь на схеме временных меток, мы добавляем параметр nonce, потому что параметр timstamp считается незаконным запросом для запросов, превышающих 60 секунд, поэтому нам нужно хранить только «коллекцию» параметров nonce из 60 секунд.
Если хакер получит URL-адрес нашего запроса, перехватив пакет:
Посмотрите на него site/index/info?…
в
$sign=md5($uid.$token.$stime.$nonce);
// 服务器通过uid从数据库中可读出token
Если HTTP-запрос повторяется в течение 60 секунд, он будет считаться недопустимым, поскольку параметр одноразового номера был записан в «коллекцию» параметров одноразового номера сервера во время первого запроса. По прошествии более 60 с параметр stime станет недействительным.В это время, поскольку хакер не знает значение токена, подпись не может быть восстановлена.
Подводя итог, мы считаем, что обычный HTTP-запрос не будет отправляться более 60 с, повторная атака в течение 60 с может быть гарантирована параметром nonce, а повторная атака, превышающая 60 с, может быть гарантирована параметром stime.
Поскольку параметр nonce работает только в течение 60 секунд, вам нужно сохранить параметр nonce только в течение 60 секунд.
Нам не нужно очищать набор параметров одноразового номера каждые 60 с. Нам нужно только судить о времени последней модификации набора одноразовых номеров при поступлении нового одноразового номера. Если он превышает 60 с, очистить набор и сохранить новый набор параметров одноразового номера. На самом деле набор параметров nonce может храниться дольше, но не менее 60 с.
процесс проверки
//判断stime参数是否有效
if( $now - $stime > 60){
die("请求超时");
}
//判断nonce参数是否在“集合”已存在
if( in_array($nonce,$nonceArray) ){
die("请求仅一次有效");
}
//验证数字签名
if ( $sign != md5($uid.$token.$stime.$nonce) ){
die("数字签名验证失败");
}
//判断是否需要清理nonce集合
if( $now - $nonceArray->lastModifyTime > 60 ){
$nonceArray = null;
}
//记录本次请求的nonce参数
$nonceArray.push($nonce);
//开始处理合法的请求
Справочная статья: