Инструменты разработчика · Генератор UUID
Утечка бизнес-данных из последовательных идентификаторов: почему общедоступные API раскрывают UUID
· Почему это важно
uuid криптография API-интерфейс браузера
Идентификаторы с автоинкрементом сообщают посторонним, сколько заказов вы принимаете, и делают каждую запись перечислимой. В этом посте объясняется, что исправляет раскрытие UUID, а что нет, и как их внедрить без миграции.
Номера ваших счетов сообщают конкурентам о вашем объеме — утечка информации в /orders/10482
Конечная точка API, возвращающая /orders/10482, сообщает постороннему лицу больше, чем сами детали заказа. Числовой идентификатор сигнализирует о том, что вы обработали не менее десяти тысяч заказов, подразумевает информацию о темпах вашего роста и делает каждый заказ угадываемым. Простой цикл по последовательным номерам извлекает все записи без проверки подлинности или разрешений. Этот шаблон появляется повсюду — в URL-адресах, ключах базы данных, номерах счетов и идентификаторах транзакций — даже когда система требует аутентификации для просмотра любой отдельной записи. Проблема усугубляется в отчетности и анализе. Злоумышленник, который сможет получить /orders/1, /orders/2, и продолжить через /orders/10482, получит полное представление об истории и тенденциях ваших заказов.
Перечисление и очистка — как последовательные идентификаторы превращают одну открытую запись во все остальные.
Последовательная модель выявляет тенденции в том, когда поступают заказы, какие продукты упоминаются, а также закономерности ценообразования. Наблюдатель узнает, с какой скоростью растет или сокращается ваш бизнес. Эта информация, полученная только в результате перечисления идентификаторов, может использоваться в конкурентной стратегии, в качестве руководства для социальной инженерии или определения времени для других атак. Обнаружение не требует никаких затрат и отображается в URL-адресах, истории браузера, кэшированных страницах и журналах сервера. Это не теория: компании по конкурентной разведке и любопытные инженеры регулярно извлекают бизнес-показатели из публично перечисляемых идентификаторов. Выборка номеров заказов показывает уровень производства и общий объем любому, кто достаточно мотивирован для сбора данных и выполнения базового анализа.
Немецкая танковая задача в одном абзаце — подсчет итогов по выборке последовательных чисел
При переборе применяется статистический анализ для оценки общих объемов и отслеживания временных закономерностей. Если первый заказ был сделан в известную дату и вы фиксируете наличие десяти заказов, распределенных в течение недели, средний интервал оценивает общую скорость. Конкуренты, инвесторы и злоумышленники могут оценить вашу скорость, не получая доступа к каким-либо данным о клиентах, кроме самих идентификаторов. Последовательные идентификаторы гарантируют, что каждый идентификатор, превышающий текущее число, прогнозирует будущие заказы; каждый идентификатор ниже минимального в выборке подтверждает, что ранее ваша операция была меньше. Точки исторических данных создают временную шкалу роста и позволяют прогнозировать. Тот же принцип применяется во всех отраслях: финансовые транзакции, заказы на доставку, медицинские записи и любая система, раскрывающая последовательные идентификаторы.
Что исправляют UUID — неугадываемые ссылки и отсутствие сигнала роста в самом ID
Случайно сгенерированный UUID содержит 122 bits энтропии, если он сгенерирован из криптографически безопасного источника, поскольку RFC 9562 указывает для версии 4. Идентификатор не является угадываемым, неперечислимым и ничего не раскрывает внешним наблюдателям о темпах роста или объеме. Злоумышленник, знающий /orders/9a1f4e2b-7c3e-4d1a-8a5f-1b2c3d4e5f60, не может предсказать UUID следующего заказа или просмотреть ваши исторические идентификаторы с какой-либо разумной уверенностью. UUID сам по себе становится уникальной, но совершенно непрозрачной ссылкой. Случайное распределение означает, что множественные запросы не выявляют никаких закономерностей, прогресса и скорости для внешних наблюдателей, наблюдающих за вашим API.
Чего не исправляют UUID — неугаданный ID не является авторизацией, и за ним по-прежнему нужны проверки доступа к неизвестности.
Замена последовательных идентификаторов на UUID в общедоступных API проста с эксплуатационной точки зрения и не требует сложной координации между системами. Добавьте столбец UUID в таблицу заказов, создавайте его для каждого нового заказа, отображайте UUID в ответах и постепенно отказывайтесь от числового ключа. Ваши внутренние системы могут продолжать использовать целочисленные первичные ключи для повышения производительности и простоты; меняется только публичный интерфейс. Старый последовательный идентификатор остается в базе данных для вашей собственной справки или контрольного журнала, но клиенты и третьи лица видят только UUID. Этот подход с использованием двойного ключа является лучшей практикой для поддержания существующей производительности индекса при одновременном раскрытии непрозрачных идентификаторов внешнему миру.
Рабочий пример — добавление общедоступного столбца UUID рядом с внутренним целочисленным ключом и предоставление доступа только к первому.
Этот подход отличается от фактической авторизации, поскольку UUID не является паролем, а скрытность не является мерой безопасности. Клиент, имеющий законный доступ к /orders/{their-uuid}, должен иметь возможность просмотреть его, но /orders/{someone-elses-uuid} все равно должен быть отклонен вашими проверками доступа. UUID скрывает номер заказа от случайного просмотра и предотвращает статистический анализ посредством перечисления, но за логику аутентификации и авторизации отвечает код вашего приложения. Защита многоуровневая: UUID предотвращает утечку информации в самом идентификаторе, а контроль доступа определяет, кто может действовать с этим идентификатором.
Чего это не касается — компромисс между индексом и производительностью случайных ключей, обсуждаемый в отдельном посте.
Операционная граница имеет значение, поскольку UUID устраняют утечку информации в самом идентификаторе, но не заменяют механизмы контроля доступа. Если у клиента есть ключ API и достаточные разрешения, он все равно может отправлять запросы к вашей системе. Объем доступа к ним определяется вашей моделью разрешений и определениями ролей, а не форматом идентификатора. Преимущество UUID заключается лишь в том, что идентификатор перестает транслировать данные об объеме, последовательности и росте всем, кто может его наблюдать. Хорошо спроектированная система сочетает в себе непрозрачность UUID с явной проверкой контроля доступа при каждом запросе к API.
Вывод: отделите общедоступные ссылки от внутренних ключей — генератор ToolAcre предоставляет UUID, поддерживаемые CSPRNG, для общедоступной стороны.
Практическая миграция позволяет избежать «дня флага», поскольку постепенно поддерживает оба формата. Если вы создаете версии своих конечных точек, v1 API может продолжать возвращать целочисленные идентификаторы, а v2 возвращает UUID. Клиенты переходят в своем собственном темпе, не требуя скоординированного переключения. Ваши внутренние запросы к базе данных остаются неизменными: они по-прежнему фильтруются по целочисленному идентификатору, поскольку ваши индексы построены на этом столбце, а ваши внешние ключи ссылаются на него. Изменяются только данные, возвращаемые клиентам. Генератор ToolAcre UUID создает формат версии 4, который вы будете использовать; каждый результат представляет собой правильный RFC 9562 UUID готовый к сценариям хранения, развертывания и постепенной миграции.