Что такое токен аккаунта
Перейти к содержимому

Что такое токен аккаунта

  • автор:

Неприметные токены. Часть 1. Теория

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

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

  • пароли в открытом виде
  • NT-хэши паролей
  • TGT
  • MsCache v2 хеши
  • секреты в DPAPI и др.

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

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

Сессия пользователя#

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

Бытовая аналогия#

Рассмотрим следующий пример — организация доступа на стадионы чемпионата мира по футболу 2018.

Поверхностно опишем процедуру прохода:

  1. Каждый, кому требовалось пройти на стадион, сначала приходил в один из нескольких аккредитационных центров, где предоставлял свой паспорт и обоснование для прохода.
  2. Сотрудник аккредитационного центра проверял личность предъявителя и его обоснование, тем самым аутентифицируя его. Если личность была болельщиком, то обоснованием являлся билет на матч, если репортером, то требовалось наличие соответствующей записи в заранее согласованной базе данных. Кроме того требовалось смотреть в базу, чтобы выявлять нежелательных посетителей, входящих в черный список (пранкеры, агрессивные фанаты). Отметим, что процедуру проверки в базе данных можно считать довольно ресурсозатратной.
  3. В результате успешной проверки посетителю стадиона выдавалась аккредитация. Таким образом осуществлялась авторизация.

Каждая аккредитация содержала следующую информацию:

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

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

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

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

Сессия в Windows#

Рассмотрим, что происходит при входе пользователя в Windows:

  1. Пользователь садится за компьютер и предоставляет системе свои аутентификационные данные (логин, пароль, название домена, smart карту или другие).
  2. Система передает полученную информацию в свой локальный центр безопасности (далее — LSA).
  3. LSA осуществляет аутентификацию пользователя.

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

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

В Windows в качестве защищаемых объектов выступают совершенно различные объекты, например: файлы, именованные каналы, ключи реестра, процессы, потоки, сетевые папки, службы, устройства, объекты Active Directory и т.д.

Пользователю не требуется заново вводить свой пароль при каждом открытии файла или запуске прикладной программы. Это называется концепцией единого входа (Single Sign On — SSO), которая реализуется, в том числе с помощью механизма сессий.

В рамках сессии для получения доступа к защищаемому объекту пользователю необходимо обладать определенным контекстом безопасности.

Связь пользователя, сессии и контекста безопасности

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

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

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

Процессы в Windows#

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

Процесс — это объект операционной системы, содержащий набор ресурсов (в частности выделенный диапазон адресов виртуальной памяти) и данных используемых в ходе работы программы.

Уместно провести следующую аналогию:

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

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

Токены в первом приближении#

Что происходит, когда пользователь открывает файл в текстовом редакторе?

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

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

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

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

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

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

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

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

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

Теперь в первом приближении можно ввести следующее определение:

Токен доступа пользователя — объект ядра ОС Windows, описывающий контекст безопасности процесса, работающего от имени указанного пользователя.

Синонимы: токен, токен доступа, маркер доступа, маркер безопасности.

Атрибуты токена#

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

  • Идентификатор пользователя
  • Идентификатор входа в систему (Logon ID — LUID)
  • Перечень локальных и доменных групп, в которые входит пользователь
  • Список привилегий, которыми обладает пользователь

Пример отображения некоторых атрибутов токена

Более наглядно посмотреть токены и их атрибуты можно с помощью утилиты TokenViewer

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

Уровни целостности#

Начиная с Windows Vista, в операционных системах семейства Windows реализован механизм мандатного контроля целостности (mandatory integrity control, MIC).

Согласно MIC в Windows каждому защищаемому объекту операционной системы присваивается мандатная метка, соответствующая определенному уровню целостности. Физически мандатная метка представляет собой целое число. Чем больше число, тем выше уровень целостности.

Уровень целостности процесса хранится в токене указанного процесса в списке групп:

В современных версиях Windows поддерживаются следующие уровни целостности:

Числовой идентификатор Название Описание
0 Untrusted Используется редко, например в ходе анонимного подключения.
4096 Low Назначается процессам браузеров или контейнеров, чтобы ограничить права на запись в отношения системных файлов или ключей реестра.
8192 Medium По умолчанию назначается большинству процессов прикладных программ.
8448 Medium Plus Недокументирован.
12288 High Назначается процессам прикладных программ администратором.
16384 System Автоматически назначается всем системным процессам. Процессам прикладных программ назначаться не может.
20480 Protected Process Назначается специальным защищаемыми процессам

Основная идея мандатного контроля целостности заключается в том, что “низкоцелостные” субъекты не могут изменять “высокоцелостные” объекты.

Рассмотрим, как это используется на практике.

Токены привилегированных учетных записей#

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

  • Builtin Administrators
  • Domain / Enterprise Administrators
  • Policy Administrators
  • Account Operators
  • Backup Operators

а также на предмет наличия следующих “опасных” привилегий:

  • SeBackupPrivilege
  • SeCreateTokenPrivilege
  • SeDebugPrivilege
  • SeImpersonatePrivilege
  • SeLabelPrivilege
  • SeLoadDriverPrivilege
  • SeRestorePrivilege
  • SeTakeOwnershipPrivilege
  • SeTcbPrivilege

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

  1. Полный токен (в англ. “elevated token”), содержащий все назначенные права, группы, привилегии и имеющий высокий уровень целостности.
  2. Отфильтрованный токен, в частности обладающий следующими ограничениями:
    • отсутствуют “опасные” привилегии
    • присваивается средний уровень целостности

Сравнение логона администратора и обычного пользователя

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

Содержимое токена процесса администратора, запущенного в обычном режиме

Когда пользователю необходимо выполнить задачу, требующую повышенного токена доступа, Windows автоматически запрашивает подтверждение. Этот запрос называется запросом на повышение прав и реализуется с помощью специального компонента — UAC (User Account Control).

Пример оконных сообщений UAC

Содержимое токена процесса, запущенного от имени администратора

Более детальное описание механизма UAC выходит за рамки настоящего материала.

Виды логонов#

Вход в Windows можно осуществить по-разному. Для простоты можно выделить следующие два типа входа (строго говоря их больше):

  • Интерактивный
  • Сетевой (неинтерактивный)

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

Но что происходит, когда пользователь пытается посмотреть содержимое удаленной сетевой папки, например с помощью следующей команды?

Просмотр содержимого сетевой папки

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

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

Это еще один из примеров, иллюстрирующий поддержку принципа единого входа в Windows.

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

Связь между токенами, различными видами сессий и учетными данными

Еще раз отдельно отметим:

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

Теперь рассмотрим, что происходит с другой стороны в удаленной системе.

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

Процесс “SMB сервера” работает от имени и с правами псевдопользователя SYSTEM. Предоставление прав системы всякому аутентифицированному к SMB серверу пользователю однозначно избыточно. Более того указанный пользователь может обладать доступом не ко всему содержимому сетевой папки.

То есть, процессу “SMB сервера” было бы очень удобно как-то работать от имени своих клиентов. В Windows такой механизм предусмотрен и называется олицетворением (англ. Impersonation).

Олицетворение#

До этого уже немного была затронута тема процессов в операционной системе Windows. Теперь расширим это понятие. У каждого процесса есть как минимум один поток, выделяемый при создании процесса (как правило, на практике потоков больше). Этот поток может породить другие потоки, те в свою очередь новые и т.д.

Рассматриваемый всюду ранее токен доступа, назначаемый процессу операционной системы при его создании, называется первоначальным токеном или токеном процесса (англ. primary token).

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

Токен потока, применяемый для заимствования контекста безопасности другого пользователя, называется олицетворяющим токеном (англ. impersonation token).

Таким образом появляется еще одна классификация токена: первоначальный или олицетворяющий.

В связи изложенным можно уточнить определение токена:

Токен доступа пользователя — объект ядра ОС Windows, описывающий контекст безопасности процессов или потоков, работающих от имени указанного пользователя.

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

Выдача олицетворяющего токена при сетевом входе

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

Аутентификации при сетевом входе

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

Уровни олицетворения#

Олицетворяющие токены имеют следующую важную характеристику — уровень олицетворения, который отражает степень того, насколько сервер может олицетворять клиента. Всего существуют следующие четыре уровня олицетворения:

Название Описание
Anonymous Удаленный сервер не может идентифицировать или олицетворять клиента. Используется для анонимного подключения.
Identification Удаленный сервер может идентифицировать, но не может олицетворять клиента.
Impersonation Удаленный сервер может идентифицировать и олицетворять клиента локально в системе. Подобные токены обычно создаются в результате сетевого входа, например при доступе к FTP серверу.
Delegation Удаленный сервер может идентифицировать и олицетворять клиента в удаленных системах. Подобные токены обычно создаются в результате интерактивного входа, например по RDP.

Классификации токенов#

Обобщая написанное выше, получается, что токен:

  1. Содержит перечень групп и привилегий пользователя
  2. Может быть полным, а может быть фильтрованным
  3. Может быть связан с интерактивной или неинтерактивной сессией, то есть иметь связь с учетными данными или не иметь
  4. Может быть первоначальным, а может быть олицетворяющим. Если токен олицетворяющий, то он обладает одним из четырех уровней олицетворения

Заключение#

В настоящей статье было рассмотрено устройство токенов доступа в Windows. Был представлен обзор основных атрибутов по которым можно классифицировать токены, а также рассказано о связи токенов, сессий и аутентификационных данных. Изложенные сведения полезны для понимания атак, связанных с манипуляциями токенами.

Token-Based Authentication

Tyroo West

In this tutorial, we will cover token-based authentication .

The general concept behind token-based authentication is the ability for users to obtain a token in exchange for their user credentials. This token authorizes the user to access protected resources without the need for querying for credentials.

Once the token is obtained, the user is now authenticated and can access protected resources for a specified amount of time.

In other words…

Typically when you check into a hotel you are given a room key. Think of the room key as your token. This room key gives you the user, access to the protected resources, such as the gym and the pool.

You are authorized to use the gym and pool for a specified amount of time: the duration of your staty at the hotel. Once you have checked out of the hotel, you are no longer authorized to access those protected resources.

What is a cookie? ��

Cookies are small pieces of data sent from a website and are stored in the user’s web browser while the user is browsing that website. Every time the user loads that website back, the browser sends that stored data back to website or server, to distinguish user’s previous activity.

G etting Started

In this tutorial, the emphasis is on token-based authentication therefore, we will not be using a database. In another tutorial, I will revisit this topic to create a MERN Stack Web application using token-based authentication.

Side note…

I wrote this post from a particular perspective. At the time of this post, I was a teaching assistant for a coding bootcamp and noticed a lot of students struggling debugging their console errors. In this guide, we analyze and resolve common errors. With that said…

Let’s Get Started

The 3 most important tools we will be using for this project are the following:

bcrypt: A library to help you hash passwords.

json-webtoken: A JSON object that is defined as a safe way to represent a set of information between two parties.

dotenv: A zero-dependency module that loads environment variables from a .env file into process.env .

cookie-parser: Parse Cookie header and populate req.cookies with an object keyed by the cookie names. Optionally you may enable signed cookie support by passing a secret string, which assigns req.secret so it may be used by other middleware.

N ow, lets set up our app:

Assuming you have Node.js and Git installed, run the following commands in your terminal to get started.

In this tutorial config and models is not needed. However, if we were using a database the config directory would contain our database connection and our model's directory would contain the models of our data.

In your .env file, change the following:

The last change is to update our package.json file and add a script for nodemon. In package.json add the following:

Heres a summary of what we’ve just done.

  1. made a directory called authentication on your desktop and navigated to the directory
  2. we initialize the project with git
  3. we initialize the project with a package.json file with default settings
  4. we install our dependencies
  5. we create our empty server file and the needed directories
  6. created a Users.json file, that would contain our mock database of users
  7. created a file called .ignore and write names of files/folders to ignore
  8. create a file called .env that will hold the environment vairables that will be used throughout our project by using process.env .

Let's start the server.js file by running npm run nodemon from the terminal.

let's add some code to our express app. I will not explain in detail what each line of code does, however, the answer to these question can quickly be found with a bit of google foo! Moving on…

Congrats! We have our first error! ��

We’ll get to that soon enough. But before then, a few things to note. In our code, we are using destructuring:

Now, for the Error… ��

At first, this can be overwhelming, but if we look closely…

  1. What does our error say? Error: Cannot find module './routes/user'
  2. What does this error mean? Cannot find our module userRoutes
  3. Why are we getting this error? ur we are requiring a variable that references a file which does not exist yet
  4. How can we fix this error? Create a file called user.js inside of the routes directory

Side Note: what does app.use('/users', userRoutes) do?

app.use('/users', userRoutes) prefixes all of our routes inside the routes/user.js with /users .

What we are doing here is requiring & exporting the, and using our controller functions to handle our routes . These functions getUser, cookieCheck, login, logout, signup are used to do something on these particular routes. We will review these in a second. But first…

We now have another Error! ��

Take some time to think about how to answer the following questions:

  1. What does our error say?
  2. What does this error mean?
  3. Why is this error happening?
  4. How can we fix this error?

Answer: our controller functions are not defined.

To resolve this error, let's create a file called user.js inside of the controllers directory and insert the following code:

Oh look, another Error, yay!�� �� This is the last one I promise ��

How do we fix this one? no clue?

Let’s google it! �� …Wait, what do I google?

Answer: SyntaxError: Unexpected end of JSON input

…If you didn’t find the answer, here is why we get the error:

We do not have any data in our dbUsers.json file

How to Fix?

Open our config/dbUsers.json file and copy �� our mock data.

Make sure the data is properly formatted as JSON by using double quotes " "

For demonstration purposes, we’ve hardcoded plainTextPasswords and hashedPasswords for testing our mock users. However, we will create new users and hash their passwords.

Congratulations!

You’ve made it this far. At this point, it would be a good idea to start testing our routes and ensure everything is working correctly. If you have not done so already, go ahead and download POSTMAN.

��Before you start testing routes!!

Every time you save your JavaScript files nodemon will restart the application. Therefore, our newly created users are deleted every time we save.

�� Here’s what our routes look like, the corresponding methods, and the response:

�� Your application structure should look like this:

You can ignore the images directory and the README.md those were included in the image while testing the tutorial.

Now that all our routes are defined, let write the logic for hashing passwords and start testing using POSTMAN.

���� Testing our Routes in POSTMAN

Let’s open POSTMAN and make our first request.

TODO:

  1. set our HTTP METHOD to GET
  2. set our route name to http://localhost:PORT/users/all
  3. ensure the PORT is the correct number. Check your .env
  4. finally, click send

Notice on our GET /users/all route, our passwords are stored as plain text. What we need to do is store the plainTextPasswords as hashedPasswords using bcrypt.

Let's create a file called passwordService.js in our utility directory and insert the following code:

  1. What we are doing here is requiring the bcrypt package and using our environment variable SALTROUNDS from our .env file.
  2. Exporting two functions, hashPassword and checkPassword which will be used in our login and register routes. This would typically be done on your user model but because we are not using an official database we will use them directly on our routes.
  • hashPassword : is an async function that takes a plain text password as an argument , uses the bcrypt.hash method which takes a plain text as its first argument and the number of salt rounds as its second argument and returns the hashed password .
  • checkPassword : is an async function that takes a plain text password as its first argument and a hashed password as its second argument and uses the bcrypt.compare method which takes a plain text as its first argument and the hash as its second argument and returns the hashed password .

Although our environment variable for SALTROUNDS is a number, we still need to parse our value as an Integer.

SaltRounds…Ummm what's that? ��

SALTROUNDS: “The Cost Factor”

The cost factor controls the amount of time needed to calculate a single BCrypt hash. The higher the cost factor, the more hashing rounds is done. Increasing the cost factor by one doubles the necessary time. The higher the cost factor, the more difficult a hash is susceptible to brute-forcing.

  1. The salt is a random value and should differ for each calculation. The results should hardly ever be the same, even for equal passwords.
  2. The salt is usually included in the resulting hash-string in a readable form. So with storing the hash-string you also store the salt.
  3. A cost factor of 10 means that the calculation is done 2¹⁰ times which is about 1000 times. The more rounds of calculation you need to get the final hash, the more CPU/GPU time is necessary. This is no problem for calculating a single hash for a login, but it is a huge problem when you brute-force millions of password combinations.

We have our function, how do we use it?

For this exercise, we will modify each route individually, so be sure to always copy and paste the new constant variables located at the top of each code snippet.

Insert the following code for the signup route:

What we are doing here is requiring a package uuid which creates a unique id for our newUser object. Then we use our hashPassword middleware function and pass our password from the post in our req.body . We then push our newUser to our dbUsers.json file, send a status code to our client and redirect to our /users/all route.

Test your /users/signup route using POSTMAN

  • HTTP METHOD: POST ,
  • ROUTE: http://localhost:yourPortNumber/users/signup
  • click on body
  • select x-www-form-urlencoded
  • finally, add a key-value pair of username, password

Once you submit your POST you should have a new user in the response

Wallah! You should now be able to create a new user which should have an id, username, password, and a hashedPassword field.

Next, we will add functionality to our login route using our checkPassword middleware function from utilities/passwordService.js .

Add the following code to our login route:

Test your login route using POSTMAN

What we are doing in our login route is returning the first user in our “database” that matches the req.body.username. Then we are using our checkPassword function which returns a Boolean value . The check password function checks if the req.body.password matches the hashedPassword from our user .

Now we conditionally check if a user exists. If the user exists, we then check if the password matches. If all goes well, we send a 202 status code and redirect to our authorized route. Otherwise, we send errors to the client explaining what went wrong. In a real application, your message would look more something like: “sorry, the credentials you have entered are incorrect please try again”.

We now need to implement json-webtokens and ��’s.

Let's create and open a file utilities/tokenService.js . In this file, we need the jsonwebtoken package and our SECRET environment variable. We will then create two functions, createToken and isValidToken .

What we expect the code above to do is create a token by using jwt to sign a token. Passing in an object with our expected user, and an expiration time, and our SECRET environment variable. Then we return the token. Additionally, we verify our token using jwt.verify which takes an expected token string as its first argument and our SECRET environment variable.

Now in our controllers/user.js file lets refactor our code and each route to use our token service and cookies.

Updating our Route handlers, one by one

������MAKE SURE TO TEST EVERY ROUTE!!

In the above snippet:

  • require UUID which automatically generates unique id’s for our users.
  • require our Users mock database.
  • require our utilities for our password Service and token Service.
  • create an object called cookie options which will be explained below.

In the above snippet:

  • we create a getUsers handler that sends our Users array to the client.

In the above snippet, we create a login handler which:

  1. Finds a user by its username
  2. Checks the submitted password to our users hashedPassword
  3. Then we check if the user exists if true…
  4. We then check if the password matches, if true…
  5. Create a token with the user object.
  6. Create a cookie called token, pass in our token, and our cookieOptions and redirect to authorized route.

Notice, we console.log("token", token); . Copy �� this token from the terminal and visit JWT. Scroll down to the debugger and past your token in the encoded area.

Our token, when decoded contains a header, payload, and signature. Where the header contains the algorithm and type of token, the payload contains the data, and the signature verifies if our signature matches our SECRET environment variable.

How do you use API keys and tokens to manage and revoke access to your API?

If you are building or consuming an API, you need to ensure that only authorized users and applications can access it. One of the most common ways to do that is by using API keys and tokens. These are unique identifiers that grant or restrict access to your API based on predefined rules and policies. In this article, you will learn how to use API keys and tokens to manage and revoke access to your API, and what are the best practices to follow.

What are API keys and tokens?

API keys and tokens are different types of credentials that authenticate and authorize requests to your API. An API key is a simple string that identifies the client or application that is making the request. An API token is a more complex string that encodes information such as the scope, expiration, and permissions of the request. Both API keys and tokens are usually passed as headers or query parameters in the HTTP request.

★ 320K+ subscribers | 2MM+ views on YT ���� �� ���� Man-vs-Machine | #AI | #chatgpt | #api | #cybersecurity | keynote speaker | ex-hacker | strategist | filmmaker | developer | consultant | #apisecurity | #houserules

⭐ API keys: Passwords for apps! Unique identifiers that authenticate requests, allowing access to your API. Handle with care, as they don’t discern users or roles. ��️ ⭐ Tokens: Temporary passports, issued after user authentication. Carrying roles, permissions, and user info, they’re versatile! Two popular types: JWT (JSON Web Tokens): Compact, URL-safe, and self-contained. Carries claims and can be cryptographically signed ��. OAuth2 tokens: From OAuth2 authorization framework, they delegate access without sharing credentials ��. Use API keys and tokens to manage access to your API like a digital locksmith! ��

  • Копировать ссылку на вклад
  • Пожаловаться на вклад

Спасибо за уведомление! Вы больше не увидите этот вклад.

Why use API keys and tokens?

API keys and tokens offer several advantages for securing your API. They enable you to control who can access your API and what they can do with it, as well as track and monitor its usage and performance. Additionally, you can revoke or rotate access when needed without affecting other users or applications. Moreover, you can implement different levels of authentication and authorization depending on the sensitivity and complexity of your API.

★ 320K+ subscribers | 2MM+ views on YT ���� �� ���� Man-vs-Machine | #AI | #chatgpt | #api | #cybersecurity | keynote speaker | ex-hacker | strategist | filmmaker | developer | consultant | #apisecurity | #houserules

⭐ Authentication: API keys/tokens verify app/user identity, ensuring authorized access ��. ⭐ Rate limiting: Control traffic by assigning access levels to keys/tokens ��. ⭐ Traceability: Track usage to specific keys/tokens, aiding investigations ��. ⭐ Revocation: Revoke compromised/inactive keys/tokens with ease ��. ⭐ Granular access: Tokens enable fine-grained permissions for specific resources ��. Harness the power of API keys and tokens to expertly manage access, ensuring security and balance in your digital dominion! ����

  • Копировать ссылку на вклад
  • Пожаловаться на вклад

Спасибо за уведомление! Вы больше не увидите этот вклад.

How to generate API keys and tokens?

When it comes to generating API keys and tokens, there are a few different methods to choose from. You may use a built-in or third-party service, such as AWS API Gateway, Auth0, or Firebase. Additionally, you can use standard protocols or specifications like OAuth, JWT, or API Key Authentication. Finally, you can create and verify API keys and tokens with custom logic or algorithms like hashing, encryption, or signing.

Accenture API Security Lead, The API Guy, Cyber Security, and All Things Cloud!

This is way too generic. You should have a well-governed process and tooling in place to manage API keys, secrets, and tokens. Modern API platforms can manage keys and secrets, but it is often better to use an identity management provider. The last sentence of the paragraph is not accurate. Hashing, encryption, and signing are not, in and of themselves, ways to create and verify tokens.

  • Копировать ссылку на вклад
  • Пожаловаться на вклад

Спасибо за уведомление! Вы больше не увидите этот вклад.

★ 320K+ subscribers | 2MM+ views on YT ���� �� ���� Man-vs-Machine | #AI | #chatgpt | #api | #cybersecurity | keynote speaker | ex-hacker | strategist | filmmaker | developer | consultant | #apisecurity | #houserules

⭐ Generating API keys: Typically, API management platforms or identity management providers handle key generation. When a developer requests access, a unique key is created for their API calls ��️. ⭐ Generating tokens: You’ll need an authentication server supporting OAuth2, OpenID Connect, or a custom scheme. The (simplified) process: 1. User logs in with credentials ��. 2. Server verifies credentials ��. 3. Server issues access token for API calls ��️. API keys and tokens equip you to skillfully oversee access to your digital assets, ensuring top-notch security and precise control in your API ecosystem! ����

  • Копировать ссылку на вклад
  • Пожаловаться на вклад

Спасибо за уведомление! Вы больше не увидите этот вклад.

How to manage API keys and tokens?

Managing API keys and tokens requires setting up and enforcing policies and rules that determine how they are used and distributed. It is essential to consider how to store and secure them, both on the server and the client side, as well as avoiding any exposure of them in plain text or hardcoding. Additionally, you should limit the number and scope of your API keys and tokens, assigning them based on the roles and responsibilities of users and applications. Furthermore, you should use tools that allow you to monitor, audit, analyze, report on your API keys and tokens, as well as alerting you of any anomalies or breaches.

★ 320K+ subscribers | 2MM+ views on YT ���� �� ���� Man-vs-Machine | #AI | #chatgpt | #api | #cybersecurity | keynote speaker | ex-hacker | strategist | filmmaker | developer | consultant | #apisecurity | #houserules

⭐ Centralize management: Oversee key/token distribution and usage with API management platforms ��. ⭐ Assign roles & permissions: Implement role-based access control (RBAC) to define access levels for API keys/tokens, ensuring proper resource usage ��️. ⭐ Rotate keys/tokens: Update keys/tokens regularly, automating the process if possible ��. ⭐ Revoke when needed: Terminate access for compromised, expired, or unused keys/tokens promptly ��. ⭐ Monitor & audit: Track usage patterns, investigate anomalies, and conduct regular audits to ensure compliance ��. Masterfully manage API keys and tokens to maintain a secure and well-organized API ecosystem, protecting your digital resources! ����

Справочник анонима. Как работают токены аутентификации и в чем их отличия от паролей

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

Другие статьи цикла:

  • «Теория и практика шифрования почты»;
  • «Виды шифрования и защиты трафика, выбор софта»;
  • «Как шифровать переписку в Jabber: пошаговая инструкция»;
  • «Делаем шпионскую флешку с защищенной операционкой Tails».

Если для тебя эти материалы тривиальны — отлично! Но ты сделаешь доброе дело, отправив ссылку на них своим друзьям, знакомым и родственникам, менее подкованным в технических вопросах.

Подписываемся под данными

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

Схема генерации HMAC (hash-based message authentication code), кода аутентификации сообщений с использованием хеш-функции

Схема генерации HMAC (hash-based message authentication code), кода аутентификации сообщений с использованием хеш-функции

Другие статьи в выпуске:

Xakep #247. Мобильная антислежка

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

Придумываем коды доступа

Люди, которые придумали двухфакторную аутентификацию, по всей видимости, руководствовались принципом «одна голова хорошо, а две — лучше». И действительно — два пароля точно безопаснее одного. Но пароли, которые отправляет сайт в SMS, нельзя назвать абсолютно защищенными: сообщение чаще всего можно перехватить. Другое дело — специальные приложения для аутентификации, они нацелены на полную защиту всего процесса входа пользователя в аккаунт. Именно их мы сейчас с тобой и разберем.

Создание безопасных одноразовых паролей состоит из двух этапов:

  1. Первичная настройка — включение двухфакторной аутентификации.
  2. Использование пароля — непосредственный ввод кода и отправка для проверки.

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

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

На самом деле весь секрет — последовательность из случайных символов, которые закодированы в формате Base32. Суммарно они занимают не меньше 128 бит, а чаще и все 190 бит. Эту последовательность и видит пользователь как текст или QR-код.

Так выглядит код QR для обмена секретом Так выглядит код QR для обмена секретом
Тот же самый секрет, только текстом Тот же самый секрет, только текстом

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

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

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

Возьмем время празднования Нового года в формате UNIX ( 1577811600000 ) и посчитаем порядковый номер нашего пароля: поделим на 30 секунд — 52593720 . Воспользуемся нашим секретом и вычислим хеш — по стандарту RFC 6238 это функция SHA-1:

Не забудь про аргумент -n для команды echo , чтобы в ее выводе не было ненужного перевода строки, иначе хеш будет другим.

Теперь дело за малым: нужно получить шесть цифр, которые мы и будем отправлять на сервер при авторизации. Возьмем последние четыре бита хеша — сдвиг, — это будет число a , или 10. Именно по этому сдвигу расположен наш код, который пока в виде байтов, — 03b08b12 = 61901586 . Отбросим все цифры этого числа, кроме шести последних, и получим наш новенький, готовый к использованию одноразовый код — 901586 .

Входим в приложение

Ни одно современное приложение не спрашивает пароль у пользователя постоянно, поскольку пользователей это раздражает. Именно поэтому разработчики и ученые-криптографы придумали токены, которые могут заменить собой пару логин — пароль. Перед учеными стояла задача не столько скрыть какую-то информацию, сколько создать общий стандарт для ее хранения и подтверждения ее надежности. Для всего этого была придумана технология JSON Web Token (JWT).

Как работает JWT?

Если есть данные, достоверность которых следует подтвердить, нам надо подписать их секретным ключом, используя HMAC. Для этого применяется такой же способ хеширования, что и для одноразовых паролей, только вместо шести цифр берется весь хеш целиком. Единственная разница — это сам алгоритм хеширования: в таких токенах SHA-1 считают слишком коротким и небезопасным, поэтому обычно используют SHA-256.

Главная задача JWT — подтверждение личности создателя токена и сопутствующих данных. Обычно содержимое токена — логин или другой идентификатор пользователя.

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

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

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

Закодируем наши данные и заголовок в Base64 и соединим их через точку. Это делается, чтобы безопасно пересылать данные через HTTP: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjogMTIzNDU2fQ . Теперь, зная и данные, и заголовок, мы можем посчитать ее хеш, который содержит наш пароль — строку QWERTYUI12345678 .

Этот хеш нам тоже надо перевести в кодировку Base64 и затем присоединить к уже имеющейся строке из заголовка и данных: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjogMTIzNDU2fQ.4Ka0ipYe4/x-s4r82xqO8i77BXLh1TM7hdsqpmkZ6Y4 — это и есть наш токен. Можно пользоваться!

Так выглядит наш токен

Так выглядит наш токен

Подробнее про стандарт JWT можно почитать на сайте организации RFC, а про реализацию для своего любимого языка — на сайте jwt.io.

Заключение

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *