О, вы много чего можете сделать, так что садитесь поудобнее! И приготовьтесь слушать.
Многофакторная аутентификация
Некоторые специалисты по информационной безопасности любят говорить, что парольные технологии умерли и что пользоваться ими вообще не нужно. На деле верно прямо противоположное. Есть три основных класса технологий аутентификации:
□ Что вы знаете. Сюда относятся ПИНы, парольные фразы, в общем, все, что можно охарактеризовать как пароль.
□ Чем вы обладаете. Речь идет о смарт–картах, криптографических маркерах, кредитной карте и т. д.
□ Чем вы являетесь. Это различные виды биометрии.
У каждого подхода есть свои плюсы и минусы. Например, физический предмет, на основе которого производится аутентификация, может быть утерян или украден. Биометрические данные можно похитить и фальсифицировать (например, с помощью искусственного пальца или путем внедрения битов, описывающих отпечатки пальцев, непосредственно в систему). А если ваши биометрические данные похищены, то это катастрофа – ведь изменить–то их вы не сможете!
Можно усилить аутентификацию, объединив все три технологии. Если противник похитит физический предмет, то ему еще предстоит узнать пароль. И даже если беспечная жертва оставит свой пароль под клавиатурой, противнику все же придется преодолеть барьер физического устройства аутентификации.
Подчеркнем, что защита системы усилится, лишь если вы будете учитывать при аутентификации разные факторы. Если же она построена по принципу «или–или», то противнику нужно взломать только самое слабое звено.
Хранение и проверка паролей
Пароли следует хранить в свернутом виде, то есть после применения к ним односторонней функции хэширования, не допускающей обращения. Тогда противник не сможет расшифровать пароль, а вынужден будет пробовать разные комбинации символов, пока не получится тот же результат хэширования. Поэтому нужно сделать все возможное, чтобы усложнить функцию нахождения соответствия.
Стандартный и надежный способ дает алгоритм PBKDF2 (password–based key derivation function, Version 2.0 – функция выработки ключа на основе пароля, версия 2.0). Он описан в документе Public Key Cryptography Standard # 5 (PRCS #5–стандарт криптографии с открытым ключом). Хотя первоначально эта функция разрабатывалась для создания криптографического ключа из пароля, но она хороша и для наших целей, поскольку является стандартной, открытой и удовлетворяет всем выдвинутым требованиям. Она односторонняя, но детерминированная. Можно задать размер результата, так что выбирайте валидаторы длиной не менее 128 битов (16 байтов).
У этой функции есть также особенности, затрудняющие атаку полным перебором. Во–первых, необходимо задать затравку, в качестве которой выбирается случайное значение. Это защищает от атак с предварительным вычислением. Затравка необходима для проверки пароля, поэтому можно хранить ее в составе результата, возвращаемого алгоритмом PBKDF2. Восьмибайтовой затравки достаточно, если она выбрана действительно случайно (см. грех 18).
Во–вторых, можно сделать так, что вычисление результата будет занимать относительно много времени. Идея в том, что законный пользователь введет пароль лишь один раз, так что вполне может подождать одну секунду, пока он будет проверяться. Но если противнику придется ждать одну секунду для каждого варианта, то офлайновая атака с перебором по словарю окажется весьма проблематичной. Управлять временем вычисления можно, задав счетчик итераций, определяющий, сколько раз повторять вызов основной функции. Возникает вопрос: «Так сколько итераций задавать?» Ответ зависит от того, сколько времени вы согласны ждать при использовании самой дешевой из имеющейся у вас аппаратуры. Если алгоритм реализован внутри недорого встраиваемого устройства, то 5000 итераций достаточно (в предположении, что он написан на С или машинном языке; желательно, чтобы алгоритм был реализован максимально эффективно, тогда вы сможете задать большее число итераций). Десять тысяч считается приемлемым значением счетчика в общем случае, если речь не идет о низкопроизводительном встраиваемом оборудовании или машинах 15–летней давности. На современных ПК (класса Pentium 4 и сравнимых с ним) можно говорить о 50–100 тысячах итераций. Чем число меньше, тем проще задача противника. Ведь он–то не ограничен встраиваемым устройством. Конечно, если вы зададите слишком много итераций, а приложение выполняет много операций аутентификации, то его производительность может пострадать. Поэтому начните с высокого значения и займитесь измерениями; не считайте при этом, что единственная причина медленной работы приложения – это большое число итераций.
Отметим попутно, что в API защиты данных (Data Protection API) (см. грех 12) в Windows используется алгоритм PBKDF2 с 4000 итераций, чтобы затруднить задачу противнику, пытающемуся взломать пароль. Ясно, что это значение маловато, если вы собираетесь поддерживать свое приложение на современных ОС, работающих на не слишком старом оборудовании (скажем, последних пяти лет выпуска).
В некоторых библиотеках имеется функция PBKDF2 (но, как правило, старая версия, которая не так хорошо спроектирована). Если же нет, то ее легко построить на базе любой реализации хэшированного кода аутентификации сообщений (НМАС – Hash–based Message Authentication Code). Вот, например, реализация на языке Python, где на вход подаются затравка и счетчик итераций, а полученное на выходе значение можно использовать в качестве валидатора пароля: