Аннотация

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

В данной статье автором осуществляется фундаментальный обзор актуальных на сегодняшний день алгоритмов аутентификации пользователей, а также производится разбор и оценка возможности их применимости в контексте инфраструктурного подхода Нулевого Доверия (англ. Zero-Trust).

Что такое аутентификация?

«Куда бы тебя жизнью не заносило, ты — это ты. Со своими проблемами, со своими способностями, единственный и неповторимый.»

© Харуки Мураками, 1Q84

Первостепенными объектами рассмотрения, требующими максимально точной и исчерпывающей формулировки, являются понятия Аутентификации и Двухфакторной Аутентификации. Приведём первое из определений, ссылаясь на основной нормативно правовой документ Российской Федерации, устанавливающий стандарты управления доступом ГОСТ Р 58833-2020.

Аутентификация (установление подлинности) - Действия по проверке подлинности субъекта доступа и/или объекта доступа, а также по проверке принадлежности субъекту доступа и/или объекту доступа предъявленного идентификатора доступа и аутентификационной информации. Иными словами, в процессе классической аутентификации, можно выделить два этапа:

  1. Субъект доступа, в частном случае, пользователь, предъявляет свой уникальный идентификатор и аутентификатор (набор аутентификаторов) сервису проверки (аутентификации).

    [ В роли идентификатора может выступать логин, а в роли аутентификатора пароль]

  2. В случае существования информации о таком идентификаторе и соответствующем ему аутентификаторе (наборе аутентификаторов), в базе данных сервиса, в качестве ответа, сервис аутентификации, присваивает или не присваивает предоставленной пользователем информации статус достоверной

    Математическая интерпретация подобной модели в первом приближении тривиальна:

    Пусть пользователем на вход сервису подается упорядоченный набор из одного, уникального идентификатора  ID и n аутентификаторов, обозначим i-й аутентификатор такого набора Au_i. Тогда вся входная цепочка будет иметь вид:

    CHAIN =  ( ID, ..., Au_1, ..., Au_i, ...,  Au_n)

    В то же время, она может быть представлена в виде:

    CHAIN =  (ID, X)

    Где за X = (Au_1, ..., Au_i,..., Au_n) обозначим набор из nаутентификаторов.

    Пусть имеется реестр идентификаторов и аутентификаторов на стороне сервиса, он представляет собой матрицу размером (k \times n+1) , где n- число аутентификаторов в наборе, необходимых для прохождения процедуры проверки, k - число зарегистрированных в реестре аккаунтов.

    \left(\begin{matrix}ID_1^{\prime}&Au_{11}^{\prime}&...&Au_{1i}^{\prime}&...&Au_{1n}^{\prime}\\ ...&...&...&...&...&...\\ ID_j^{\prime}&Au_{j1}^{\prime}&...&Au_{ji}^{\prime}&...&Au_{jn}^{\prime}\\ ...&...&...&...&...&...\\ ID_k^{\prime}&Au_{k1}^{\prime}&...&Au_{ki}^{\prime}&...&Au_{jn}^{\prime}\end{matrix}\right)\

    ­Тогда для каждой цепочки, введённой пользователем, сервис осуществит проверку путём поиска значения IDсреди значений идентификаторовID_j^{\prime} путем перебора по индексам j, и в случае, если такой j будет найден, проверит соответствующие этому j значения аутентификаторов Au_{ij}^{\prime} на предмет совпадения с аутентификаторами цепочкиAu_i.

    Рассмотрим отображение, действующее из множества идентификаторов и аутентификаторов в множество дискретных значений.

    \begin{array}{l}F\ (ID\ ,\ Au_{1\ },\ ...\ ,\ Au_i\ ,\ ...\ ,\ Au_n)\ =\ F\left(ID,\ X\right)\ =\ \\ \\ =\begin{cases}1\ if\ \exists j\in\left[1,...,k\right]:\ \left[ID_j^{\prime}=ID\right]\&\\ \&\left[\forall Au_i\in X\ \to Au_i=Au_{ji}^{\prime}\right]\\ \\ 0\ if\ \forall j\in\left[1,...,k\right]\to\left[ID_j^{\prime\ }\ne ID\right]or\\ or\left[\exists\ Au_i\in X\ :\ Au_i\ne Au_{ji}^{\prime}\right]\end{cases}\end{array}

Будем называтьF(ID, X)  – функцией аутентификации, заметив, что:

D\left(F\right)\ =\ \left\{0\right\}\cup\left\{1\right\}\

Отметим, что аутентификаторы не передаются субъектом и не хранятся в первозданном виде на стороне сервиса – в обоих случаях применяется процедура хеширования.

Хеширование на стороне субъекта делается это для того, чтобы:

  • В случае компрометации сервиса, злоумышленники не могли получить доступ к аутентификаторам в явном виде

  • Сам сервис не мог воровать пароли

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

Дополним сказанное некоторыми необходимыми пояснениями:

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

Во-вторых, не следует путать Аутентификацию с Авторизацией, приведём недостающее определение из уже упомянутого выше ГОСТ Р 58833-2020.

Авторизация (санкционирование доступа) - предоставление субъекту доступа прав доступа, а также предоставление доступа в соответствии с установленными правилами управления доступом.

Таким образом, авторизация представляет собой непосредственно выдачу прав на доступ к интересующему субъекта ресурсу. Процесс авторизации использует факт установления подлинности, являющийся результатом процесса аутентификации как “отправную точку” при дальнейшем принятии решения о выдаче разрешения на работу с платформой, порталом или приложением.

Для большей наглядности приведём иллюстрацию, описывающую сказанное выше:

Канарейка проходит через все необходимые этапы для получения прав на работу с платформой
Канарейка проходит через все необходимые этапы для получения прав на работу с платформой

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

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

Предваряя разбор введённого определения, хотелось бы для начала сделать вполне очевидное, но тем не менее необходимое замечание: при использовании стандартной процедуры аутентификации не достаточно сколь угодно много увеличивать число подаваемых на вход аутентификаторов (привычных паролей) так, чтобы в предельном случае i \to \infty . Подобное увеличение массива входных данных будет обеспечивать дополнительную защиту от простейшей атаки методом полного перебора, или его более совершенных вариаций, таких как, например, подбор по словарям, или с использованием радужных таблиц. К тому же, длинную цепочку аутентификаторов необходимо специальным образом генерировать и где-то хранить, наконец, подобный объем аутентификационных данных просто не удобен для использования конечным пользователем, порой испытывающим необходимость осуществлять вход в сервис несколько раз на протяжении дня. Самым же существенным недостатком подобного метода является его неуменьшающаяся, с ростом набора аутентификаторов, уязвимость перед атакой “человек посередине” и компрометацией аутентификационных данных – в том случае если киберпреступнику (кибераналитику после дешифрования) становится известен каждый аутентификатор из набора, он не имеет более препятствий для осуществления авторизации и получения полного доступа к сервису.

Именно ввиду упомянутых выше причин, и возникает необходимость в создании структурно иной процедуры аутентификации, которая, будучи более совершенной, дополняла бы существующий процесс, но не являлась бы его следствием, или предельным случаем. Возникает закономерный вопрос – основываясь на каких данных пользователя, в таком случае, можно создать так называемые дополнительные механизмы или, иначе говоря, “слои” (от англ. layers) аутентификации?

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

Класс 1: [Знание]

Некоторой секретной информации, например пароля или конечного их числа

Класс 2: [Обладание]

Подкласс 1: [Естественное обладание] (постоянная характеристика пользователя, или неизменная на временах порядка нескольких лет, обусловленная его существованием как биологической особи)

Группа 1: [Физиологическое обладание]

  • Отпечатки пальцев и ладоней

  • Сетчатка глаза

  • Распознавание лица

  • Цепочка ДНК

Группа 2: [Естественное поведенческое обладание]

  • Речь/особенности речи, тембр и тональность голоса

  • Походка

Подкласс 2: [Искусственное физическое обладание] (постоянная, или неизменная продолжительное время характеристика пользователя, обусловленная его существованием как социальной особи и наличием у него необходимых атрибутов социализации или принадлежности к определённой социальной группе)

Группа 1: [Физическое обладание]

  • Адрес электронной почты/аккаунты на других ресурсах

  • Смартфон

  • NFC чип в любом из сторонних устройств (пропуск в офис, часы, браслет, кольцо)

  • RFID метка

Группа 2: [Искусственное поведенческое обладание]

  • Характерные паттерны взаимодействия с рабочим пространством (англ. workspace)

В силу исторических предпосылок, в качестве первого фактора аутентификации выбирается [Знание], а конкретно, пароль, в качестве же второго, представляется возможным выбрать любой из подклассов [Обладания] и, как показывает практика, чаще всего, при проектировании инфраструктуры безопасности, выбор падает на [Искусственное обладание] субъекта смартфоном. Стоит отдельно заметить, что этот подход, хоть и может показаться искушённому читателю некоторым компромиссом, (смартфон может с той же вероятностью быть компрометирован, что и устройство, с которого осуществляется вход), тем не менее, имеет под собой фундаментальное основание, в особенности, если речь идет о создании инфраструктуры безопасности внутри организаций большого масштаба, так, например, в случае выбора сканирования сетчатки глаза пользователя, в качестве второго фактора, нам будет необходимо оснастить каждую конечную точку (англ. endpoint) организации компактным и простым в использовании сканером, цена которого, на момент написания статьи, варьируется в диапазоне от 2 500 до 3 000 долларов США, разумеется, в итоге, мы получим высокий уровень безопасности, но достигнут он будет ценой крайне внушительных финансовых затрат.

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

Пусть:

P_{penetration}- итоговая вероятность проникновения в рассматриваемую организацию по произвольному вектору атаки (в качестве подобного вектора данном случае можно рассматривать аутентификацию).

S_{implementation}– совокупная стоимость решения для предотвращения атаки по этому вектору.

Тогда:

P_{penetration\ }\cdot\ S_{implementation\ }\sim\ EFF

Помимо этого,S_{implementation}будет состоять из двух слагаемых: стоимости оборудования (англ. Hardware) и цены программной части вместе с технической поддержкой (англ. Services):

\begin{array}{l}S_{implementation}\ \left(t\right)\ =\ S_{hardware\ }\ +\ S_{services}\ \left(t\right)\ &\\ S_{hardware\ }\ =\ const\ &\\ S_{services\ }\left(t+T\right)\ =\ S_{services}\left(t\right)&\end{array}

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

T  \sim 1 \ year

Объединяя выражения для оценки на показатель получим следующее соотношение:

P_{penetration\ }\cdot\ \left(S_{hardware}\ +\ S_{services}\ \left(t\right)\right)\ \sim EFF\

Поскольку в настоящий момент практически каждый пользователь обладает смартфономS_{hardware}\ \to\ 0\ , то, для построения двухфакторной аутентификации, основывающейся на его использовании, закономерно, будем иметь:

P_{penetration\ }\cdot\ S_{services}\ \sim\ EFF_{smartphone\ }

Как следствие, в случае смартфона, мы получаем более высокое значение для введённого нами показателя эффективности чем, например, для аутентификации с применением сканеров сетчатки:

EFF_{smartphone\ }>\ EFF_{retinascanner}

Следует воздержаться от буквального понимания этого выражения, тем более что на данный момент, практически не существует универсальных алгоритмов для точного установления P_{penetration}, помимо очевидных (статистика по предотвращённым атакам; статистика, полученная в результате пентестов).Более того, величина P_{penetration} индивидуальна для каждой организации и каждого, из возможных, векторов атаки.

Основная мысль, которую упомянутая выше математическая интерпретация ставит своей целью донести – безопасность, предоставляемая тем или иным решением или подходом всегда “напрямую” связана c итоговой его стоимостью внедрения, именно поэтому, в рамках существующих реалий, со стороны рынка информационной безопасности, возникает потребность в создании алгоритмов аутентификации, которые, опираясь на обладание смартфоном в качестве второго фактора, могли бы гарантировать высокую степень защищённости процесса аутентификации в рамках корпоративных сервисов и платформ.

Алгоритмы безопасной аутентификации

«Для чего тебе нужны доспехи, если внутри тебя нечего защищать?»

© Антуан де Сент-Экзюпери, Цитадель

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

1)     При помощи SMS-сообщения:

После ввода пары логин-пароль, открывается вторая форма для ввода, после этого, субъект получает SMS-сообщение, содержащее одноразовый код-пароль, для её заполнения.

2)     При помощи мессенджеров (Telegram, WhatsApp):

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

3)     При помощи алгоритмов HOTP и TOTP:

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

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

Как уже было упомянуто выше, пользователю, до начала использования аутентификации с применением подхода, основанного на HOTP и TOTP, необходимо отсканировать через специализированное приложение QR-код – делается это для того, чтобы максимально удобно передать ему первоначальный секретный ключ (англ. secret), без фактической его отправки по каналам связи (дополнительное увеличение безопасности процедуры), таким образом, после расшифровки QR-кода внутри приложения,  мы имеем синхронизированный secret между сервером аутентификации и мобильным устройством.

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

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

HOTP (HMAC-Based One-Time Password Algorithm)

Перейдем к рассмотрению каждого из алгоритмов в рамках третьего подхода и начать предлагается с более простого – HOTP.

1) Допустим у нас есть синхронизированный secret, он статичен (жёстко закреплён за пользователем), но при этом, каждый раз при аутентификации, мы хотим генерировать “двух сторон” одинаковый новый код-пароль, значит, нам необходимо ввести ещё один параметр генерации – динамический (счётчик от англ. counter) , который, каждый раз изменяясь во времени, тем не менее, оставался бы одинаковым как для пользователя, так и для сервиса, в HOTP, в качестве такого параметра, мы выбираем номер попытки входа в аккаунт за всю историю наблюдений.

2) Конкатенируем Secret\ = const и counter_{HOTP}(n) ,здесь дополнительно подчёркивается, что значения счётчика — это функция от номера попытки, а областью её значений в HOTP является множество натуральных чиселD(counter_{HOTP} (n)) \in N.

При этом, в рамках HOTP, функция счётчика может быть реализована со смещением относительно нуля на некоторую константу, принципиальной разницы это изменение вносить не будет:

counter_{HOTP}(n) = n_0 \ +\ n

Далее, осуществим хеширование объединённой строки:

h\left(Secret\ +\ counter_{HOTP}\left(n\right)\right)\ =\ HASH\ \left(n\right)

Вообще говоря, для хеширования можно использовать самые разные функции, но здесь и далее мы будем рассматривать хеширование, основанное на HMAC SHA-1, таким образом, будем для результата обработки (англ. digest), иметь строку длиной 160 бит:

h\left(Secret\ +\ counter_{HOTP}\left(n\right)\right)\ =\ HASH\left(n\right)\ =\ Digest_{160\ bit\ }\left(n\right)\

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

CUT\left(Digest_{160\ bit\ }\left(n\right)\right)\ =\ Digest_{31\ bit}\ \left(n\right)\

4) После чего, преобразуем нашу строку в число:

NUM\ =\ int\left(Digest_{31\ bit\ }\left(n\right)\right)

Отдельно стоит заметить, что оно, по-прежнему, может оставаться крайне большим, вплоть до:

2^{31\ }=\ 2\ 147\ 483\ 648

Его уже можно вводить непосредственно в форму, однако, предлагается всё же привести его к более удобному виду, путем сравнения по модулю с некоторым\alpha. В данном случае возьмем его равным:

\alpha = 10^6

Тогда получим:

TempPassword_{HOTP}\ =\ NUM\ mod\ \alpha\ =\ int\left(Digest_{31\ bit}\ \left(n\right)\right)\ mod\ 10^6

Это число и будет нашим искомым шестизначным кодом-паролем для удобного ввода в форму.

Приведём возможный пример реализации алгоритма HOTP на языке C# с использованием функций из специализированной библиотеки OTP-Sharp - в данном случае, предлагается, для внесения разнообразия, генерировать восьмизначный код пароль на каждой новой итерации.

       public ActionResult hotp(string button1, FormCollection form)
        {
            ViewData["seed"] = form["seed"];
            string s1 = form["seed"];
            if (s1 == null) s1 = "";
            var topt = new Hotp((System.Text.Encoding.UTF8.GetBytes(s1)));

            if (button1 != null)
            {

                topt = new Hotp((System.Text.Encoding.UTF8.GetBytes(s1)));
                Session["counter"] = 0;

            }


            int counter = (int)Session["counter"];
            ViewData["counter"]=counter++;
            Session["counter"]=counter++;

            var totpCode = topt.ComputeHotp(counter);
            string v = String.Format("{0:00000000}", totpCode);
            ViewData["random"] = v;

            return PartialView("hotp_partial");




        }

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

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

\begin{array}{l}counter_{HOTP_{Service\ }}\left(n\right)\ =\ n_1\\ counter_{HOTP_{Smartphone}}\left(n\right)\ =\ n_2\end{array}\rightarrow\ n_{2\ }\ >\ n_1

Нам известно, что каждому значению счетчика однозначно поставлено в соответствие значение кода-пароля (при этом отображение инъективно, но не сюръективно), начнём постепенно решать возникшую проблему: рассмотрим фиксированный массив, задаваемый параметром \gamma = 5 “на опережение” сгенерированных сервисом кодов-паролей, и назовём этот массив окном предпросмотра (англ. Lookahead window).

Окно предпросмотра, состоящее из пяти наперёд сгенерированных кодов-паролей
Окно предпросмотра, состоящее из пяти наперёд сгенерированных кодов-паролей

Далее, будем осуществлять пошаговую проверку имеющихся кодов внутри окна на предмет соответствия коду-паролю, предоставленному пользователем – в случае успеха, сервис осуществляет “скачок” на это значение и заново формирует окно предпросмотра

Скачок окна предпросмотра
Скачок окна предпросмотра

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

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

TOTP (Time-based One-Time Password Algorithm)

С алгоритмом HOTP мы разобрались, но возникает закономерный вопрос – можно ли изменить динамический параметр генерации (counter) таким образом, чтобы ситуации, требующие прохождения процедуры восстановления (выход пользователя за окно предпросмотра), происходили реже? Разумеется, это возможно.

Нами уже обсуждалось, что значения, выдаваемые счетчиком, представляют собой функцию от времени – просто в алгоритме HOTP мы в качестве её аргумента выбрали номер попытки (формально зависящий от времени).

counter_{HOTP}\ \left(n\right)\ =\ n_{0\ }\ +\ n\

В алгоритме TOTP же, в свою очередь, в качестве аргумента функции счётчика предлагается выбрать непосредственно время, причем в наиболее удобном для этого формате – UNIX.

counter_{TOTP}\ \left(t\right)\ =\ \tau_{UNIX}

Стоит заметить, что несмотря на то, что время UNIX из-за факта наличия високосных секунд не всегда совпадает с привычным для нас временем UTC, оно, тем не менее, с устраивающей нас точностью будет совпадать для сервиса и мобильного приложения аутентификации – этот факт, как раз, и является для нас основополагающим при выборе его в качестве аргумента функции счётчика.

Сделаем еще одно необходимое дополнение – при подобном выборе счётчика мы будем каждую секунду, вместе с изменением времени UNIX, обновлять динамический параметр генерации, получая, как следствие, после прохождения всех шагов алгоритма, новый шестизначный код-пароль – подобного нам хотелось бы избежать, поэтому вместо обычного UNIX-времени, предлагается брать его интервалы длиной по 30 секунд каждый – осуществим это при помощи взятии целой части:

counter_{TOTP}\ \left(t\right)\ =\ \left[\frac{\tau_{UNIX}}{30}\right]

Заметив, что функция в правой части будет возвращать целое число, увеличенное на единицу каждый новый тридцатисекундный интервал, без ограничения общности можем также записать:

counter_{TOTP}\ \left(t\right)\ =\ \left[\frac{\tau_{UNIX}}{30}\right]\ =\ n\left(t\right)\ =\ n\ =\ counter_{TOTP}\ \left(n\right)\

Используя полученный счётчик, и, проделав c ним шаги алгоритма HOTP, получим в результате, искомый шестизначный код-пароль, сгенерированный при помощи алгоритма TOTP:

\begin{array}{l}TempPassword_{TOTP}\ =\ NUM\ mod\ \alpha\ =\ int\left(Digest_{31\ bit}\ \left(t\right)\right)\ mod\ \alpha\ =\ \ \\ =\ int\left(CUT\left(Digest_{160\ bit\ }\left(t\right)\ \right)\right)\ mod\ \alpha\ =\\ =\ int\left(CUT\ \left(h\left(Secret\ +\ counter_{TOTP}\left(t\right)\right)\right)\right)\ mod\ \alpha\ =\\ =\ int\left(\ CUT\left(h\left(Secret\ +\ \left[\ \frac{\tau_{UNIX}}{30}\right]\ \right)\right)\right)\ mod\ 10^6\end{array}

Для алгоритма TOTP также приведём возможный пример реализации на языке C#, по-прежнему, как и в примере для HOTP, будем генерировать восьмизначный код пароль, и делать это будем каждые пять секунд:

        public ActionResult totp(string button1, FormCollection form)
        {
            ViewData["seed"] = form["seed"];
            string s1 = form["seed"];
            if (s1 == null) s1 = "";
            var topt = new Totp(System.Text.Encoding.UTF8.GetBytes(s1), step: 5);

            if (button1 != null)
            {

                topt = new Totp(System.Text.Encoding.UTF8.GetBytes(form["seed"]), step: 5);

            }


            
            var totpCode = topt.ComputeTotp();
            string v = String.Format("{0:00000000}", totpCode);
            ViewData["random"] = v;

            return PartialView("onetime_random");




        }

Современные проблемы и современные решения

«Всякая перемена прокладывает путь другим переменам»

© Никколо Макиавелли, Государь

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

Но что, если мы захотим в своих рассуждениях покинуть рамки привычной нам процедуры аутентификации, и сделать следующий шаг, предполагающий эффективное использование самого понятия двухфакторной/многофакторной аутентификации как инструмента, позволяющего контролировать, санкционировать и управлять доступом субъектов к чувствительной информации? В этом случае, нам будет необходимо начать использовать принцип Нулевого доверия (англ. Zero-Trust)

Zero-Trust

Сам принцип предполагает отсутствие как такового доверия между двумя сущностями, намеревающимися осуществить взаимодействие между собой, до того момента, пока обе сущности не произведут идентификацию друг друга. Появление метода обуславливается тем, что на сегодняшний день, периметр организаций уже не закачивается, как 10 лет назад локализовано - на шлюзах безопасности, располагающихся непосредственно в офисе, а постепенно становится всё более и более размытым – вклад в это вносят, например, работники “в полях”, интернет вещей и неуменьшающийся рост популярности WEB-приложений и ИТ решений, предоставляемых ИБ вендорами в рамках сервисных моделей.

Принцип Нулевого Доверия (англ. Zero-Trust) опирается на три фундаментальных постулата:

1) [Постоянная аутентификация]

Предполагается, что она производится не в индивидуальном порядке – непосредственно сервисом, а как сервисом, так и субъектом, по отношению друг к другу.

2) [Предоставление минимально допустимых привилегий]

Со стороны организации формируется набор политик безопасности, ранжирующий информацию по степени её чувствительности и важности для компании.

3) [Контроль за строгим соблюдением правил и мониторинг]

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

Далее предлагается разобрать принцип его реализации, основываясь на трех, упомянутых выше постулатах.

Графическая иллюстрация возможной реализации принципа нулевого доверия
Графическая иллюстрация возможной реализации принципа нулевого доверия

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

1)     Размещаем субъекта в некоторой “буферной” зоне, которую будем называть шлюзом аутентификации – из неё пользователь физически не может проникнуть вглубь инфраструктуры дальше и передать или запросить из неё какие-либо данные.

2)     Наблюдаем за поведением субъекта при помощи контроллера доступа, пока он находится внутри “зоны досмотра” (читатель с богатым воображением может представить себе нечто наподобие стеклянного куба, внешняя грань которого удалена [пройдя сквозь неё пользователь в этот куб проник, и по-прежнему, через неё может получать информацию из внешнего мира]).

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

4)     Провайдер идентификации (IDP) проводит проверку подлинности субъекта при помощи многофакторной аутентификации (возможные варианты реализации, которой, на уровне алгоритмов, разбирались ранее)

5)     В случае успешного завершения процедуры, IDP сообщает об этом контроллеру доступа по защищённому каналу

6)     После этого контроллер доступа, повторно анализируя весь имеющийся набор данных о субъекте, запрос на тип информации, поступивший от него, а также ответ IDP принимает, или не принимает решение об открытии шлюза доступа

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

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

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

2)     Запрашивать при аутентификации дополнительные факторы, в том числе, при каждом повышении уровня чувствительности информации, например:

  • Доступ к общей папке отдела сотрудника разрешается после двухфакторной аутентификации через приложение на смартфоне по одному из упомянутых ранее алгоритмов (HOTP, TOTP).

  • Доступ к общей папке департамента разрешается после аутентификации по еще одному фактору – сканированию отпечатка пальца.

Вообще говоря, перечисленными способностями набор возможностей, открывающихся при использовании контроллера доступа и подхода Нулевого Доверия как такового, разумеется, не исчерпывается. При помощи формирования и точной подстройки политик, основываясь на подходе Zero-Trust, можно создать, действительно, современную, надёжную и защищённую инфраструктуру безопасности – тем более, необходимость подобных нововведений обуславливается не синтетическим прогрессом средств защиты, а необходимостью неуклонно следовать за ходом эволюционного развития киберпространства.

Заключение

В рамках данной статьи были определены и исследованы понятия Аутентификации и Двухфакторной Аутентификации с использованием как математических средств, так и анализа предпосылок, формируемых текущим состоянием рынка кибербезопасности, совершён разбор алгоритмов двухфакторной аутентификации HOTP и TOTP, показано возможное их применение в рамках более фундаментальных архитектурных подходов к организации инфраструктуры безопасности компаний - таких, как концепция Нулевого Доверия, а также, описан сам принцип Zero-Trust.

Послесловие

Данная статья писалась студентом МФТИ и действующим junior-менеджером продукта одного из VAD-дистрибуторов рынка ИБ - она была тщательно проверена на предмет наличия ошибок, как обычными менеджерами продукта и членами отдела технической экспертизы, так и одним из университетских преподавателей автора, имеющим непосредственное отношение к криптографическим кругам защиты информации и академической среде, тем не менее, в том случае, если после прочтения, какой-то из её фрагментов вызывает у вас вопросы, или желание сделать некоторое дополнение, автор призывает не испытывать стеснения и смело высказывать подобные мысли в секции комментариев - возможно именно ваша корректировка окажется полезной и нужной для следующего читателя.

Комментарии (5)


  1. Protos
    08.12.2021 04:54

    Очень подробно описаны алгоритмы, которые известны уже много лет, а вот про алгоритмы или конкретные решения именно zero-trust не сказано ничего. Последний раздел звучит красиво, но так ли легок к реализации на самом деле? Что если злоумышленник получил полное владение ПК сотрудника, поможет ли zero-trust?

    Почему сотрудник изображен именно в недоверенной сети, а если я включаю ПК который находится в доверенной сети, для него никакого zero-trust не будет, он сразу будет иметь полный доступ Или как в данном случае предполагается?

    Почему по тексту используется термин субъект, но если идет объяснение, то становится понятнее, что речь идет о ПК пользователя. Zero-trust для доступа серверов к серверам плохо применим? Или точнее он совсем не применим так как рассмотрены алгоритмы аутентификации людей, а не программ при доступе к программам?


    1. PlastilinovayaVorona Автор
      08.12.2021 09:50
      +1

      Доброе утро ;)


    1. PlastilinovayaVorona Автор
      08.12.2021 11:36
      +1

      Доброе утро, спасибо за ваше внимание к статье ;)

      [Прошу прощения - предыдущий комментарий отправился случайно, и я не успел его исправить]


      Подробные описание алгоритмов, именно в таком формате, были включены в статью для того, чтобы читатель в случае первичного знакомства с предметной тематикой, без труда составил для себя представление о иных подходах к построению аутентификации, не загоняя себя в рамки Push и уже привычных SMS, которые, кстати, NIST примерно с Q1 2016 перестал рекомендовать для использования при аутентификации.

      Zero-Trust это концепция в организации инфраструктуры безопасности, и построить её можно самыми разными способами - доказательством этого, служит тот факт, что есть довольно большое число вендоров, предлагающих свои решения в этой парадигме. Тут вопрос уже больше к архитекторам, потому что, например, вместо шлюза аутентификации можно использовать VPN, в рамках IDP выбирать факторы, по которым будет осуществляется проверка подлинности, а на контроллере доступа собирать свой набор политик.

      ZT хорош как раз своей гибкостью, поэтому, отвечая на ваш вопрос:

      "Почему сотрудник изображен именно в недоверенной сети, а если я включаю ПК который находится в доверенной сети, для него никакого zero-trust не будет, он сразу будет иметь полный доступ Или как в данном случае предполагается?"

      Хотелось бы уточнить, что в рамках подхода, выбор фрагмента сети, который вы будете считать доверенным или публичным, зависит сугубо от вашего решения – вы можете, например, в рамках метода, полностью упразднить доверенную сеть (фактически ваш defined perimeter, разумеется, останется таким же, каким и был до этого) [получается что в данном случае мы строим ZT внутри привычного периметра, доверенной сети, которую мы доверенной считать перестали]. Тогда каждый пользователь будет проходить через все процедуры ZT, регулируемые вашими политиками, даже в том случае, если он находится внутри периметра организации.

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

      Что если злоумышленник получил полное владение ПК сотрудника, поможет ли zero-trust?

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


  1. itsoft
    08.12.2021 12:25
    -1

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

    Правильно разделять общедоступные выкладки для всех и обоснования для специалистов. Сложности надо скрывать под капот, а методы использования давать максимально понятным для всех языком. На сложностях мозг отключается.


  1. styugin
    10.12.2021 13:55
    +1

    Мне остался непонятен индекс эффективности EFF (с ходу загуглить не удалось). Почему EFF растет с ростом значения вероятности проникновения и стоимости решения? Разве он не должен быть обратно зависим от этих величин? И почему по вашей же формуле у вас EFF смартфона больше чем EFF сканера сетчатки?