Как изолировать выполнение пользовательских шаблонов, чтобы компрометация исполнителя не дала доступ к данным самого сервиса?
Пользовательские шаблоны следует выполнять в отдельном изолированном окружении с минимальными привилегиями, отдельной идентичностью, ограниченными ресурсами и запрещённым доступом к внутренним сервисам и секретам. Основной защитный механизм — песочница на границе между недоверенным кодом и доверенной частью системы.
Одной проверки синтаксиса недостаточно: шаблон может использовать уязвимость движка или вызвать разрешённую, но опасную операцию. Поэтому безопасность должна обеспечиваться архитектурной изоляцией, а не только фильтрацией содержимого.
Песочницы появились как способ безопасно выполнять код, которому нельзя полностью доверять: пользовательские сценарии, плагины, документы и содержимое веб-страниц. Исходная проблема состояла в том, что анализ входных данных не мог гарантировать отсутствие всех опасных конструкций и ошибок интерпретатора.
Изоляция процессов, виртуальных машин и контейнеров позволила отделить выполнение потенциально опасного кода от данных и привилегий основной системы. На практике песочница рассматривается не как абсолютная гарантия, а как дополнительная граница безопасности, снижающая последствия компрометации исполнителя.
Шаблон может содержать обращения к файлам, переменным окружения, сетевым адресам или функциям движка, которые первоначально не считались опасными. Если исполнитель работает с правами основного сервиса, успешная атака на него может привести к чтению секретов, изменению данных, обращению к внутренним API или захвату других компонентов.
Даже полностью изолированный процесс может создать отказ в обслуживании: бесконечный цикл, чрезмерное потребление памяти, большое число сетевых запросов или генерацию огромного результата. Поэтому нужно защищать не только конфиденциальность и целостность, но и доступность.
Исполнитель размещают за отдельной границей доверия. Обычно это отдельный процесс или рабочая нагрузка с собственной учётной записью, без доступа к секретам основного сервиса, с минимальными правами файловой системы и только необходимыми системными возможностями.
Сетевой доступ по умолчанию запрещают. Если шаблону действительно нужны внешние данные, разрешают только конкретные направления через контролируемый посредник; прямой доступ к адресному пространству внутренних сервисов, метаданным облачной платформы и административным интерфейсам должен быть закрыт.
Для ограничения последствий применяют следующие меры:
Фильтрация шаблона и статический анализ полезны как дополнительный слой, но не должны быть единственным барьером. Чем сложнее язык шаблонов и чем больше разрешённых функций, тем выше поверхность атаки и стоимость безопасного аудита.
Выбор уровня изоляции зависит от модели угроз. Для простых шаблонов без логики безопаснее использовать ограниченный декларативный формат, чем полноценный язык. Для недоверенного кода с высокой ценностью защищаемых данных может потребоваться отдельная виртуальная машина или специализированный изолированный исполнитель, а не только процесс внутри общего окружения.
Платформа отчётности позволяла клиентам создавать шаблоны документов. Первый вариант выполнял их внутри процесса API-сервиса после удаления нескольких опасных конструкций. Он был простым и быстрым, но зависел от полноты фильтра и делил с шаблонами память, секреты и сетевые права приложения.
Второй вариант использовал отдельный контейнер с ограничениями ресурсов. Это уменьшало последствия компрометации, но всё ещё требовало корректной настройки прав контейнера, сетевой политики и самого узла; контейнер нельзя считать автоматически полной изоляцией.
Выбранное решение запускало каждый шаблон в отдельном краткоживущем исполнителе с собственной идентичностью, отключённым исходящим трафиком, только чтением входных данных через контролируемый канал и жёсткими лимитами. Для особо чувствительных отчётов применялась более сильная изоляция. В результате компрометация движка ограничивалась рабочим окружением одного запуска, хотя стоимость выполнения и операционная сложность выросли.
1. Достаточно ли запретить опасные функции в языке шаблонов?
Нет. Фильтрация может пропустить неизвестную конструкцию, ошибку в анализаторе или неожиданную комбинацию разрешённых функций. Она полезна для уменьшения поверхности атаки, но должна дополняться изоляцией, отдельной идентичностью и ограничением доступа к ресурсам.
2. Защищает ли песочница от отказа в обслуживании?
Не сама по себе. Изоляция может не дать шаблону прочитать данные или выйти в сеть, но бесконечное выполнение всё равно способно занять процессор и память. Нужны тайм-ауты, лимиты памяти, размера результата, очереди заданий и параллелизма, а также корректное завершение исполнителя.
3. Можно ли передать исполнителю рабочие секреты, если сетевой доступ запрещён?
Это существенно увеличивает последствия возможного обхода изоляции и обычно неоправданно. Исполнителю следует передавать только минимальный набор данных, необходимых для конкретного задания, через контролируемый канал; секреты основной системы не должны попадать в его окружение. Если доступ к секрету неизбежен, его ограничивают отдельной идентичностью, коротким сроком действия и минимальным набором разрешений.