open atlas
↑ К треку
Безопасность облака и инфраструктуры CLOUD · 04 · 04

Data security and KMS

Шифрование at-rest стоит ровно столько, скольких принципалов пускает политика ключа. Данные защищает envelope-шифрование KMS и deny-by-default политика ключа — а не галочка про AES.

CLOUD Senior ◷ 18 min
Уровень
ОсновыJuniorMiddleSenior

Разбор инцидента окончен, и вердикт тот же, что ты видел трижды за этот год: бакет был зашифрован. «Server-side encryption with KMS» — стоит галочка, чекбокс комплаенса зелёный, аудитор подписал. И всё же 40 миллионов записей клиентов ушли наружу в открытом виде. Атакующий ни разу не коснулся шифротекста. Он перехватил слишком широкую IAM-роль, вызвал kms:Decrypt — и сервис KMS, делая ровно свою работу, выдал ему дата-ключ и расшифровал всё. Шифрование at-rest не отказало. Оно сработало идеально — для не того принципала. Контролем, который имел значение, был не шифр. Это была политика ключа — и её никто не прочитал.

К концу урока ты поймёшь, почему «зашифровано at-rest» само по себе — почти бессмысленная гарантия, как envelope-шифрование с KMS на деле переносит границу безопасности на решение о доступе и как написать политику ключа, в которой Decrypt становится сложной частью, а не бесплатной.

Что на самом деле даёт «шифрование at-rest»

Начнём с неудобной правды: server-side шифрование at-rest защищает ровно от одной угрозы — что кто-то физически унесёт диск или прочитает сырой носитель из-под работающей системы. И всё. Украденный диск, списанный SSD без затирания, снапшот, скопированный уставшим инженером не в тот аккаунт: против этого at-rest шифрование реально и ценно. Это нижняя планка.

Оно ничего не делает против угрозы, которая случается на деле. Когда приложение читает строку, слой хранения прозрачно расшифровывает её первым — в этом и весь смысл прозрачного шифрования. Поэтому любой принципал, который может заставить твой сервис прочитать данные или может вызвать decrypt-API напрямую, получает открытый текст. SQL-инъекция возвращает открытый текст. Утёкшая учётка БД возвращает открытый текст. Сверхпривилегированная IAM-роль с вызовом kms:Decrypt возвращает открытый текст. Шифрование невидимо для атаки, потому что оно невидимо для любого легитимного чтения, а атакующий едет на легитимном пути чтения. «Данные зашифрованы at-rest?» — неверный вопрос аудита. Вопрос — «кто может вызвать их расшифровку?», и ответ живёт в IAM и политике ключа, а не в конфиге хранилища.

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

Envelope-шифрование: почему никто не шифрует данные прямо через KMS

Ты не можешь отправить файл на 4 ГБ в KMS на шифрование. Аппаратные сервисы ключей ограничивают прямой encrypt несколькими килобайтами (AWS KMS: 4 КБ), потому что мастер-ключи никогда не покидают HSM — каждый байт, который ты хочешь зашифровать, делал бы сетевой round-trip внутрь границы и обратно. Поэтому вся индустрия использует envelope-шифрование, и понимание его двухключевой структуры — то, что делает всё остальное осмысленным.

Есть два слоя ключей:

  • Дата-ключ (DEK) — свежий симметричный ключ (например, AES-256), генерируемый на каждый объект или на логическую область. Он шифрует сами байты, локально, на полной скорости. Это ключ, делающий основную работу.
  • Ключ шифрования ключей (KEK), он же мастер-ключ или CMK, — долгоживущий ключ, который никогда не покидает KMS/HSM. Его единственная задача — шифровать и расшифровывать дата-ключи.

Поток: ты просишь KMS сгенерировать дата-ключ. Он выдаёт его дважды — один раз в открытом виде (используй сейчас, в памяти) и один раз уже зашифрованным под KEK («обёрнутый» или «зашифрованный дата-ключ»). Ты шифруешь полезную нагрузку открытым DEK, затем немедленно стираешь открытый DEK из памяти и хранишь обёрнутый DEK прямо рядом с шифротекстом. Чтобы прочитать данные обратно, ты отправляешь обёрнутый DEK в KMS, KMS вызывает Decrypt с помощью своего KEK, возвращает открытый DEK, ты расшифровываешь нагрузку и снова стираешь DEK.

Почему эта структура оправдывает свою сложность: основные данные никогда не пересекают границу KMS, поэтому ты держишь AES на скорости канала; единственное, чего KMS вообще касается, — крошечный обёрнутый DEK. И она даёт два независимых рычага отзыва. Ты можешь ротировать KEK, не перешифровывая ни одного байта данных, — лишь маленькие обёрнутые DEK нужно переобернуть. А поскольку открытый DEK существует лишь временно в памяти приложения, долговременная безопасность всех твоих данных сводится к долговременной безопасности одной вещи: доступа к вызову Decrypt на KEK. Этот схлоп — петабайты конфиденциальности, держащиеся на одном решении о контроле доступа, — ровно поэтому политика ключа и есть настоящий артефакт.

Почему это работает

Зачем генерировать новый дата-ключ на каждый объект, а не переиспользовать один быстрый локальный ключ на всё? Радиус поражения и крипто-гигиена. Один DEK, шифрующий миллионы записей, — единая точка компрометации: утеки его раз (дамп кучи, выгруженная страница, лог расшифрованного материала) — и каждая запись, которой он касался, раскрыта, без возможности отозвать только одну. DEK на объект (или на тенанта) означает, что утёкший открытый DEK раскрывает только свою область, и ты можешь крипто-шреднуть одного тенанта, уничтожив его обёрнутый DEK, — шифротекст становится безвозвратно нечитаемым шумом, не трогая данные других тенантов. Это ещё и держит каждый отдельный ключ хорошо под лимитами объёма данных, которые ослабляют уникальность nonce у AES-GCM на масштабе.

Политика ключа — это и есть контроль безопасности

Вот часть, которую команды пропускают, и причина, по которой пробой из Hook повторяется: политика ключа и IAM-права вокруг kms:Decrypt и есть контроль шифрования at-rest. Шифр — это коммодити; решение о доступе — это продукт.

Здравая политика ключа — это deny-by-default и least-privilege над ключом, та же дисциплина, что ты применил бы к любому ресурсу, — просто применённая к одному ресурсу, который держит на замке всё остальное:

  • Сузь Decrypt до наименьшего набора принципалов, которым действительно нужен открытый текст. Сервису приёма, который пишет зашифрованные строки, часто нужен только GenerateDataKey (создавать новые DEK), а Decrypt — вообще нет: он не читает обратно. Аналитической задаче Decrypt может быть нужен, но только через конкретную роль. Большинства людей и большинства сервисов в политике ключа быть вообще не должно.
  • Ограничивай условиями, а не только принципалами. Используй encryption context (дополнительные аутентифицируемые данные), чтобы обёрнутый DEK тенанта A буквально не мог быть расшифрован под запросом, заявляющим тенанта B, — вызов Decrypt падает, потому что AAD не совпадает. Привязывай grant к исходному VPC, к конкретной сессии роли, к конкретному ресурсу. Голый Allow Decrypt на * — это та политика, что потеряла 40 миллионов записей.
  • Разделяй администраторов ключа и пользователей ключа. Тот, кто может вызывать Decrypt, не должен также мочь переписать политику ключа, чтобы выдать себе больше, — а тот, кто может менять политику, не должен незаметно мочь читать данные. Это separation of duties применительно к ключу, и именно это не даёт одной скомпрометированной роли и читать данные, и стирать улики того, что она могла.

Зрелый рефлекс: когда видишь «зашифровано через KMS», твой следующий клик — политика ключа, и ты читаешь её как список контроля доступа, спрашивая: какие принципалы могут превратить шифротекст обратно в открытый текст, при каких условиях и кто может изменить этот ответ. Если политика — дефолт AWS (root-аккаунт + широкий admin), данные фактически защищены твоей общей IAM-гигиеной и ничем более конкретным — шифрование делает пиар, а не оборону.

УгрозаТолько at-rest шифрованиеЧто её реально останавливает
Украденный диск / незатёртый SSDОстанавливает — это та самая угроза, ради которой оноСамо at-rest шифрование
Снапшот скопирован не в тот аккаунтОстанавливает, только если целевой аккаунт не может использовать KEKПолитика ключа, ограниченная исходным аккаунтом
Сверхпривилегированная роль вызывает kms:DecryptЗащиты нет — KMS расшифровывает для неёLeast-privilege политика ключа + условия
SQL-инъекция / утёкшая учётка БДЗащиты нет — путь чтения авто-расшифровываетAuthz на уровне приложения; шифрование — не тот инструмент
Нужно навсегда уничтожить данные одного тенантаТяжело — надо перезаписать каждую записьКрипто-шред: уничтожить обёрнутый DEK этого тенанта

Ротация, шреддинг и сбойные сценарии

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

Ротация. Автоматическая ротация KEK (например, ежегодная) не перешифровывает твои данные и не переобёртывает хранимые DEK — она добавляет новую версию KEK и использует её для новых операций обёртывания, держа старые версии доступными для распаковки существующих DEK. Поэтому ротация дешева и поэтому те, кто ждёт от неё «переzащиты старых данных», ошибаются: DEK, обёрнутый под версией KEK 2023 года, всё равно распаковываем вечно, пока ты активно не переобернёшь его. Истинное уничтожение ключа (удаление версии KEK) — единственное, что делает его обёрнутые DEK — а значит и нижележащий шифротекст — безвозвратно невосстановимыми. Это механизм крипто-шреддинга: чтобы сделать данные невосстановимыми по требованию (запрос на удаление по GDPR, списанный тенант), ты не скребёшь петабайты — ты уничтожаешь маленький обёрнутый DEK, единственный путь к этим данным, и шифротекст мгновенно становится необратимым шумом.

Сбойные сценарии, которые надо уважать:

  • Потеря или уничтожение KEK, который ещё был нужен, — это невосстановимая потеря данных by design: нет восстановления, нет тикета в саппорт, нет бэкдора. То же свойство, что делает крипто-шред мощным, делает случайное удаление ключа катастрофой. AWS навязывает обязательный период ожидания 7–30 дней на удаление ключа именно потому, что операция необратима.
  • Вызов Decrypt — жёсткая рантайм-зависимость. Если KMS недостижим, или ты пересёк регион, где ключа нет, или попал в лимит частоты запросов на ключ во время всплеска трафика, твои чтения начинают падать — данные целы, но не расшифровываемы, пока KMS не ответит. Envelope-шифрование меняет гарантию конфиденциальности на зависимость доступности от сервиса ключей, и ты должен планировать троттлинг KMS и региональную доступность ключа так же, как планировал бы любую критическую зависимость.
  • Забыть стереть открытый DEK превращает всю схему в театр. Если открытый DEK задержался в логе, дампе кучи, кеше или артефакте краша, атакующий, прочитавший его, пропускает KMS целиком. Обёрнутый DEK безопасно хранить где угодно; открытый DEK радиоактивен и должен жить только временно в памяти.

Свяжи это обратно с детектированием и постурой: политика ключа — статический артефакт, который можно сканировать (постура), а вызовы Decrypt — события, которые можно мониторить (детектирование). Модель непрерывного мониторинга NIST SP 800-137 применяется напрямую — аномальный всплеск kms:Decrypt от роли, которая обычно только пишет, или Decrypt, чей encryption context не совпадает с ожидаемым тенантом, — один из самых сигнальных алертов, что ты можешь поставить, потому что по дизайну выше он сидит ровно на той единственной границе, что имеет значение.

Выбери лучший вариант

Скан комплаенса рапортует «S3-бакет зашифрован через KMS — PASS». В бакете PII клиентов. Ты security-ревьюер — каков твой следующий шаг?

Викторина

Почему envelope-шифрование использует дата-ключ на объект (DEK), обёрнутый мастер-ключом (KEK), а не шифрует данные напрямую мастер-ключом KMS?

Викторина

Бакет хранения зашифрован at-rest через KMS. Атакующий крадёт валидную учётку БД и запрашивает данные обычным путём чтения. Что он получит?

Расставь шаги по порядку

Упорядочь путь записи envelope-шифрования, от запроса ключа до безопасного сохранения результата:

  1. 1 Вызвать KMS GenerateDataKey для KEK
  2. 2 Получить DEK дважды: открытый + обёрнутый под KEK
  3. 3 Зашифровать нагрузку локально открытым DEK
  4. 4 Стереть открытый DEK из памяти
  5. 5 Сохранить шифротекст рядом с обёрнутым DEK
Вспомните перед уходом
  1. 01
    Объясни, почему «бакет зашифрован at-rest через KMS» почти ничего не говорит о том, защищены ли данные на деле, и на что смотреть вместо этого.
  2. 02
    Пройди envelope-шифрование по шагам и объясни, что оно даёт по сравнению с прямым шифрованием данных мастер-ключом KMS.
Итог

Шифрование at-rest защищает от одной узкой угрозы — что кто-то прочитает сырой носитель — и ни от чего больше, потому что любой легитимный путь чтения прозрачно расшифровывает данные до того, как их увидит приложение. Это значит, что утёкшая учётка, SQL-инъекция или слишком широкая IAM-роль с вызовом kms:Decrypt — все уходят с открытым текстом, пока чекбокс «зашифровано» остаётся зелёным. Envelope-шифрование — это то, как ты превращаешь это в нечто защитимое: дата-ключ на объект (DEK) шифрует основные данные локально на полной скорости, этот DEK обёрнут мастер-ключом (KEK), который никогда не покидает HSM, а обёрнутый DEK хранится рядом с шифротекстом. Тогда вся безопасность схемы схлопывается до одного решения о контроле доступа — кто может вызвать Decrypt на KEK, — поэтому политика ключа, ограниченная deny-by-default и least-privilege с условиями вроде encryption context и разделения админов ключа и пользователей ключа, и есть настоящий контроль, а не шифр. Двухключевой дизайн ещё и даёт дешёвую ротацию KEK (без перешифрования данных) и крипто-шреддинг (уничтожь один обёрнутый DEK, чтобы сделать ровно эти данные невосстановимыми) — ценой того, что Decrypt становится жёсткой зависимостью доступности, а случайное удаление ключа — необратимым. Так что в следующий раз, когда скан скажет «зашифровано через KMS — PASS», твой первый ход — открыть политику ключа и спросить: какие принципалы могут превратить этот шифротекст обратно в открытый текст, при каких условиях и кто может изменить этот ответ?

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 6 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

Примени это

Примени этот урок в реальном проекте.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.