Использование временных меток для предотвращения перехвата сеанса?
Я искал способы защиты от перехвата сеансов, когда кто-то крал cookie-файл сеанса и использовал его для получения доступа к системе.
Такие программы, как http://codebutler.com/firesheep позволяют легко прослушивать сеансы в открытых беспроводных сетях, а другие способы получения сеансов включают атаки с использованием межсайтовых сценариев или просто физическое снятие их с компьютера жертвы.
Использование SSL для защиты всех сеансов связи cookie-файлов с сервером имеет решающее значение для предотвращения перехвата Firesheep, а настройка HTTPOnly для cookie-файлов помогает предотвратить возможность чтения cookie сеансовых cookie-файлов при атаках XSS, но все же уязвима для атак на основе AJAX.
Другим уровнем является включение токена безопасности или одноразового номера в файл cookie сеанса, который обновляется при каждом запросе. Вы сохраняете токен в хранилище данных на стороне сервера и в файле cookie, и при каждом запросе вы сравниваете, что токен в файле cookie совпадает с токеном в хранилище данных.
Если токены не совпадают, это может указывать на то, что кто-то украл сеанс и пытается его использовать, чтобы вы могли либо проигнорировать запрос, либо аннулировать сеанс и потребовать от пользователя повторной аутентификации. Однако несоответствующие токены также могут быть результатом медленного / нестабильного соединения.
Например, может иметь место случай, когда сервер получает запрос от реального пользователя, обновляет токен сеанса в хранилище данных сервера и отвечает пользователю сессионным куки-файлом, который содержит обновленный токен. Но пользователь не получает ответ из-за медленного / нестабильного соединения, поэтому у пользователя все еще есть старый токен сеанса, в то время как новый хранится на сервере. Когда пользователь повторяет запрос, токены не совпадают.
Один из способов смягчить эту проблему - позволить серверу сохранить историю последних нескольких токенов и проверить, совпадают ли они, но затем возникает ситуация, сколько токенов нужно сохранить, и в зависимости от того, насколько нестабильно соединение или насколько пользователь доволен кликом, сервер может перебирать историю до того, как соединение восстанавливается, а сессия пользователя обновляется браузером.
Альтернативой хранению истории токенов является отметка времени каждого сеанса и проверка, находятся ли отметки времени в некотором коротком заданном диапазоне, скажем, 30 секунд. Если временная метка cookie сеанса пользователя находится в пределах 30 секунд от сохраненной временной метки сеанса сервера, то сеанс считается подлинным.
Пример псевдокода
def authenticate_request():
if (stored_session.timestamp - session.timestamp > 30 seconds):
return False
return True
Это позволяет избежать необходимости сохранять историю токенов - метка времени становится токеном - но у злоумышленников есть 30-секундное окно для возможности перехватить сеанс после его кражи. Хотя это и так, альтернатива истории токенов не лучше, потому что она дает злоумышленникам потенциально более длительное окно возможностей.
Другие подходы к проверке IP-адресов и изменений User-Agent также имеют проблемы. Пользовательские агенты легко подделываются, и если злоумышленник может получить сеанс пользователя, он может легко определить пользовательский агент с помощью того же кода XSS или с помощью других средств.
Если пользователь подключен к мобильному устройству, его IP-адрес может часто меняться, что приведет к множеству ложных срабатываний. Кроме того, злоумышленник может находиться за брандмауэром одной компании, поэтому IP-адрес пользователя и злоумышленника совпадают с внешним веб-сервером.
Является ли использование метки времени правильным подходом или есть лучший способ? Правильный ли 30-секундный буфер? Какие крайние случаи я пропускаю?
1 ответ
Я не вижу, как будет работать отметка времени. Это потребовало бы от пользователя никогда не тратить больше 30 секунд на страницу перед отправкой другого запроса на сервер. Я уверен, что потратил намного больше 30 секунд, читая эту страницу и набирая этот ответ, прежде чем нажать "Опубликовать".
Мне кажется, что существует внутренняя проблема, заключающаяся в том, что любые данные, которые вы отправляете по линии, могут быть перехвачены и дублированы. Шифрование пароля не решает проблему, потому что хакер может перехватить зашифрованное значение и затем отправить это зашифрованное значение. Его не волнует, что такое незашифрованное значение.
Та же история для любого токена, который вы отправляете. Хакер может перехватить токен и скопировать его.
Единственная идея, о которой я слышал, которая, кажется, решает проблему, - это система вызова и ответа, использующая открытый и закрытый ключи: A создает произвольную строку символов, шифрует ее с использованием открытого ключа B и отправляет ее B. B расшифровывает, что строка, используя свой закрытый ключ и отправляет расшифрованное значение обратно вместе с данными своего приложения. Затем A проверяет, соответствует ли расшифрованное значение исходному значению. Если он не проверяется, он отклоняет связанные данные.
Хакер не может перехватить сообщение от A и подделать ответ, если он не знает секретный ключ B. Хакер не может использовать ранее перехваченный ответ от B, потому что случайная строка каждый раз отличается.