Назад в библиотеку
УДК 004.056.53

Cравнительный анализ и выбор алгоритмов хеширования для организации парольной защиты игровых приложений

Н.Е.Губенко, А.В.Сирант

Донецкий национальный технический университет, г. Донецк кафедра компьютерного моделирования и дизайна

an147job@gmail.com

Н.Е.Губенко, А.В.Сирант. Сравнительный анализ и выбор алгоритмов хеширования для организации парольной защиты игровых приложений. Рассматриваются проблемы защищенности игрового веб-приложения. Был проведен анализ существующих решений для парольной защиты с учетом существующих видов атак.

Ключевые слова: криптография, хеширование, кибер-безопасность, игровое приложение, веб-приложение.

Постановка проблемы

Современная игровая индустрия занимает значительный сегмент рынка программных продуктов и является потребителем и стимулятором графических систем. Создателям цифровых видео-игр постоянно приходится сталкиваться с читерством, которое базируется на взломе исходного кода игры (например, путем реверсного инжиниринга) либо других ее составляющих. При этом четко прослеживается закономерность: чем популярнее игровое приложение, тем больше шансы быть взломанными [1]. Продажа читов к играм является целым подпольным бизнесом, ведь каждый хочет получить игровое преимущество, которое легально можно получить только за реальные деньги (имеются в виду игры, распространяемые по модели «free to play»).

Другая проблема состоит в защите данных каждого конкретного пользователя, в распоряжении которого может находиться собственное «цифровое имущество». Этой проблеме уделяется в данной статье основное внимание.

Анализ существующих видов атак.

Проведем анализ различных атак на пользовательскую базу данных. Согласно принципу Керкгоффса [2] при оценке надёжности криптосистемы необходимо предполагать, что злоумышленник знает об используемой системе шифрования всё, кроме ключей. В данном случае ключами являются пароли пользователей, которые хранятся в виде хешей, а сама СУБД, соответственно, была взломана и база данных целиком попала к злоумышленнику.

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

Взлом пароля с помощью атаки по словарю и brute-force атаки

Рисунок.1. Взлом пароля с помощью атаки по словарю и brute-force атаки.

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

Взлом пароля с помощью заранее созданной таблицы хешей

Рисунок.2. Взлом пароля с помощью заранее созданной таблицы хешей.

Похожий метод взлома называется обратным поиском по таблице. Это очень эффективный метод при больших объемах пользовательской БД. Эта атака позволяет злоумышленнику применять метод перебора паролей ко множеству хешей одновременно. Сначала создается поисковая таблица, где в соответствие каждому возможному значению хеша ставится один или более пользователей, имеющие данный хеш. Затем злоумышленник перебирает все возможные варианты пароля, хеширует их и делает поиск пользователей с таким же значением хеша. Данная атака продемонстрирована ниже на рис. 3. Эффективность данной атаки еще выше из-за того факта, что несколько пользователей в большой БД обычно могут иметь один и тот же пароль.

Взлом пароля методом обратного поиска

Рисунок.3. Взлом пароля методом обратного поиска.

Последний, наиболее изощренный и прогрессивный способ взлома – это использование так называемых радужных таблиц [3]. Радужная таблица является вариантом обычной таблицы поиска, но хранит в себе цепочки хешей, полученные с помощью чередования функции хеширования со специальной функцией редукции. Данный метод замедляет поиск совпадений в хеше, так как многие элементы таблицы приходится вычислять динамически. Плюс данной таблицы в снижении требования на необходимую память: при объёме для обычных таблиц в N слов для радужных нужно всего порядка N в степени 2/3. Уже существуют таблицы, позволяющие легко взломать любой пароль длиной до 8 символов, зашифрованный при помощи хеш функции MD5 [4].

Анализ объекта защиты и выбор инструментов для обеспечения безопасности

Остановимся подробнее на особенностях данных, которые необходимо шифровать для собственно разработки многопользовательской игры. При ее создании была использована СУБД MongoDB. Все объекты хранятся в БД в виде JSON-объектов, и они не обязательно должны иметь одинаковый размер, что добавляет гибкости при дальнейшей разработке приложения. В базу данных при регистрации нового пользователя заносится новый объект, содержащий хеш пароля, так называемую соль (затравку для функции хеширования) и токен пользователя – еще один хеш. Запись структуры данных показана ниже на рис. 4.

			{
			    "_id": {
			        "$oid": "58d153bcc2ef165bbfc76b8d"
			    },
			    "name": "MyPasswordIs1111",
			    "nickname": "MyPasswordIs1111",
			    "passwordHash": "3b780f6d2ede6ed47a8897c8031885b21e73b7f63ea5e036997f7f17b68a398c",
			    "r": "cEtRWW18uznbZ5WTWWjHw2f0O00XjawxTj623i6pMe3djNJUN5GtcgdDX1Bzw2Qf",
			    "token": "$2y$14$k4t2RZU0DVv5MG3czFEjgeodyCV2uL3KuagkOc01F/ZdpP1shCEAW",
			    "id": 6,
			    "survey": {
			        "e-mail": "an147job@gmail.com",
			        "age": 0,
			        "gender": "",
			        "source": ""
			    },
			    "registerDate": "2017-03-21 19:24:27"
			}
		

Рисунок.4. Структура данных о пользователе игрового приложения.

Как можно увидеть из рис. 4, основаная информация о пользователе это логин, электронный адрес почты, хэш пароля (элемент passwordHash) , соль хеша пароля (элемент r) и токен (элемент token).

Рассмотрим на этом примере, как сделать криптографически стойкое хеширование паролей. Согласно множеству источников [4,5] MD5 и SHA1 уже изжили свой век и не являются достаточно криптостойкими функциями хеширования. SHA2 «на очереди», однако, для простоты и скорости вычислений при авторизации пользователей был выбран именно этот алгоритм. Именно этим алгоритмом хешируется пароль пользователя при регистрации и каждый раз при попытке авторизации. Возможно, он будет заменен на более надежный и медленный алгоритм в дальнейшем. Однако, также намного более криптостойким хэш делает использование затравки.

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

Хеши сообщения hello без затравки и с разными затравками

Рисунок.5. Хеши сообщения hello без затравки и с разными затравками.

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

Типичные ошибки при работе с затравками это использование одной и той же затравки и использование слишком короткой затравки. В первом случае смысл использования затравки в целом пропадает, во втором – злоумышленник все же может построить таблицы для всех возможных значений слишком короткой затравки. Например, если в затравке всего 3 ASCII символа, то имеется всего 95*95*95 = 857,375 возможных комбинаций. На первый взгляд это очень много, но если каждая таблица содержит около 1 Мб наиболее часто используемых паролей, то в сумме они займут 836 Гб. Это не так уж и много, если учесть, что сегодня можно приобрести жесткий диск на 1Тб по цене дешевле 100$.

Для генерации случайных строк, как, собственно, для генерации любых случайных значений для криптосистемы, нужно пользоваться криптостойкими псевдогенераторами чисел, чтобы последовательность случайных величин была непредсказуемой, иначе криптостойкость системы падает. Такие генераторы можно найти в свободно распространяемых библиотеках на любом языке, например, в PHP 7 уже встроена функция random_int [6].

Стоит также отметить, что затравку как таковую нет смысла шифровать или прятать, это только усложнит процесс аутентификации пользователей с точки зрения приложения.

Для повышения уровня защищенности при использовании пары «логин - пароль» в веб-запросах в разрабатываемом игровом приложении, было решено создавать для каждого пользователя по токену. Токен в данном конкретном случае – это зашифрованная пара: логин и хеш пароля.

При этом возникает проблема, которая заключается в том, что приложение использует RESTful API для обращения к серверам с БД. Одно из требований RESTful API – это независимость от состояния, согласно источнику [7]. Таким образом, невозможно ввести понятие сессии, и приходится передавать данные для идентификации пользователя каждый раз при новом запросе к БД. Это обыденная практика для современных облачных сервисов. При регистрации пользователю выдается специальный хеш – секретный API ключ, который не следует разглашать. Этот ключ используется в каждом запросе к сервису, таким образом идентифицируя клиента. Пример подобного ключа можно увидеть ниже на рис. 6.

Ключ для идентификации клиента API веб-сервиса Page2Images

Рисунок.6. Ключ для идентификации клиента API веб-сервиса Page2Images

Самый простой способ сделать RESTful запросы безопасными – использовать защищенное соединение [8]. В разрабатываемом игровом приложении это, конечно, обязательный пункт. Однако SSL/TLS не является панацеей, поэтому были предприняты дополнительные меры по безопасности, а именно передача токена вместо пары «логин-хеш пароля». При запросе к серверу в БД пользователей ищется пользователь с таким же токеном, и если он найден, то этот запрос идет от имени конкретного пользователя. Таким образом, даже если HTTPS запрос к RESTful API будет расшифрован при перехвате сообщения, злоумышленнику придется расшифровывать токен, чтобы иметь доступ к логину и хешу пароля. В целях безопасности токен создается лишь единожды при регистрации пользователя, и не меняется при смене пароля, следовательно, нельзя будет сделать запрос на присвоение токена определенному пользователю.

Так как операция хеширования (создания) токена проводится единожды, есть смысл применить более тяжелые современные алгоритмы хеширования, которые применяют технику «key stretching». Согласно [9], данная техника призвана сделать любой даже самый слабый пароль более криптостойким просто увеличив время на хеширование.

Рассмотрим данную технику на примере алгоритма bcrypt, который был выбран для создания токенов. Данный алгоритм принимает целочисленный аргумент, который отражает количество итераций алгоритма хеширования. Количество итераций получается возведением двойки в степень аргумента N, т.е. 2N. Этот алгоритм адаптируется под любые нужды, например, при создании токена было задано достаточно большое количество итераций, 214 = 16384 итерации. Данную цифру можно изменять в зависимости от нагрузки на сервер, чтобы при регистрации множества пользователей не страдала производительность [10]. Например, если приложение весьма популярно и в секунду регистрируется 10 пользователей, то есть смысл подобрать такое количество итераций, чтобы хеширование занимало 100 мс.

Для создаваемого игрового приложения, с учетом его популярности, на сегодня достаточно оставить время хеширования в пределах 0.5 секунды. Для злоумышленника, перебирающего все возможные пароли, время отводимое на перебор будет просто неприемлемым, даже если у него в десятки раз мощнее оборудование. Действительно, если пароль состоит из всего четырех ASCII символов, имеется 2564 = 42,949,967,296 комбинаций. Допустим, злоумышленник располагает аппаратными ресурсами в 100 крат мощнее, чем веб-сервер, на котором происходит формирование токена, тогда каждая попытка займет около 5 мс. Для перебора всех возможных вариантов ему потребуется 21,474,836 секунд, или 248,5 суток (8 месяцев). При использовании трех символов перебор возможен немного менее, чем за сутки, поэтому минимальную длину пароля следует строго ограничивать.

Кроме рассмотренного алгоритма были проанализированы алгоритмы PBKDF2, crypt и scrypt, и оценена целесообразность их применения. Эти алгоритмы также используют технику key stretching. Однако, bcrypt немного лучше того же PBKDF2 по той причине, что рассчитан на использование злоумышленником графического процессора (GPU), который в некоторых случаях может давать прирост по сравнению с CPU в несколько десятков раз. Bcrypt настроен на обращения к таблице подстановок, которая постоянно меняется во время выполнения алгоритма, тем самым заставляя все ядра GPU конкурировать за общую память в шине [11]. Отсюда следует, что прирост производительности от использования GPU не будет таким огромным.

Формирование политики безопасности

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

Политика парольной защиты игрового приложения основывается на рекомендациях, приведенных в [4]. При попытках авторизации целесообразно не делать разделения на ошибку в логине и ошибку в пароле, а рассматривать их как единую пару. Не имея на руках БД пользователей, злоумышленник не сможет через интерфейс перебором подобрать логин и пароль [4]. Политика восстановления пароля должна быть основана на временных токенах. При получении письма, пользователю должна быть предоставлена ссылка с данным токеном, где он может поставить себе новый пароль. Рекомендуется привязывать токен к конкретному аккаунту, чтобы злоумышленник не мог имея на руках «свой» токен поменять чужой пароль. Время действия токена должно истекать в течение 15 минут со времени запроса на восстановление пароля. Также токен должен аннулироваться, когда данный пользователь авторизовался в системе (он вспомнил пароль). В токене не должна быть отражена информация о таймауте и прочие параметры, необходимые системе, так как злоумышленник будет способен заменить данные параметры на нужные. Никогда не следует посылать новый пароль пользователю по почте. Также нужно использовать новую затравку для хеширования нового пароля.

Выводы

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

Литература

  1. «Борьба с читерами в онлайн-играх: 22 «нужно» и «нельзя»» // Habrahabr. [Электронный ресурс]. Режим доступа: https://habrahabr.ru/post/320602/
  2. «Kerckhoffs's principle» // Wikipedia. [Электронный ресурс]. Режим доступа: https://en.wikipedia.org/wiki/Kerckhoffs's_principle
  3. «Rainbow table» // Wikipedia. [Электронный ресурс]. Режим доступа: https://en.wikipedia.org/wiki/Rainbow_table
  4. «Salted Password Hashing - Doing it Right» // CrackStation. [Электронный ресурс]. Режим доступа: https://crackstation.net/hashing-security.htm
  5. «Why not use MD5 for password hashing?» // StackOverflow. [Электронный ресурс]. Режим доступа: http://stackoverflow.com/questions/30496061/why-not-use-md5-for-password-hashing
  6. «PHP 7 Documentation: random_int» // PHP.net. [Электронный ресурс]. Режим доступа: http://www.php.net/random_int
  7. «RFC 7235. Hypertext Transfer Protocol (HTTP/1.1): Authentication» // IEFT.org. [Электронный ресурс]. Режим доступа: https://tools.ietf.org/html/rfc7235#section-4.
  8. « How do I secure my REST API? » // security.stackexchange.com. [Электронный ресурс]. Режим доступа: https://security.stackexchange.com/questions/19930/how-do-i-secure-my-rest-api
  9. «Key stretching» // Wikipedia. [Электронный ресурс]. Режим доступа: https://en.wikipedia.org/wiki/Key_stretching
  10. «Recommended # of iterations when using PKBDF2-SHA256?» // security.stackexchange.com. [Электронный ресурс]. Режим доступа: https://security.stackexchange.com/questions/3959/recommended-of-iterations-when-using-pkbdf2-sha256/3993#3993
  11. «Do any security experts recommend bcrypt for password storage?» // security.stackexchange.com. [Электронный ресурс]. Режим доступа: https://security.stackexchange.com/questions/4781/do-any-security-experts-recommend-bcrypt-for-password-storage?rq=1

Назад в библиотеку