Старая тема, но все еще действительная проблема. Я заметил несколько хороших отзывов о безопасности и об отказе от использования «безопасности через неизвестность», но реальных технических методов было недостаточно для моих глаз. Вещи, которые я должен сказать, прежде чем внести свой метод:
- НИКОГДА сохранять пароль открытым текстом ... КОГДА-ЛИБО!
- НИКОГДА хранить хешированный пароль пользователя в нескольких местах в вашей базе данных. Серверная часть вашего сервера всегда способна извлечь хешированный пароль из таблицы пользователей. Хранить избыточные данные вместо дополнительных транзакций с БД не эффективнее, обратное верно.
- Ваш идентификатор сеанса должен быть уникальным, поэтому никакие два пользователя не могут когда-либо поделиться идентификатором, следовательно, цель идентификатора (может ли ваш номер водительского удостоверения соответствовать когда-либо другим лицам? Нет.). уникальная комбинация из двух частей, основанная на 2 уникальных струнах. Ваша таблица Sessions должна использовать идентификатор в качестве PK. Чтобы разрешить нескольким устройствам доверять для автоматической регистрации, используйте другую таблицу для доверенных устройств, которая содержит список всех проверенных устройств (см. Мой пример ниже) и сопоставляется с использованием имени пользователя.
- Не имеет смысла хэшировать известные данные в куки, куки могут быть скопированы. То, что мы ищем, это соответствующее пользовательское устройство, которое предоставляет достоверную информацию, которую невозможно получить без того, чтобы злоумышленник не скомпрометировал компьютер пользователя (опять же, см. Мой пример). Это будет означать, однако, что законный пользователь, который запрещает статическую информацию своего компьютера (например, MAC-адрес, имя хоста устройства, идентификатор пользователя, если он ограничен браузером и т. Д.), Остается непротиворечивым (или подделывает его в первую очередь), не сможет используйте эту функцию. Но если это вызывает озабоченность, учтите тот факт, что вы предлагаете автоматическую регистрацию пользователям, которые идентифицируют себя уникально , поэтому, если они отказываются быть известными путем подмены своего MAC, подделывают их useragent, подмена / изменение имени хоста, скрытие прокси и т. д., тогда они не могут быть идентифицированы и никогда не должны проходить аутентификацию для автоматической службы. Если вы хотите этого, вам нужно изучить доступ к смарт-картам в комплекте с программным обеспечением на стороне клиента, которое устанавливает идентичность используемого устройства.
Несмотря на это, есть два отличных способа автоматического входа в систему.
Во-первых, дешевый, легкий способ, который ставит все это на кого-то другого. Если вы поддерживаете вход в свой сайт, скажем, с помощью, скажем, своего аккаунта Google +, у вас, вероятно, есть упрощенная кнопка Google +, которая будет входить в систему, если пользователи уже вошли в Google (я сделал это здесь, чтобы ответить на этот вопрос, как и всегда вошел в гугл). Если вы хотите, чтобы пользователь автоматически выполнил вход, если он уже выполнил вход с помощью доверенного и поддерживаемого средства проверки подлинности, и поставил флажок для этого, пусть ваши клиентские сценарии перед загрузкой выполняют код, соответствующий соответствующей кнопке «Вход в систему». Просто убедитесь, что сервер хранит уникальный идентификатор в таблице автоматического входа, в которой есть имя пользователя, идентификатор сеанса и аутентификатор, используемый для пользователя. Поскольку эти методы входа используют AJAX, вы все равно ждете ответа, и этот ответ является либо подтвержденным ответом, либо отклонением. Если вы получили проверенный ответ, используйте его как обычно, затем продолжите загрузку зарегистрированного пользователя как обычно. В противном случае вход в систему не удастся, но не говорите пользователю, просто продолжайте, поскольку не вошли в систему, они заметят. Это сделано для того, чтобы злоумышленник, который украл файлы cookie (или подделал их в попытке повысить привилегии), не узнал, что пользователь автоматически выполняет вход на сайт.
Это дешево, и некоторые также могут посчитать его грязным, потому что оно пытается проверить вашу потенциально уже подписанную самость в таких местах, как Google и Facebook, даже не сказав вам об этом. Однако его не следует использовать для пользователей, которые не запрашивали автоматическую регистрацию на вашем сайте, и этот конкретный метод предназначен только для внешней аутентификации, как в Google+ или FB.
Поскольку внешний аутентификатор использовался для скрытого информирования сервера о том, прошел ли пользователь проверку, злоумышленник не может получить ничего, кроме уникального идентификатора, который сам по себе бесполезен. Я уточню:
- Пользователь 'joe' впервые заходит на сайт, идентификатор сеанса помещен в файл cookie 'session'.
- Пользователь 'joe' Вход в систему, повышение привилегий, получение нового идентификатора сеанса и возобновление сеанса cookie.
- Пользователь "Джо" выбирает автоматическую регистрацию с помощью Google +, получает уникальный идентификатор, помещенный в cookie "keepmesignedin".
- Пользователь "joe" имеет Google, чтобы держать его в системе, что позволяет вашему сайту автоматически входить в систему с помощью Google в вашем бэкэнде.
- Атакующий систематически пытается использовать уникальные идентификаторы для «keepmesignedin» (это общедоступные знания, которые раздаются каждому пользователю), и нигде не подписывается; пытается уникальный идентификатор, присвоенный 'Джо'.
- Сервер получает уникальный идентификатор для 'joe', извлекает совпадение в БД для учетной записи Google +.
- Сервер отправляет Attacker на страницу входа, которая выполняет запрос AJAX для входа в Google.
- Сервер Google получает запрос, использует свой API, чтобы увидеть, что Attacker не вошел в систему.
- Google отправляет ответ, что в данный момент нет подключенного пользователя через это соединение.
- Страница злоумышленника получает ответ, скрипт автоматически перенаправляет на страницу входа со значением POST, закодированным в URL.
- Страница входа получает значение POST, отправляет файл cookie для 'keepmesignedin' на пустое значение и действует до даты 1-1-1970 для предотвращения автоматической попытки, в результате чего браузер злоумышленника просто удаляет cookie.
- Атакующий получает обычную страницу входа в первый раз.
Независимо от того, что, даже если злоумышленник использует несуществующий идентификатор, попытка должна завершиться неудачей на всех попытках, кроме тех случаев, когда получен проверенный ответ.
Этот метод может и должен использоваться вместе с вашим внутренним аутентификатором для тех, кто входит на ваш сайт с помощью внешнего аутентификатора.
=========
Теперь, для вашей собственной системы аутентификации, которая может автоматически подписывать пользователей, вот как я это делаю:
БД имеет несколько таблиц:
TABLE users:
UID - auto increment, PK
username - varchar(255), unique, indexed, NOT NULL
password_hash - varchar(255), NOT NULL
...
Обратите внимание, что длина имени пользователя может быть 255 символов. Моя серверная программа ограничивает имена пользователей в моей системе 32 символами, но внешние аутентификаторы могут иметь имена пользователей с их @ domain.tld больше этого значения, поэтому я просто поддерживаю максимальную длину адреса электронной почты для максимальной совместимости.
TABLE sessions:
session_id - varchar(?), PK
session_token - varchar(?), NOT NULL
session_data - MediumText, NOT NULL
Обратите внимание, что в этой таблице нет поля пользователя, поскольку имя пользователя при входе в систему содержится в данных сеанса, и программа не допускает нулевые данные. Идентификатор session_id и session_token могут быть сгенерированы с использованием случайных хэшей md5, хэшей sha1 / 128/256, меток даты и времени со случайными строками, добавленными к ним, затем хэшированными или как угодно, но энтропия вашего вывода должна оставаться настолько высокой, насколько допустимо для предотвращать атаки методом "грубой силы", даже отрываясь от земли, и перед попыткой их добавления все хеши, сгенерированные вашим классом сеансов, должны быть проверены на совпадения в таблице сеансов.
TABLE autologin:
UID - auto increment, PK
username - varchar(255), NOT NULL, allow duplicates
hostname - varchar(255), NOT NULL, allow duplicates
mac_address - char(23), NOT NULL, unique
token - varchar(?), NOT NULL, allow duplicates
expires - datetime code
MAC-адреса по своей природе должны быть УНИКАЛЬНЫМИ, поэтому имеет смысл, что каждая запись имеет уникальное значение. Имена хостов, с другой стороны, могут быть законно дублированы в отдельных сетях. Сколько людей используют «Домашний ПК» в качестве одного из имен своих компьютеров? Имя пользователя берется из данных сеанса серверным бэкэндом, поэтому манипулирование им невозможно. Что касается токена, тот же метод генерации токенов сеанса для страниц должен использоваться для генерации токенов в файлах cookie для автоматической регистрации пользователя. Наконец, добавляется код даты и времени, когда пользователь должен будет подтвердить свои учетные данные. Либо обновите эту дату-время при входе пользователя в систему, сохраняя его в течение нескольких дней, либо вынудите его истечь, независимо от того, какой последний вход в систему держал его в течение месяца или около того, в зависимости от того, что диктует ваш дизайн.
Это предотвращает систематическую подмену MAC-адреса и имени хоста для пользователя, для которого они знакомы, с автоматическим входом в систему. НИКОГДА не разрешает пользователю сохранять куки-файлы со своим паролем, открытым текстом или другим способом. , Регенерируйте токен на каждой странице навигации так же, как токен сеанса. Это значительно снижает вероятность того, что злоумышленник сможет получить действительный токен-cookie и использовать его для входа в систему. Некоторые люди пытаются сказать, что злоумышленник может украсть куки у жертвы и выполнить атаку воспроизведения сеанса для входа в систему. Если бы злоумышленник мог украсть куки (что возможно), он, несомненно, скомпрометировал бы все устройство, то есть он мог бы просто использовать устройство для входа в систему в любом случае, что полностью противоречит цели кражи куки. Пока ваш сайт работает по протоколу HTTPS (что необходимо при работе с паролями, номерами CC или другими системами входа в систему), вы предоставляете пользователю всю защиту, которую вы можете использовать в браузере.
Следует помнить одну вещь: данные сеанса не должны истекать, если вы используете авто-вход. Вы можете прервать возможность ложного продолжения сеанса, но проверка в системе должна возобновить данные сеанса, если это постоянные данные, которые, как ожидается, будут продолжаться между сеансами. Если вам нужны как постоянные, так и непостоянные данные сеанса, используйте другую таблицу для постоянных данных сеанса с именем пользователя в качестве PK, и пусть сервер извлекает их так же, как и обычные данные сеанса, просто используйте другую переменную.
После того, как логин получен таким способом, сервер все равно должен проверить сеанс. Здесь вы можете кодировать ожидания для украденных или скомпрометированных систем; Шаблоны и другие ожидаемые результаты входа в сеансовые данные часто могут привести к выводам о том, что система была взломана или были подделаны файлы cookie для получения доступа. Именно здесь ваш специалист по ISS может установить правила, которые будут инициировать блокировку учетной записи или автоматическое удаление пользователя из системы автоматического входа, не позволяя злоумышленникам оставаться на достаточно долгое время, чтобы пользователь мог определить, как злоумышленник добился успеха и как его отключить.
В качестве заключительного примечания убедитесь, что любая попытка восстановления, смена пароля или сбой входа в систему, превышающий пороговое значение, приводят к отключению автоматической регистрации до тех пор, пока пользователь не подтвердит правильность и не подтвердит, что это произошло.
Я прошу прощения, если кто-то ожидал, что код будет выдан в моем ответе, этого здесь не произойдет. Я скажу, что я использую PHP, jQuery и AJAX для запуска своих сайтов, и я НИКОГДА не использую Windows как сервер ... никогда.