Статья - Безопасность при аутентификации (идентификации) пользователя в приложениях

  Вход на форум   логин       пароль   Забыли пароль? Регистрация
On-line:  

Раздел: 
Форум сайта http://tonnys.kiev.ua / FAQ, статьи, заметки / Статья - Безопасность при аутентификации (идентификации) пользователя в приложениях

Страницы: 1  новая тема

Автор Сообщение

Группа: Администраторы
Сообщений: 56
Добавлено: 08-09-2006 12:38
Безопасность при аутентификации (идентификации) пользователя в приложениях

При разработке какой-либо многопользовательской программы одна из основных её составляющих - система аутентификации пользователя. Обычно особого внимания этой сисеме не уделяется, так как есть более важные задачи, поэтому система безопасности остаётся в "зачаточном" состоянии (о чём менеджеры клиенту, конечно же, не рассказывают).
В общем случае система аутентификации - это комплекс, состоящий из следующих основных элементов:
- Операционная система
- Система защиты Приложения
- Сетевая и Антивирусная защита
- Организационные меры

Нас интересует "наша" часть - система защиты приложения.

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

Выводы: если пользователь (в частном случае администратор) может работать в системе под чужой учётной записью, он может совершить действия, ответственым за которые будет хозяин учётной записи.

Варианты: а) хозяин учётной записи сам сообщил ключ (пароль) другому пользователю. Таким образом, сознательно или нет, он взял на себя ответственность за чужие действия в программе. Данный вопрос решается организационными мерами и здесь не рассматривается.

б) чужой ключ (пароль) был получен помимо желания хозяина, который при этом остаётся в неведении. Получить пароль можно различными способами:
- подсмотреть на бумажке, куда пользователь его записал (в записной книжке, в телефоне, подсмотреть в момент набора пароля пользователем и т.п.). Организационная ошибка.
- заполучить пароль с помощью вирусов, троянцев (кейлоггеров). Скопировать ключ с носителя с помощью удалённого доступа. Ошибки системного администрирования и антивирусной безопасности.
- получить пароль (ключ) пользователя непосредственно из приложения (из файлов, базы данных и т.п.). Ошибки разработчиков.

Наша задача - минимизировать возможность получения подобных данных из приложения.
В "Общих моментах" кажущееся противоречие между п.1 и п.2 устраняется шифрованием и его вариациями. Для разработчика, не имевшего дело с шифрованием, есть полный интернет всевозможных алгоритмов, от простейших до вошедших в стандарты. Но, учитывая обширность темы, некоторые "тонкие" моменты упускаются.
Пример: пароль пользователя шифруем и сохраняем в файле данных приложения (или базе данных). Вроде бы всё хорошо, пароль зашифрован, просто так не подсмотришь.

Тонкие моменты:
1. (основной) используется постоянный ключ шифрования. Приложению приходится сохранять где-либо ключ чтоб расшифровать пароль и сверить его с введённым пользователем.

2. Алгоритм шифрования. Простой алгоритм может быть вскрыт даже наугад, а чуть более сложные - перебором. Мощность современных машин позволяет перебирать сотни тысяч - миллионы вариантов в простых алгоритмах.
Основные алгоритмические ошибки:
1) по криптотексту (в данном случае - зашифрованному паролю) можно определить размер открытого текста. Для крупных блоков открытого текста это не важно, но для пароля его длинна - это часть информации о нём.
2) в пароле можно подбирать каждый символ отдельно от других. Подсмотрев (или предположив) какой-либо нажатый пользователем символ (или несколько) можно начать подбор всего пароля.
Определив алгоритм шифрования пользователь получает доступ ко всем учётным записям.

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

4. Полученный пароль пользователя может совпадать (и часто совпадает) с паролем к другим системам (приложениям). Таким образом, под угрозой оказывается не только приложение, из которого пароль извлечён.

5. Разработчику известен ключ и алгоритм шифрования, таким образом, разработчик может узнать пароль любого пользователя.

Решение.
Первый вопрос: а зачем приложению знать пароль пользователя? Если у разработчика такого вопроса не возникло, значит он ничего не читал про идентификацию пользователей, например, в операционных системах.

Ответ: приложению не нужен пароль. Ему нужно быть уверенным, что учётная запись принадлежит именно пользователю, логин (имя) которого использован. Ещё в системе UNIX для этого используется гениальное по простоте решение - система хранит Хэш пароля пользователя. Хэш - односторонняя и однозначная функция. Она не позволяет никаким образом расшифровать пароль, тем не менее каждому паролю соответствует уникальное значение хэша.

Таким образом, простейший вариант идентификации пользователя:
1. клиентская часть:
- пользователь вводит логин и пароль
- клиентская часть приложения вычисляет хэш-функцию введённых данных и отправляет на сервер пару логин (имя) + хэш
2. сервер сравнивает присланный хэш и хэш сохранённый в карточке пользователя и принимает решение об идентичности.

В операционных системах используются более сложные, многоступенчатые схемы, призванные защитить от перехвата сетевого траффика.
Но даже эта простейшая схема уже избегает всех недостатков, описанных в "Тонких моментах".

Вскрыть хорошо написанную хэш-функцию (примеров в интернете огромное множество, есть стандартные, проверенные временем и т.п.) можно только полным перебором вариантов, причём пароль нельзя перебирать по частям - хэш-функция зависит от каждого символа пароля.

Чтоб затруднить перебор вариантов, следует выбирать длинну хэш-значения достаточно большой. Таким образом будет значительно увеличено количество операций на его вычисление, что будет не заметно при разовых вычислениях в приложении, но очень повлияет на скорость перебора вариантов при подборе. На современных системах хранение для каждого пользователя даже килобайтного хэша - это пренебрежительно малые затраты. Хотя слишком увлекатся не стоит, просто нет смысла.

Можно предположить, что хэш длинной 100 - 1000 байт будет достаточен для большинства приложений.

Практические моменты.

1. Хэш-функцию можно реализовать на основе алгоритма шифрования. Достаточно, чтоб хешируемый пароль содержался как в ключе шифрования, так и в самом шифротексте, т.е. если есть функция вида Шифр(ключ-шифрования, текст-который-надо-зашифровать)
то Хэш = Шифр(пароль, пароль)
получим криптотекст, для расшифровки которого надо знать сам открытый текст, который хорошо подходит в качестве хэш-функции.

Тонкий момент: у разных пользователей с одинаковыми паролями будет одинаковый хэш. Чтоб этого избежать, используются уникальные для пользователя модификаторы. Например, в UNIX использовались два случайно сгенерированных байта, которые хранились вместе с хэшем.
Можно пойти по примеру UNIX, а можно использовать что-либо уникальное для пользователя, например, его логин или системный номер.
Например:

Хэш = Шифр(логин+пароль, логин+пароль)

или

Хэш = Шифр(номер_пользователя+пароль, номер_пользователя+пароль)

Варианты (главное, чтоб пароль участвовал в как в ключе так и в шифруемом тексте):

Хэш = Шифр(пароль, логин+пароль)
Хэш = Шифр(логин+пароль, пароль)


2. Вопрос: А если надо сохранить в приложении именно логин и пароль, а не их хеш? например, для доступа к серверу баз данных?
Ответ: Тогда шифровать.
Помнить следующие моменты:
- приложение расшифровывает данные один раз, переборщик - миллионы раз. Не жадничайте на длинну криптотекста, храните логин с паролем (десятки байт) в файлах, длинной в килобайты.
- лучше, конечно, шифровать нефиксированным ключём, например, пользователь вводит какой-либо пароль, а уже этим паролем расшифровывается истинный логин и пароль для доступа к серверу баз данных. Таким образом, пользователь может и не знать паролей доступа к серверу, что исключает возможность работы с БД в обход приложения.

Пример аутентификации для двухуровневой системы Приложение - сервер БД

Сервер БД: имеется одна или несколько заведённых учётных записей, предназначенных для подключения к серверу приложения
Приложение: имеется большое количество пользователей. Они работают через одинаковые учётные записи сервера БД, но разные учётные записи Приложения.

Идентификация и начало работы:
1. Старт приложения: пользователь вводит Логин и Пароль учётной записи Приложения.
2. Приложение по Логину считывает профайл пользователя, в котором содержится информация учётной записи БД (его можно хранить как в общедоступном файле, так и в БД с открытым доступом), расшифровывает его по Логин+Пароль пользователя и получает Логин + Пароль учётной записи сервера БД.
3. Приложение соединяется с БД по полученым данным.
4. Приложение считывает профиль пользователя, выполняет дополнительные проверки, например, перепроверяет действительность пары Логин+Пароль пользователя по хэшу.
5. Приложение принимает решение о успешности логина пользователя.

Пример шифрования и хэширования можно
скачать тут (D7)

Вопросы можно попытаться задать: tonnys@ukr.net
© Tonny S. 2006

Страницы: 1  новая тема
Раздел: 
Форум сайта http://tonnys.kiev.ua / FAQ, статьи, заметки / Статья - Безопасность при аутентификации (идентификации) пользователя в приложениях

Отвечать на темы в данном разделе могут только зарегистрированные пользователи

Отвечать на темы могут только зарегистрированные пользователи

KXK.RU