Русский

Инструменты разработчика · Кодер и декодер Base64

Как заголовок базовой аутентификации HTTP создается и декодируется с помощью Base64

· Как это работает

base64 безопасность

HTTP Базовый заголовок аутентификации с именем пользователя:паролем в кодировке Base64
Оригинальная векторная иллюстрация ToolAcre

Заголовок Authorization: Basic — это просто имя пользователя:пароль, проходящий через Base64. В этом посте показано, как строится значение, как его декодировать из журнала запросов и почему кодировка ничего не скрывает.

401, который сохраняется, хотя учетные данные верны — значение заголовка, которое декодируется в слегка неверную строку.

HTTP API возвращает 401 Unauthorized и ожидает заголовок Authorization: Basic. Значением является слово схемы Basic, один пробел и строка Base64. Отсутствующий префикс, закодированный префикс или незамеченная новая строка меняют то, что получает сервер, даже если видимое имя пользователя и пароль выглядят правильно.

Декодируйте эту строку, и она прочитает имя пользователя:пароль (буквально двоеточие между двумя). Байты имя пользователя:пароль кодируются UTF-8, а затем кодируются Base64, создавая значение заголовка. Если учетные данные — admin:s3cret, UTF-8 байт — 0x61 0x64 0x6D 0x69 0x6E 0x3A 0x73 0x33 0x63 0x72 0x65 0x74 (буквы ASCII плюс двоеточие), создается кодировка Base64. YWRtaW46czNjcmV0, а заголовок — Authorization: Basic YWRtaW46czNjcmV0.

Рецепт от RFC 7617: 'user:pass', UTF-8, Base64 — точные шаги и роль двоеточия

Это полная HTTP базовая схема аутентификации, определенная в RFC 7617. Он прост, стандартизирован и сам по себе не обеспечивает никакой безопасности: любой, кто читает заголовок, может немедленно расшифровать его и прочитать пароль. Вот почему HTTPS является обязательным для базовой аутентификации. Кодирование — это требование транспорта, а не функция безопасности. Пароль передается в виде UTF-8 байт, как и любые другие данные; Base64 — это просто обозначение, используемое в протоколе HTTP.

Если вам необходимо декодировать заголовок Basic из сетевого журнала, процесс прост: удалите Basic, остаток декодирования Base64, и у вас есть имя пользователя:пароль. Двоеточие является разделителем между именем пользователя и паролем. RFC 7617 указывает, что учетные данные представляют собой идентификатор пользователя: пароль, а первое двоеточие является разделителем. Если пароль содержит двоеточие, второе двоеточие — это просто еще один символ пароля. Двоеточие является структурным, поскольку получателю нужна одна однозначная граница. Он ищет первое двоеточие после декодирования; все, что до него идентифицирует пользователя, и все, что после него, является паролем. Таким образом, отсутствие двоеточия указывает на неправильный формат пары учетных данных, а не на проблему с алфавитом Base64.

Рабочий пример: кодирование admin:s3cret и декодирование заголовка из журнала — в обоих направлениях, включая ошибку с завершающим символом новой строки.

Если имя пользователя — admin, а пароль — pass:word, учетные данные — admin:pass:word, что кодируется в YWRtaW46cGFzczp3b3Jk. При декодировании необходимо разделить только первое двоеточие, указав имя пользователя admin и пароль pass:word. Разделение на каждое двоеточие приведет к неправильному разделению пароля. Параметр charset в RFC 7617 указывает, что учетные данные закодированы UTF-8. Это означает, что символы, отличные от ASCII, в именах пользователей и паролях преобразуются в UTF-8 байт перед кодированием Base64.

Если имя пользователя — cafe (с ударением e), байты UTF-8 — это 0x63 0x61 0x66 0xC3 0xA9 (четыре байта для букв ASCII плюс два для символа с акцентом), а полные учетные данные cafe:password содержат байты для cafe, затем байт двоеточия 0x3A, а затем пароль. Вывод Base64 точно кодирует все байты. Декодер должен уметь интерпретировать декодированные байты как текст UTF-8, а не Latin-1.

Пароли, содержащие двоеточия, пробелы и не-ASCII — почему первое двоеточие разбивается и для чего нужен параметр charset

Рабочий пример: начните с admin:s3cret. Преобразование в UTF-8 байт: a=0x61, d=0x64, m=0x6D, i=0x69, n=0x6E, :=0x3A, s=0x73, 3=0x33, c=0x63, r=0x72, e=0x65, t=0x74. В десятичном виде: (97, 100, 109, 105, 110, 58, 115, 51, 99, 114, 101, 116). Base64 кодирует эти 12 bytes: группы в четыре группы по три (создает четыре группы по четыре символа Base64).

Закодированное значение — YWRtaW46czNjcmV0. Заголовок авторизации — Authorization: Basic YWRtaW46czNjcmV0. Сторона пароля может содержать еще одно двоеточие без перемещения первой границы. Пробелы и текст, отличный от ASCII, также сохраняются, если оба узла согласовали кодировку текста. ToolAcre может проверять байты UTF-8, которые он выдает, но более старый сервер, который ожидает другую кодировку, остается проблемой совместимости за пределами преобразования Base64.

Почему это небезопасно без TLS — декодирование показывает пароль всем, кто видит заголовок

Чтобы декодировать полученный заголовок, разделите Basic, Base64 декодируйте YWRtaW46czNjcmV0, чтобы вернуть байты, интерпретируйте как текст UTF-8, чтобы получить admin:s3cret, разделите его на первое двоеточие, чтобы извлечь имя пользователя и пароль. Распространенной ошибкой является вывод новой строки из echo. Если запустить echo admin:s3cret | base64 в оболочке Unix, echo по умолчанию добавляет новую строку, поэтому закодируйте admin:s3cret с новой строкой (13 bytes вместо 12).

Вывод Base64 отличается: YWRtaW46czNjcmV0Cg== (заполнение и дополнительные символы). Заголовок авторизации с этим значением не будет выполнен, поскольку пароль содержит символ новой строки. Исправление — использовать echo -n или передать через printf или инструмент, который не добавляет символы новой строки. Кодер и декодер Base64 позволяет избежать этого: кодирует именно то, что вы вставляете, без скрытых символов новой строки. TLS изменяет транспортную угрозу, а не формат учетных данных. Внутри защищенного соединения заголовок шифруется вместе с остальной частью запроса; как только программное обеспечение регистрирует или отображает его, значение Base64 снова предоставляет повторно используемые учетные данные любому, кто может его декодировать. Редактирование по-прежнему имеет значение в каждой точке наблюдения.

Распространенные ошибки — новая строка из echo, отсутствующий префикс «Basic» и двойное кодирование значения.

Еще одна ошибка: отсутствует базовый префикс. Значение заголовка авторизации недопустимо только для Base64; это имя схемы (Basic, Bearer или другие), за которым следует пробел, а затем учетные данные. Некоторые системы не распознают YWRtaW46czNjcmV0 в качестве учетных данных, но успешно используют базовый YWRtaW46czNjcmV0. При отладке 401 проверьте, правильно ли сервер анализирует заголовок авторизации.

Схема нечувствительна к регистру в стандарте HTTP, но многие реализации чувствительны к регистру; проверьте документацию API. Двойное кодирование — еще один вид сбоя. Если строка кодировки Base64 уже закодирована в Base64, на выходе будет другая строка. Кодирование YWRtaW46czNjcmV0 создает WVdkbWFXNDZjek5qY3JldA== (совершенно другое). Некоторые системы могут случайно применить кодировку дважды: один раз во время настройки учетных данных и второй раз при создании заголовка. Особенно легко пропустить новую строку в команде оболочки, поскольку ее можно закодировать как часть учетных данных, а не отклонять как пробелы вокруг Base64. Полученный заголовок аккуратно декодируется в пароль с дополнительным байтом, создавая 401, который выглядит как ошибка аутентификации на стороне сервера.

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

Декодер ожидает один уровень Base64, поэтому двойное кодирование приводит к несоответствию. Вот почему регистрация значений учетных данных в форме Base64 (а не в виде открытого текста) может сбить с толку: если кто-то применит декодирование один раз, он увидит имя пользователя и пароль; если применить дважды, они увидят запутывание. Дайджест-аутентификация (RFC 7616) и аутентификация носителя (для токенов OAuth) используют разные схемы, каждая из которых имеет разные форматы учетных данных.

Дайджест требует, чтобы сервер отправлял одноразовый номер, клиент вычислял хеш, а заголовок включал хэш плюс имя пользователя, а не пароль. Носителем обычно является веб-токен JSON (JWT), который имеет кодировку Base64url, но без префикса имени пользователя. Базовая аутентификация проще, чем обе, но совершенно небезопасна без TLS, поскольку учетные данные читаются в заголовке. Digest и Bearer используют одно и то же поле заголовка авторизации, но придают своим значениям совершенно разное значение. Запросы учетных данных браузера добавляют пользовательский интерфейс и поведение кэширования поверх базового. В этой статье мы останавливаемся на создании и проверке полезных данных базовых учетных данных, а не на сравнении этих систем аутентификации.

Вывод: базовая аутентификация — это Base64, а не защита — как кодировщик и декодер Base64 позволяют проверять значение заголовка локально, не отправляя куда-либо учетные данные.

Если API поддерживает несколько схем аутентификации, выберите наиболее безопасную из доступных. Кодер и декодер Base64 могут помочь отладить ошибку базовой аутентификации: вставьте строку учетных данных (имя пользователя, двоеточие и пароль), и инструмент немедленно выдаст значение Base64. Сравните результат с отправкой заголовка, и вы увидите несоответствие. И наоборот, вставьте значение заголовка из сетевого журнала, удалите базовый префикс, декодируйте, чтобы увидеть, что увидел сервер.

Для обучения вставьте admin:s3cret и наблюдайте за выводом, затем измените пароль, чтобы увидеть, как меняется Base64. Понимание того, как создается заголовок, объясняет, почему для декодирования требуется знание формата RFC и почему двоеточие является структурным элементом, а не Base64. Локальная проверка должна использовать придуманные учетные данные, а не действующий пароль, скопированный из производства. Закодируйте пару, переместите вывод обратно на панель ввода и декодируйте его. Соответствие знаков препинания и точных конечных символов подтверждает представление туда и обратно, прежде чем заголовок будет отправлен куда-либо.