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

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

Подробнее я затрагивал вопросы по дампу ОЗУ на вебинаре «Слёрм» о том, как прятать секреты приложения и в докладе про безопасную доставку секретов на Deckhouse Conf 2025. Но в этих выступлениях не было решения, о котором я расскажу в статье. 

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

Секреты под прицелом

Простые системы хранения секретов (далее — СХС) либо совсем не шифруют данные, либо могут хранить ключ для шифрования в каком-то файле на диске. Более продвинутые не хранят ключ в персистивном хранилище: он находится только в памяти процесса. И тут остро встает вопрос «доверенной среды исполнения». 

Если ваша СХС работает на «железном» сервере, то извлечь что-то из его памяти, не внося изменений в аппаратную конфигурацию, довольно проблематично. А тем более сделать это незаметно, не выключая машину.

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

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

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

Как проблему решают производители ПО

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

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

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

На ПЭВМ и в виртуальной среде не должны устанавливаться средства разработки ПО и отладчики. Если средства отладки приложений нужны для технологических потребностей организации, то их использование должно быть санкционировано администратором безопасности. При этом должны быть реализованы меры, исключающие возможность использования этих средств для редактирования кода и памяти СКЗИ и приложений, использующих СКЗИ, а также для просмотра кода и памяти СКЗИ и приложений, использующих СКЗИ, в процессе обработки СКЗИ защищаемой информации и/или при загруженной ключевой информации.

Или даже такое:

На снапшот ВМ, сделанный после ввода ключевой информации, должны распространяться требования по обращению с ключевыми носителями.

То есть запрет на снапшотинг памяти или отладку ПО реализуется не столько или не только за счёт самого ПО, сколько административными мерами защиты.

Но что, если мы полны паранойи и не то чтобы не доверяем административным методам, а всё-таки хотим добавить технологических ограничений? Что можно предпринять в таком случае?

Как HashiСorp Vault шифрует данные

Давайте рассмотрим на примере HashiСorp Vault, как происходит шифрование:

Клиент — приложение или пользователь — подключается к Vault и отправляет запрос на чтение данных. Эти операции шифруются TLS (зелёный цвет на схеме). Если операция чтения провалидирована на router, то происходит чтение из зашифрованного с помощью AES хранилища Storage (оранжевый цвет). Данные расшифровываются с помощью ключа key, хранящегося в памяти процесса. В этот момент расшифрованный блок данных присутствует в памяти Vault в открытом виде — вплоть до передачи клиенту.

Если сделать снимок ВМ в этот момент, можно получить доступ к этому конкретному секрету. Но основная проблема в том, что также можно получить и доступ к ключу key. А имея доступ к зашифрованному Storage или снапшоту Vault, можно расшифровать его целиком. То есть получить доступ не только к секрету, который был прочитан в какой-то конкретный момент времени, а вообще ко всем секретам в системе. И — что самое неприятное — со стороны хранилища секретов не будет никаких аудит-логов про то, что такой доступ был получен, ведь извлечение данных может происходить без участия СХС.

Действительно ли проблема существует?

Vault шифрует свои данные с помощью AES256-GCM96. То есть это не только шифрование, но и аутентификация зашифрованных данных, AEAD (Authenticated Encryption with Associated Data). С одной стороны, это даёт возможность при расшифровке проверить, что данные были зашифрованы именно этим ключом, а не просто какой-то мусор подложили. А с другой… позволяет проверить, что данные были зашифрованы именно этим ключом!

То есть если снять дамп памяти, разбить его на части по 32 байта (256 бит) и пробовать расшифровывать заведомо существующую в Vault и расшифровываемую запись (например, core/master), то путём вполне конечного перебора можно найти те самые 32 байта, с помощью которых проверка AEAD пройдёт.

Внешнее шифрование

В такой непростой ситуации поможет дополнительное шифрование — seal wrap, которое мы реализовали в Deckhouse Stronghold EE.

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

На схеме синим цветом обозначены данные, зашифрованные одновременно и AES (с помощью ключа key), и неизвлекаемым ключом, находящимся внутри HSM. При этом на стороне HSM доступ к открытым данным не предоставляется, так как он работает с данными, зашифрованными AES-шифрованием. Даже если злоумышленник внедрится в канал связи с HSM, к открытым данным он доступ не получит.

В данной схеме — даже в случае утечки ключа key из памяти СХС — будет невозможно расшифровать данные из Storage. Максимум — это данные из cache, то есть те секреты, которые были явно прочитаны в процессе работы с хранилищем. Для ещё большей безопасности cache можно отключить. Это снижает производительность системы (каждый запрос на чтение явным образом читается из Storage и расшифровывается через HSM и AES), но снижает угрозу утечки секретов через снапшот памяти виртуальной машины.

На практике бывает так, что не для всех типов секретов нужна такая безопасная безопасность, поэтому часть секретов можно шифровать дополнительным шифрованием, а часть — не шифровать. Администратор СХС сам выбирает, какие типы секретов должны быть обёрнуты дополнительным слоем шифрования.

Перешифрование данных

Может возникнуть резонный вопрос, а что делать, если потребуется сменить HSM или ключ в нём? Ведь данные в хранилище зашифрованы старым ключом. Для этого при сохранении данных в Storage в метаинформации записываются данные о ключе, которыми были дополнительно зашифрованы данные. Таким образом можно определить, какой ключ использовать при расшифровании прочитанных с хранилища данных.

Если мы подключим к системе два разных HSM (или один HSM, но в котором находятся разные ключи или который использует разные методы шифрования), то можно одновременно работать с данными, зашифрованными в хранилище разными ключами.

Для миграции на новый ключ в Stronghold дополнительно реализован метод rewrap. Он позволяет прочитать из хранилища все данные, зашифрованные «старым» ключом, перешифровать их «новым» ключом и сохранить в Storage. Это может быть полезно не только при смене HSM, но и при плановой ротации ключей шифрования.

Когда нет HSM

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

Но что делать, если у нас нет HSM или же полностью облачная инфраструктура? Поможет ли как-то двойное шифрование, особенно в вариантах со снапшотом памяти ОС? Давайте разберёмся.

Помимо поддержки двойного шифрования через HSM-модули, Stronghold поддерживает двойное шифрование через другой Stronghold. Это так называемый механизм транзитного шифрования (transit). 

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

Поэтому даже при отсутствии HSM двойное шифрование может повысить безопасность ваших данных.

Приятные мелочи

При разработке Deckhouse Stronghold мы учитываем, что драйвером индустрии являлся (да и, наверное, является) HashiCorp Vault. Поэтому мы стараемся максимально поддерживать совместимость нашего продукта с HashiCorp Vault. 

Во-первых, с точки зрения API. Stronghold позволяет пользователю применять привычные инструменты и библиотеки, в том числе для работы с enterprise-функциями, например с такими, как autosnapshots (резервное копирование по расписанию) или namespaces. То есть ваши любимые библиотеки или Terraform-манифесты будут работать со Stronghold так, как если бы это был Vault Enterprise.

Во-вторых, мы стараемся поддерживать совместимость на уровне хранения данных. Если вы ранее пользовались Vault Enterprise, то сможете взять его бэкап или снапшот либо просто запустить Stonghold вместо Vault, и все ваши данные останутся на месте: пространства имён, секреты, права доступа, политики в пространствах имён и так далее. Например, OpenBao относится к совместимости более вольно: их реализация пространств имён несовместима с HashiСorp Vault, что усложняет возможную миграцию.

В случае с механизмом двойного шифрования мы придерживались такого же подхода. Вы можете взять данные от Vault Enterprise, которые были зашифрованы через HSM и Seal Wrap, запустить Stronghold — и все данные будут доступны в последнем. Для переезда не нужны никакие небезопасные «миграторы», вы просто запускаете новое приложение на старых данных.

Что даёт механизм двойного шифрования

Если говорить про Vault-совместимые хранилища секретов, то механизм двойного шифрования поддерживается в системах enterprise-уровня, таких как HashiCorp Vault Enterprise или Deckhouse Stronghold EE, и отсутствует в их младших версиях — HashiCorp Vault, Deckhouse Stronghold CE — и различных форках Vault, например в российских или OpenBao.

Что даёт пользователям двойное шифрование?

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

Российским пользователям оно позволяет легко внедрить сертифицированное шифрование ГОСТом хранимых данных. Если HSM поддерживает ГОСТ-шифрование, то данные в Storage будут зашифрованы ГОСТом. Это позволяет подстроиться под требование регуляторов.

А ещё двойное шифрование позволяет использовать HSM как «второй фактор» для работы СХС. 

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

P. S. 

Больше наших материалов по теме:

Комментарии (8)


  1. Litemanager_remoteadmin
    10.11.2025 08:22

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


    1. trublast Автор
      10.11.2025 08:22

      Основная идея не в том, что используется двойное шифрование (два "лучше" чем один, три "лучше" чем два и т.д.), а в том, что ключ для "второго типа шифрования" не присутствует в ОС, где запущена СХС (система хранения секретов) ни в каком виде. И таким образом можно закрыть потенциальную проблему возможной несанкционированной расшифровки данных если верхний слой инфраструктуры по отношению к СХС (например, ОС или же еще выше - система виртуализации) будет скомпрометирован.


      1. Kahelman
        10.11.2025 08:22

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

        Если Хаузер не может извлекать данные из ВМ клиента, то повторное шифрование не требуется. А если может, то оно не спасет


        1. trublast Автор
          10.11.2025 08:22

          Ну для начала у вас скорее всего не получится "Запустить свою ВМ и обратиться к вашему первому хранилищу". Почему?
          1. Запуск машины не будет "незамеченным". Помимо самого снапшота ВМ для запуска нужны какие-то права на запуск, в конце концов сами ресурсы для запуска (cpu/mem/disk), которые обычно квотированные.
          2. Для машины нужен будет какой-то адрес, с которого должен быть доступ до второй машины. И наверное он должен отличаться от адреса, с которым работает оригинальная машина. То есть потенциальная проблема доступа решится банально на уровне сетевых политик. У вас же надеюсь не проходной двор в виртуализации, где кто угодно запускает что угодно, где угодно, и с любыми сетевыми адресами?

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

          Понятное дело что сами от себя вы ваши пароли не убережете, но ведь цель не в этом.


          1. Kahelman
            10.11.2025 08:22

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

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


            1. trublast Автор
              10.11.2025 08:22

              Вы слишком упрощаете. В духе "рисуем круг, рисуем сову"

              Во-первых, нужно определиться, какого уровня доступ к кластеру получил этот "кто-то"

              Ну ладно, пусть даже самый суперпользовательский.

              Далее надо определиться, какие такие пароли он может "тупо стырить". Допустим это пароль для доступа к базе данных. Если сектерт инжектируется в память приложения, то в кубернетес его не существует, поэтому "тырить" из кубов нечего. Если пароль динамический, то "тырить" его смысла не имеет, он действителен для одного подключения (оба этих подхода кстати реализованы в модуле secrets-store-integration кубернетес-платформы Deckhouse)

              Единственный вариант - запускать поддельные версии приложений которые будут создавать новые пароли, но вместо подключения к базе будут выводить их, допустим, в логи. Но чтобы запускать эти приложения они должны быть доступны где-то внутри вашего контура с кубами. Но вы можете сделать закрытый контур, в котором есть доступ только к вашему проверенному реджистри. Поэтому Хакер сможет делать в вашем кубе "что угодно" (создавать любые манифесты в api), но запускать сможет только ваши доверенные приложения. Которые конечно же пароли в лог не пишут. То есть систему можно настроить так, что даже имея административный доступ а API куба доступа к данным приложений хакер не получит.

              То есть "может делать в кубе что угодно" не равно "может запускать в кубе что угодно".

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

              Конечно нет какой-то серебряной пули, вроде "включи вот эту настройку и хакер даже имея рут привилегии точно ничего у тебя не украдёт". Но можно сильно ограничить возможности хакера с root. Хотя конечно лучше не доводить дело до получения хакером root.


  1. IZh
    10.11.2025 08:22

    А если атакующий, взломавший виртуальную машину, неспешно через HSM просто зачитает всю базу в кэш? HSM её услужливо и расшифрует, если нет ограничений по числу запросов к HSM.


    1. trublast Автор
      10.11.2025 08:22

      Если нужна защита от такой угрозы - отключите кэш.

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

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

      Если у вас storage backend это внешняя база, например postgres, то такой аудит можно сделать даже на стороне базы, анализируя select-ы по значению where, или добавив триггер.

      То есть если вы даже не защитит есть от того, что данные прочитали, то вы точно узнаете про это. А вот в случае снапшота ВМ, без двойного шифрования, данные могут быть расшифрованы оффлайн, и вы про это не узнаете.