Старый поток, но все еще действительная проблема. Я заметил несколько хороших отзывов о безопасности и об отказе от использования «безопасности через неизвестность», но настоящие технические методы были недостаточны в моих глазах. Вещи, которые я должен сказать, прежде чем внести свой метод:
- НИКОГДА не храните пароль открытым текстом ... НИКОГДА !
- НИКОГДА храните хешированный пароль пользователя в нескольких местах в вашей базе данных. Серверная часть вашего сервера всегда способна извлечь хешированный пароль из таблицы пользователей. Не более эффективно хранить избыточные данные вместо дополнительных транзакций с БД, обратное верно.
- Идентификаторы вашего сеанса должны быть уникальными, поэтому никакие два пользователя никогда не смогут совместно использовать идентификатор, поэтому назначение идентификатора (может ли ваш номер водительского удостоверения соответствовать другим лицам? Нет.) При этом создается уникальная комбинация из двух частей, основанная на 2 уникальные строки. Ваша таблица Sessions должна использовать идентификатор в качестве PK. Чтобы разрешить нескольким устройствам доверять для автоматической регистрации, используйте другую таблицу для доверенных устройств, которая содержит список всех проверенных устройств (см. Мой пример ниже) и отображается с использованием имени пользователя.
- Нет смысла хэшировать известные данные в куки, куки могут быть скопированы. То, что мы ищем, это соответствующее пользовательское устройство, которое предоставляет достоверную информацию, которую невозможно получить без того, чтобы злоумышленник не скомпрометировал компьютер пользователя (опять же, см. Мой пример). Это будет означать, однако, что законный пользователь, который запрещает статическую информацию своего компьютера (например, MAC-адрес, имя хоста устройства, идентификатор пользователя, если он ограничен браузером и т. Д.), Остается непротиворечивым (или подделывает его в первую очередь), не сможет используйте эту функцию. Но если это вызывает озабоченность, учтите тот факт, что вы предлагаете автоматическую подписку пользователям, которым идентифицируют себя уникальнопоэтому, если они отказываются быть известными путем подмены своего MAC, подмены своего идентификатора пользователя, подмены / изменения своего имени хоста, скрытия за прокси и т. д., то они не могут быть идентифицированы и никогда не должны проходить аутентификацию для автоматической службы. Если вы хотите этого, вам нужно изучить доступ к смарт-картам в комплекте с программным обеспечением на стороне клиента, которое устанавливает идентичность используемого устройства.
Тем не менее, есть два отличных способа автоматического входа в систему.
Во-первых, дешевый, легкий способ, который ставит все это на кого-то другого. Если вы поддерживаете вход на свой сайт, например, с помощью своего аккаунта google +, возможно, у вас есть упрощенная кнопка google +, которая будет входить в систему, если пользователи уже вошли в google (я сделал это здесь, чтобы ответить на этот вопрос, как и всегда вошел в гугл). Если вы хотите, чтобы пользователь автоматически входил в систему, если он уже вошел с помощью доверенного и поддерживаемого средства проверки подлинности, и поставил флажок, чтобы сделать это, пусть ваши клиентские скрипты перед загрузкой выполняют код, соответствующий соответствующей кнопке «Вход в систему». просто убедитесь, что сервер хранит уникальный идентификатор в таблице автоматического входа, который содержит имя пользователя, идентификатор сеанса и аутентификатор, используемый для пользователя. Поскольку эти методы входа используют AJAX, вы все равно ждете ответа, и этот ответ является либо подтвержденным ответом, либо отклонением. Если вы получили проверенный ответ, используйте его как обычно, затем продолжите загрузку зарегистрированного пользователя как обычно. В противном случае вход в систему не удастся, но не говорите пользователю, просто продолжайте, не входя в систему, они заметят. Это сделано для того, чтобы злоумышленник, который украл куки (или подделал их в попытке повысить привилегии), не узнал, что пользователь автоматически выполняет вход на сайт.
Это дешево, и некоторые также могут посчитать его грязным, потому что оно пытается проверить вашу потенциально уже зарегистрированную личность в таких местах, как Google и Facebook, даже не сказав вам об этом. Однако его не следует использовать для пользователей, которые не запрашивали автоматическую регистрацию на вашем сайте, и этот конкретный метод предназначен только для внешней аутентификации, как в Google+ или FB.
Поскольку внешний аутентификатор использовался для скрытого информирования сервера о том, прошел ли пользователь проверку, злоумышленник не может получить ничего, кроме уникального идентификатора, который сам по себе бесполезен. Я уточню:
- Пользователь 'joe' впервые заходит на сайт, идентификатор сессии помещен в cookie-файл 'session'.
- Пользователь 'joe' Вход в систему, повышение привилегий, получение нового идентификатора сеанса и обновление cookie-сеанса.
- Пользователь "Джо" выбирает автоматическую регистрацию с помощью Google +, получает уникальный идентификатор, помещенный в cookie "keepmesignedin".
- Пользователь "Джо" имеет Google держать их в системе, что позволяет вашему сайту автоматически входить в систему с помощью Google в вашем бэкэнде.
- Атакующий систематически пытается использовать уникальные идентификаторы для «keepmesignedin» (это общедоступные знания, которые раздаются каждому пользователю), и нигде не подписывается; пытается уникальный идентификатор, присвоенный «Джо».
- Сервер получает уникальный идентификатор для «Джо», извлекает совпадения в БД для учетной записи 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 со своим паролем, открытым текстом или другим способом. Регенерируйте токен на каждой странице навигации так же, как токен сеанса. Это значительно снижает вероятность того, что злоумышленник сможет получить действительный токен-cookie и использовать его для входа в систему. Некоторые люди пытаются сказать, что злоумышленник может украсть файлы cookie у жертвы и выполнить атаку воспроизведения сеанса для входа в систему. Если бы злоумышленник мог украсть куки (что возможно), он, несомненно, скомпрометировал бы все устройство, то есть он мог бы просто использовать устройство для входа в систему в любом случае, что полностью противоречит цели кражи куки. Пока ваш сайт работает по протоколу HTTPS (что должно происходить при работе с паролями, номерами CC или другими системами входа в систему), вы предоставляете пользователю всю защиту, которую вы можете использовать в браузере.
Следует помнить одну вещь: данные сеанса не должны истекать, если вы используете автоподпись. Вы можете прервать возможность ложного продолжения сеанса, но проверка в системе должна возобновить данные сеанса, если это постоянные данные, которые, как ожидается, будут продолжаться между сеансами. Если вам нужны как постоянные, так и непостоянные данные сеанса, используйте другую таблицу для постоянных данных сеанса с именем пользователя в качестве PK и попросите сервер извлечь их, как если бы это были обычные данные сеанса, просто используйте другую переменную.
После того, как логин получен таким способом, сервер все равно должен проверить сеанс. Здесь вы можете кодировать ожидания для украденных или скомпрометированных систем; паттерны и другие ожидаемые результаты входа в сеансовые данные часто могут привести к выводам о том, что система была взломана или файлы cookie были подделаны для получения доступа. Именно здесь ваш специалист по ISS может установить правила, которые будут инициировать блокировку учетной записи или автоматическое удаление пользователя из системы автоматического входа, не позволяя злоумышленникам оставаться на достаточно долгое время, чтобы пользователь мог определить, как злоумышленник добился успеха и как его отключить.
В качестве заключительного примечания убедитесь, что любая попытка восстановления, изменения пароля или ошибки входа в систему после превышения порогового значения приводят к отключению автоматической регистрации до тех пор, пока пользователь не подтвердит правильность и не подтвердит, что это произошло.
Я прошу прощения, если кто-то ожидал, что код будет выдан в моем ответе, этого не произойдет Я скажу, что я использую PHP, jQuery и AJAX для запуска своих сайтов, и я НИКОГДА не использую Windows как сервер ... никогда.