Игорь З.
29 сообщений
#15 лет назад
Возникла задача разработки более-менее защищенной системы регистрации пользователей на сайте на ява-скрипт. Т.е. чтобы злоумышленник не смог авторизоваться на сайте в следующих случаях:

1. Увел с сервера базу данных пользователей;
2. Проснифал трафик на стороне клиента.
3. Украл сессию (куки) у клиента.
Случаи, когда у клиента перехватываются нажатия клавиш на клавиатуре с целью получения пароля, не рассматриваем.

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

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

Уязвимое место - это передача пароля в открытом виде.

Первый момент - авторизация. Решение - при нажатии кнопки "Войти" производить 2 запроса к серверу – при первом сервер возвращает случайное число, которым шифруется пароль и во втором запросе на сервер уже передаётся зашифрованный этим числом пароль.
Т.е. при нажатии кнопки "Войти" в форме авторизации ява-скрипт отправляет аякс запрос на сервер, в котором передаёт логин. Сервер проверяет, если такой пользователь есть, генерирует случайное число Random, заносит его в базу, туда же заносит данные пользователя (IP и браузер), отправляет Random обратно. Ява-скрипт вычисляет значение md5(Random+md5(пароль+const)), где const - некая константа. Полученное значение передаёт на сервер. Сервер извлекает из базы хеш пароля md5(пароль+const), Random, IP и браузер, вычисляет md5(Random+md5(пароль+const)) и сравнивает с тем, что прислал клиент. Если всё совпадает - значит пользователь ввел правильный пароль, открывается сессия с определенным временем жизни, с привязкой к ip и браузеру клиента, все существующие сессии для этого пользователя удаляются (если такие существуют) - генерируется случайное уникальное session_id, записывается в куки и заносится в таблицу сессий. Также в таблицу сессий заносим IP клиента и данные о его браузере.
Логин можно передавать в открытую, это не принципиально, или как xor(логин, const) - мизерная, но защита от тупого снифинга.
Итого вопрос с авторизацией решен.

Второй момент - регистрация. Чтобы при регистрации не передавать пароль в открытом виде, используем RSA шифрование - открытый ключ задаём в ява-скрипте, им шифруем пароль по методу Сервер расшифровывает пароль своим закрытым ключом, вычисляет хеш md5(пароль+const) и заносит его в базу.

Всё. На мой взгляд, в случае любой из атак, перечисленных в п.1-3 злоумышленник не сможет авторизоваться на сайте.

Ваше мнение? На сколько действенен на практике такой алгоритм, может какие дыры пропустил?
Андрей К.
1172 сообщения
#15 лет назад
Первое, вы параноик. Второе, солёный хэш - не лучший способ защиты. В случае сниффинга все ваши выкрутасы вообще пустая трата времени.
Электронную платежную систему разрабатываете?
Игорь З.
29 сообщений
#15 лет назад
Для платежной системы по любому нужен https. Тут попроще система, но защититься тоже нужно.
И как раз в данном случае снифинг по-моему ничего не даст. Предположим, я как хакер узнаю логин некого пользователя, значение Random и md5(Random+md5(пароль+const)). Каким образом это поможет мне авторизоваться под этим пользователем на сайте?
Если я повторно отправлю на сайт md5(Random+md5(пароль+const)), авторизации не произойдет, т.к. значения Random в базе уже нет. Если попытаюсь зайти с сессионной кукой, тоже не выйдет, т.к. сессия к IP привязана. Т.е. не зная пароля ничего не выйдет.
Вадим Т.
3240 сообщений
#15 лет назад
Цитата ("tri777ki"):
Очевидный вариант - использовать ssl. Был отвергнут по причине наличия нескольких сайтов, на каждый из которых пришлось бы покупать сертификат, плюс еще и следить за продлением сертификатов.

Если не хотите покупать, то кто мешает самому сертификат сгенерировать?

Цитата ("tri777ki"):
Если я повторно отправлю на сайт md5(Random+md5(пароль+const)), авторизации не произойдет, т.к. значения Random в базе уже нет. Если попытаюсь зайти с сессионной кукой, тоже не выйдет, т.к. сессия к IP привязана. Т.е. не зная пароля ничего не выйдет.

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

IMHO это как раз тот случай, когда любой изобретенный велосипед будет хуже старых проверенных решений (с HTTPS).
Вадим Т.
3240 сообщений
#15 лет назад
И да, в базе пароли лучше не хранить, стандартный вариант: salt + f(salt + password), тут вместо f подставьте предпочитаемую функцию хеширования.
Андрей К.
1172 сообщения
#15 лет назад
Если сайт не может окупить стоимость ssl, то и ролики к костылям приделывать смысла нет.
Вадим Т.
3240 сообщений
#15 лет назад
Далее, даже если отбросить легкость кражи сессионной куки и захода хакера с того же IP из локалки...
Да, можно защитить авторизацию (точнее, в данном случае это не авторизация, а аутентификация), реализовав алгоритм RSA на клиенте и на сервере самостоятельно, обеспечив обмен ключани и т.д.
Хотя это будет далеко не легковесные решения, тот же HTTPS будет работать шустрее хотя бы потому, что реализован в бинарном нативном коде в браузере клиента и на сервере в либах. Теперь сравните с вариантом генерации приватного и паблик ключа на JavaScript на клиенте, и например на <Ваш_язык_программирования> на сервере...
Ну ладно, допустим, Вы защитили процедуру аутентификации.

Но что дальше? Сами данные защищать не нужно? То есть, пароль пусть заснифить не смогут, а остальные данные, например информацию о платежах, о состоянии счета, личную переписку с другими пользователями и т.д пусть снифят?
Думаю, Вы уже понимаете, что конкурентов у HTTPS просто нет на данный момент.
Вадим Т.
3240 сообщений
#15 лет назад
Цитата ("Lisio"):
Если сайт не может окупить стоимость ssl, то и ролики к костылям приделывать смысла нет.

Согласен.

Для тех, кто не хочет самостоятельно сертификат себе генерить (чтобы браузер не выводил окошко про незнакомый сертификат), но в то же время являющихся любителями халявы, есть и другой вариант.
Центры, выдающие сертификаты, часто имеют триал, обычно месяц, но бывает и до 90 дней.
То есть можно потратить час, и все свои сайты снабдить фирменными сертификатами, которые до трех месяцев будут валидны. Через 2.5 месяца операцию повторить... Да, напрягает, но человек же сам себе выбрал бесплатный путь.
Ну ладно, это баловство все.

В общем, если делаете что-то серьезное, то имеет смысл потратить несколько десятков долларов на сертификат. А если что-то несерьезное, то IMHO лучше сгенерить самому, бесплатно конечно.
Игорь З.
29 сообщений
#15 лет назад
По поводу генерации своего сертификата - минус именно в запросах браузера. 90 дней - это конечно на практике не дело.
А вот из местной локалки зайти или с того же прокси по сессии сможет, это согласен.
По поводу остальных данных - проснифить их конечно сможет, но что-то сделать (например, перевести деньги) уже нет. Если только конечно не из локалки или с того же прокси потом не зайдет.

Но в целом конечно понятно, что нужно использовать https. Другое дело, что это не несколько десятков долларов. Например, сертификат Thawte стоит на 1 год 149$. Умножаем примерно на 10 сайтов и получаем уже кругленькую сумму, которую нужно отстегивать каждый год.
Роман Беляев
16382 сообщения
#15 лет назад
tri777ki, если ваш сайт за год не окупает сертификат, то может ну его?
Игорь З.
29 сообщений
#15 лет назад
Frig,
Тут дело не столько в том, окупает ли сайт сертификат, а скорее в том, возможно ли создать относительно защищенную систему без использования сертификата. Т.е. систему, которую можно было бы при необходимости поставить и на 100 сайтов, которая бы на практике нормально работала.
Хотя раз такую систему, похоже, никто еще не создал, то выбор, наверное, прост - или https или ну его нафиг
Евгений Б.
5330 сообщений
#15 лет назад
Цитата ("tri777ki"):
Тут дело не столько в том, окупает ли сайт сертификат, а скорее в том, возможно ли создать относительно защищенную систему без использования сертификата. Т.е. систему, которую можно было бы при необходимости поставить и на 100 сайтов, которая бы на практике нормально работала.
Хотя раз такую систему, похоже, никто еще не создал, то выбор, наверное, прост - или https или ну его нафиг

делов то, собрать все параноидальные техники слежения за IP, куками, параметрами браузера, разрешением экрана и т.п. тогда сервант будет ломиться только от одного слежения, зато клиент чихнет лишний раз и снова логиниться надо будет
Роман Беляев
16382 сообщения
#15 лет назад
Цитата ("tri777ki"):
Тут дело не столько в том, окупает ли сайт сертификат, а скорее в том, возможно ли создать относительно защищенную систему без использования сертификата. Т.е. систему, которую можно было бы при необходимости поставить и на 100 сайтов, которая бы на практике нормально работала.


относительно чего?

Цитата ("ArtPro"):
делов то, собрать все параноидальные техники слежения за..

и в итоге келоггер на клиенте все равно все похерит
Вадим Т.
3240 сообщений
#15 лет назад
Цитата ("tri777ki"):
По поводу остальных данных - проснифить их конечно сможет, но что-то сделать (например, перевести деньги) уже нет. Если только конечно не из локалки или с того же прокси потом не зайдет.

Ну, смотря как оплата производится. Если там номер кредитки будет передаваться в открытом виде, то и денег с нее хакер сможет снять.
К тому же есть и личные данные, которые тоже не желательно знать кому попало — например номер паспорта, домашний адрес, личная переписка с другими пользователями или даже почта, и т.д. В общем, это от проекта зависит, смотря какие данные хранятся... просто подумайте, будут ли счастливы пользователи, если их приватные данные попадут в чужие руки?

Цитата ("frig"):
и в итоге келоггер на клиенте все равно все похерит

В данном случае обычного снифера в локалке достаточно. Бывает, таким балуются работающие у провайдеров малолетние админы. Одно время назад я общался с таким админом в Харькове, который рассказывал смешные моменты из перехваченных емейлов. Хобби у него было такое, приходит на работу, и начинает чужие емейлы читать. На мои недоуменные вопросы о моральной стороне отвечал, мол, а что тут такого?
Николай Т.
205 сообщений
#15 лет назад
Цитата ("tvv"):
Если там номер кредитки будет передаваться в открытом виде, то и денег с нее хакер сможет снять.

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

Цитата ("tri777ki"):
Тут дело не столько в том, окупает ли сайт сертификат, а скорее в том, возможно ли создать относительно защищенную систему без использования сертификата. Т.е. систему, которую можно было бы при необходимости поставить и на 100 сайтов, которая бы на практике нормально работала.

можно, но стоимость разработки такой системы будем во много раз дороже покупки сертификатов на 10 лет на 100 сайтов.

раз уж так хочется экономить - то покупается технический домен и сертификат к нему... и уже на этом домене настраивается оплата/работа с личными данными
Роман Беляев
16382 сообщения
#15 лет назад
Цитата ("tvv"):
В данном случае обычного снифера в локалке достаточно.


мне кажется, что не так все просто со сниффером будет. Даже более того, кажется, что сниффер не поможет. Вот например при входе
- от сервера получаем строку (уникальная, посылается один раз)
- на клиенте делаем md5(строка+md5(пароль))
на сервере у нас в базе md5(пароль), например. На сервере мы можем сделать тоже самое (md5(строка+md5(пароль))) и проверить факт наличия пароля у пользователя, т.е. если строки на выходе совпадают - пользователя авторизируем. Перехват строки от сервера ничего не даст, так как для входа еще нужен корректный пароль или md5 пароля, перехват отправляемой клиентом строки тоже ничего не даст, так как сервер повторно такую строку высылать не будет, она на один раз. Сначала вообще думалось в сторону симметричного шифрования - шифруем паролем строку и шлем серверу, но принцип тот же самый. Да, в данном месте есть уязвимость при краже базы - для входа достаточно хранимого в базе значения, но можно подумать и в эту сторону :-)
Ававав А.
85 сообщений
#15 лет назад
frig, речь идет о перехвате сессии, а не об авторизации/аутентификации.
Вадим Т.
3240 сообщений
#15 лет назад
Оффтопик
Цитата ("e1it3"):
номер кредитки без cvv2 кода ничего не даст, хотя в любом случае такие данные нужно передавать шифрованными

Это в России так, и в ряде европейских стран.
А например в США проверка CVV2 при онлайн платежах не является обязательной.
То есть хакеру достаточно увести номер кредитки и дату, и потом он сможет отовариться где-то в американском или японском интернет магазине.

Так что кража номера кредитки, даже без CVV2 — катастрофа для пользователя.
Алексей М.
1 сообщение
#15 лет назад
Цитата ("tvv"):
Одно время назад я общался с таким админом в Харькове

Вот блин
Уже и в Харькове снифят траф
Вадим Т.
3240 сообщений
#15 лет назад
Цитата ("frig"):
мне кажется, что не так все просто со сниффером будет. Даже более того, кажется, что сниффер не поможет. Вот например при входе
- от сервера получаем строку (уникальная, посылается один раз)
- на клиенте делаем md5(строка+md5(пароль))
...
перехват отправляемой клиентом строки тоже ничего не даст, так как сервер повторно такую строку высылать не будет, она на один раз.

Да, пароль можно защитить, я же не спорю.
Но так как пароль только на один раз, как потом будет отслеживаться пользовательская сессия? Правильно, через сессионную куку. Вот ее-то и можно перехватить снифером, если она не защищена. Затем записать куку в свой браузер, и все — хакер, находящийся в локалке пользователя, уже в сессии пользователя на ресурсе.