Редактируйте секреты до вставки

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

Почему секреты оказываются в тикетах, чатах и логах

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

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

Что сканер может обнаружить: формы, контрольные суммы и структуру

Хорошая новость в том, что настоящие учётные данные сильно узорны, а сканирование по шаблонам детерминировано: тот же текст всегда даёт те же находки, без угадывающей модели между ними. Ключи поставщиков несут опубликованные формы — префиксы, фиксированные длины, ограниченные алфавиты, — поэтому ключ доступа AWS, токен GitHub, ключ Stripe или токен Slack можно узнать с первого взгляда, как человек узнаёт номер телефона в абзаце. Закрытые ключи объявляют о себе строками брони BEGIN и END, а JSON Web Token имеют жёсткую трёхсегментную структуру, первые два сегмента которой всегда начинаются одинаково, потому что всегда кодируют один и тот же вид JSON.

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

Что сканер не может обнаружить: энтропию и контекст

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

Контекст — большее слепое пятно, потому что почти всё, что делает значение опасным, находится вне значения. Сессионная cookie — просто буквы и цифры, пока вы не узнаете, какой сервис она отпирает. Пароль базы данных выглядит безобидно внутри строки подключения, распределённой между тремя переменными окружения, а одноразовый код чувствителен только десять минут. Сканеры также не видят сквозь структуру: секрет, перенесённый через две строки лога, закодированный в base64 внутри блоба или сфотографированный в изображение, невидим для текстовых шаблонов, какими бы хорошими они ни были. Честный итог таков: сканер надёжно ловит документированное, хорошо сформированное большинство — а предпросмотр, который он вам показывает, с подсвеченными на месте совпадениями, всё же заслуживает вашего собственного десятисекундного просмотра, потому что ваши глаза знают контекст, которого шаблоны знать не могут.

Есть ещё один класс, к которому сканер намеренно слеп, и он находится прямо рядом с ловушкой: заполнители. Значения документации — содержащие слова вроде example, test, dummy или your- — исключаются, чтобы руководства и учебные материалы не зажигали таблицу находок. Но каждое исключение — это дверь: настоящий ключ, случайно содержащий одно из этих слов, или ленивый настоящий пароль, установленный в похожее на заполнитель значение, проходит молча. Обращайтесь со списком исключений как с контролем шума, никогда — как с гарантией, и никогда не помечайте настоящие учётные данные словами-заполнителями, чтобы заставить сканер молчать.

Проблема канонического фальшивого примера

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

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

Ротируйте, а не просто удаляйте — и делитесь безопасно

Если настоящий секрет уже был вставлен без редактирования, порядок операций имеет значение, а удаление идёт последним, если вообще идёт. Предположите, что значение было скопировано — индексом, уведомлением, скриншотом, цитатой коллеги, — и обращайтесь с ним как с публичным: сначала идите к поставщику и ротируйте учётные данные, отзывая старые, чтобы утечённая строка перестала работать, где бы она ни выжила. Только тогда удаляйте или редактируйте исходное сообщение, как гигиену, а не как исправление. Руководство OWASP по управлению секретами и проект gitleaks, оба перечисленные ниже, существуют для двух половин этого урока: управлять секретами так, чтобы они были короткоживущими и ограниченными по объёму, и сканировать репозитории и истории в предположении, что вставки уже произошли. Сопутствующая проблема для захватов браузера разбирается в перед тем, как отправить тот файл HAR.

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

Источники и дальнейшее чтение

Частые вопросы

Я уже вставил настоящий секрет в тикет. Что делать сначала?

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

Делает ли отредактированная копия текст полностью безопасным для обмена?

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

Почему сканер отмечает пример ключа AWS, если он фальшивый?

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