В затруднительном положении: почему любой метод защиты от pickle в машинном обучении обходится одинаково

Источник: Sysdig•

В затруднительном положении: почему любой метод защиты от pickle в машинном обучении обходится одинаково

Шесть задокументированных обходов защит для PyTorch weights_only, Keras safe_mode и picklescan. Узнайте, какие форматы МО безопасны и что обнаруживает обнаружение во время выполнения.

Экосистема машинного обучения (МО) недавно выпустила ряд средств защиты от вредоносных файлов моделей. PyTorch ограничила возможности своего загрузчика по десериализации. Keras добавила безопасный режим (safe mode), который отказывается выполнять встроенный код. Поставщики создали сканеры для проверки файлов моделей в состоянии покоя и отклонения опасных.

Но ни одно из этих решений не выдержало шести задокументированных обходов CVE. Эти обходы, часто называемые «pickle» (пикл-файлы), позволяют вредоносному файлу данных Python незаметно проскользнуть мимо сканеров безопасности. И после того как исследовательская группа Sysdig Threat Research Team (TRT) разобрала каждый известный общедоступный метод обхода pickle, проявилась закономерная картина.

Прежде чем исследовать эту закономерность, давайте сначала разберем, что такое pickle на самом деле и почему машинное обучение (МО) ими переполнено. Затем мы проанализируем, какие форматы моделей наиболее опасны, что зафиксировала Sysdig TRT при загрузке вредоносных моделей в два механизма обнаружения, а также как лучше всего развертывать уязвимые модели и защищать их в вашей среде.

Pickle — это программа

Pickle — это встроенная возможность Python сохранять что-то из памяти в файл, чтобы вы могли загрузить это позже в точно таком же виде. Многие команды могут использовать сериализацию pickle, даже не подозревая об этом. И torch.save(), и joblib задействуют pickle, а это скрытое непонимание увеличивает риски и приводит к тому, что проблемы возникают незаметно, а никто вокруг не понимает ни почему это произошло, ни в чем дело.

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

Pickle — это совсем другой формат. pickle.load() не выполняет разбор; он выполняет код. Файл .pkl представляет собой последовательность инструкций для небольшой стековой виртуальной машины, встроенной в CPython, и загрузка файла означает их выполнение. Это не недостаток реализации и не ошибка синтаксического анализатора, которую можно исправить патчем, а неотъемлемая часть архитектуры.

Проще всего убедиться в этом — прочитать такой файл. Протокол 0 формата Pickle по задумке читаем человеком, и перед вами готовая рабочая полезная нагрузка (пейлоад):

Приведенный выше фрагмент содержит пять инструкций, и он читается как ассемблерный код, потому что функционально им и является:

  • GLOBAL находит и помещает в стек вызываемый объект (callable).
  • MARK и TUPLE формируют кортеж аргументов.
  • REDUCE вызывает вызываемый объект с этими аргументами.
  • STOP завершает программу.
  • Замените "id" на что-то более амбициозное, и структура останется прежней.

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

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

Обычно вы не стали бы писать эти опкоды вручную. Python сгенерирует их для вас через документированную точку расширения:

__reduce__ — это способ, которым объект указывает pickle, как его реконструировать: этот метод определяет вызываемый объект и его аргументы, а pickle вызывает их при загрузке. Именно так объекты, которые нельзя сериализовать обычным путем, восстанавливают себя на другой стороне. Атака не подрывает этот механизм. Она использует pickle ровно так, как задумано, и назначает os.system в качестве вызываемого объекта.

Взгляните, например, на этот скрипт:

pickletools.dis выполняет декомпиляцию байт-кода без его запуска, и вывод выглядит как листинг: GLOBAL, MARK, SHORT_BINUNICODE, TUPLE1, REDUCE, STOP. Разбирайте код сколько угодно. Запускайте pickle.loads для этой полезной нагрузки только в том окружении, где вы готовы пожертвовать системой в случае неудачи.

Последствия имеют огромное значение

Если pickle — это программа, то файл, недействительный в целом, все же может прекрасно работать в своей части. Виртуальная машина выполняет опкоды по мере их поступления. Она не проверяет поток заранее перед запуском, потому что никакого «заранее» не существует. Она работает до тех пор, пока не завершится или пока не наткнется на то, что не может выполнить. Всё, что было до этого момента, уже произошло.

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

Злоумышленники это заметили, и мы вернемся к этому в третьем разделе.

Почему машинное обучение вообще забито файлами pickle?

Pickle решает реальную проблему, и то, как он ее решает, требует ровно тех возможностей, которые делают его опасным.

Проблема заключается в сериализации произвольных объектов. Записать список целых чисел на диск легко. Однако записать произвольный объект Python гораздо сложнее.

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

Именно так работает метод __reduce__, и стандартная библиотека описывает его именно в таких терминах. Первые два элемента кортежа __reduce__ — это:

  • Вызываемый объект, который будет вызван для создания исходной версии объекта.
  • Кортеж аргументов для вызываемого объекта.

Если прочитать это глазами злоумышленника, эксплойт пишется сам собой. Однако если прочитать это глазами разработчика языка, это единственный доступный универсальный ответ.

Таким образом, произвольное выполнение кода — это не баг в pickle, а фича. Python никогда этого не скрывал. Предупреждение находится в самом верху документации модуля:

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

Так как же машинное обучение оказалось построено на pickle?

torch.save выполняет сериализацию с помощью pickle. Сохранение модели — это один вызов, а артефактом является файл .pt, .pth или .bin, ни один из которых для стороннего наблюдателя в листинге файлов не выглядит как pickle. Руководство scikit-learn по сохранению данных указывает на joblib, обертку над pickle, оптимизированную для объектов, содержащих большие массивы NumPy, что как раз и представляет собой обученный оценщик. Собственный формат NumPy .npy является простым числовым контейнером ровно до тех пор, пока массив не начинает содержать объекты Python. Именно в этот момент ему требуется pickle, и именно поэтому существует флаг allow_pickle.

Никто в этой цепочке не выбирал произвольное выполнение кода. Они выбрали функцию «сохранить мой объект Python», что является очевидным желаемым API, а pickle — это готовый инструмент из коробки для реализации этой возможности.

В результате мы получаем цепочку поставок, в которой преобладают файлы pickle. На зеркале Hugging Face файлы .pt, .pth и .bin от PyTorch составили 335 893 модели (51,0%), а явные варианты pickle (.pkl, .pickle, .joblib, .dill) добавили еще 26 696, или 4,1%. Более половины моделей, которые вы можете скачать, выполняют код в тот самый момент, когда вы их загружаете.

Почему вариант «просто исправить pickle» не рассматривается

Вы не можете сделать pickle.load одновременно универсальным и безопасным, поскольку универсальность — это как раз то свойство, которое требует вызова кода. Тем не менее, вы можете сделать одну из двух более узких вещей:

  • Ограничить загрузчик. Сохранить формат, но разрешить только заведомо безопасное подмножество вызываемых объектов (callable). Это стандартная рекомендация стандартной библиотеки, а параметры weights_only=True в PyTorch и safe_mode в Keras представляют собой именно такой подход применительно к файлам моделей.
  • Изменить формат. Хранить только то, что действительно нужно модели — например, именованные массивы чисел в контейнере, который вообще не поддерживает возможность вызова функций. Это safetensors.

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

Какие модели действительно уязвимы

Какие файлы моделей следует рассматривать как код? Краткий ответ: гораздо большее их число, чем следует из названия, и почти ни один из них не называется .pkl.

Формат

Выполняется при загрузке?

Примечания

.pkl.pickle.dill

Да

Обычный случай

scikit-learn .joblib

Да

joblib оборачивает pickle

PyTorch .pt.pth.bin

Да

Pickle в ZIP-оболочке. weights_only=True начиная с версии 2.6; см. ниже

NumPy .npy.npz

Только при allow_pickle=True

По умолчанию False с момента выхода CVE-2019-6446. Требуется для массивов объектов, именно так эта функция снова включается

Keras/TensorFlow .h5.hdf5

Да

Lambda-слои, а устаревший путь игнорирует safe_mode

Keras .keras (v3)

Да, в обход

См. CVE-2025-9906

TensorFlow SavedModel

Да, фактически

Графовые операции плюс пользовательские слои

safetensors

Именованные тензоры и заголовок JSON. Никаких опкодов или вызываемых объектов

GGUF

Нет известных путей

Тензоры и метаданные для квантованного инференса

ONNX

Нет известных путей

Вычислительный граф Protobuf, только предопределенные операции

Обратите внимание на формулировку для последних двух форматов: нет известных путей выполнения кода. Эти форматы моложе и подвергаются атакам реже, чем pickle, и отсутствие опубликованных CVE является гораздо менее весомым доказательством по сравнению с форматом, который в принципе не способен выразить вызов.

Стратегия первая: ограничить загрузчик и получить обход защиты

Сохранить формат, разрешив только заведомо безопасное подмножество вызываемых объектов: это собственный совет стандартной библиотеки. Обе основные библиотеки последовали этому совету, но защиту все равно удалось обойти.

PyTorch переключил аргумент weights_only функции torch.load с False на True по умолчанию в версии 2.6, явно из соображений безопасности. Ограниченный инструмент разархивации (unpickler) разрешает тензоры, хранилища (storages) и базовые коллекции, отклоняя все остальное.

За исключением того, что в версии 2.5.1 и более ранних параметр weights_only=True уже можно было обойти. CVE-2025-32434 обнаружила, что _legacy_load — путь, обрабатывающий старые чекпоинты на основе tar — на самом деле не применял ограничения unpickler ко всему, что он обрабатывал. Флаг был установлен, но выполняемый код его не учитывал.

Затем это повторилось снова. Уязвимость CVE-2026-24747, опубликованная в январе 2026 года с оценкой CVSS 8.8, обходит проверку ограниченного unpickler с помощью специально сформированных опкодов, вызывая повреждение памяти для достижения выполнения кода. Она затрагивает каждую версию до 2.10.0, что означает, что исправление обхода 2025 года само по себе было уязвимо во всем диапазоне от 2.6 до 2.9. Если вы зафиксировали версию PyTorch 2.6 в начале 2025 года, потому что она считалась безопасной по умолчанию, вы оставались уязвимы в течение четырех минорных версий.

У Keras та же схема и еще больше итераций. Lambda-слои содержат сериализованный Python и выполняют его при загрузке (. В Keras параметр safe_mode=True стал значением по умолчанию начиная с версии 2.13, что запрещает их десериализацию.

Затем, в CVE-2025-9905, загрузка устаревшего файла .h5 игнорирует safe_mode. Никаких предупреждений, никаких ошибок. Злоумышленнику достаточно создать чекпоинт в старом формате, и текущая библиотека загрузит его и все равно выполнит код.

Наконец, CVE-2025-9906, специально созданный архив .keras, чей файл config.json вызывает keras.config.enable_unsafe_deserialization(), после чего добавляет Lambda-слой. Файл отключает проверку, которая его анализирует.

В том же исследовании 705 991 модели с платформы Hugging Face исследователи обнаружили 91 вредоносную, причем 15 из них использовали Lambda-слои Keras.

Стратегия вторая: просканировать файл перед загрузкой и все равно пропустить вредоносные файлы

Проверить артефакт в неактивном состоянии и отклонить его, если он выглядит подозрительно. Именно это использует Hugging Face при загрузке и большинство систем непрерывной интеграции (CI).

Компания Sonatype в 2025 году раскрыла четыре уязвимости в picklescan, и три из них описывают одну и ту же ошибку с разной механикой:

  • CVE-2025-1889: Стандартные механизмы обнаружения привязаны к расширению файла, а не к его содержимому. Если злоумышленники переименовывали файл, он никогда не сканировался.
  • CVE-2025-1944: Намеренно поврежденный ZIP заставляет picklescan аварийно завершаться с ошибкой BadZipFile. Более снисходительный ZIP-парсер PyTorch загружает тот же файл без каких-либо жалоб.
  • CVE-2025-1945: Если злоумышленник изменяет биты флагов ZIP, picklescan не может обнаружить угрозу, а PyTorch все равно выполняет загрузку.

Кроме того, существует nullifAI, обнаруженная ReversingLabs на Hugging Face в феврале 2025 года. Модели были сжаты с помощью 7z вместо стандартного для PyTorch ZIP. Picklescan их не распознал.

Одна ошибка, шесть раз

Уязвимость

Пробел в защите

PyTorch CVE-2025-32434

weights_only не применяется на пути _legacy_load

Keras CVE-2025-9905

safe_mode игнорируется на устаревшем пути H5

Keras CVE-2025-9906

Файл отключает проверяющую его процедуру

picklescan CVE-2025-1889

Сканер считывает расширения; загрузчик считывает содержимое

picklescan CVE-2025-1944 и 1945

ZIP-парсер сканера строг; парсер загрузчика снисходителен

nullifAI

Сканер ожидает ZIP; загрузчик принимает 7z

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

Это носит структурный, а не просто случайный характер. Сканер должен предвидеть, как каждый загрузчик, в каждой версии и на каждом устаревшем пути выполнения кода будет интерпретировать поток байтов. Загрузчику же достаточно интерпретировать его хоть каким-то одним образом, и именно это приводит к пропуску вредоносных файлов.

Pickle не обязательно должен быть валидным, чтобы работать

Модели nullifAI были сломаны намеренно.

Вспомните из первого раздела, что виртуальная машина pickle выполняет опкоды по мере их обнаружения. Проход валидации отсутствует. Полезная нагрузка была размещена в начале потока, поэтому к тому моменту, когда десериализация доходила до повреждения и выдавала ошибку, os.system уже вызывалась. Как описывали это в ReversingLabs, опкоды выполняются «до тех пор, пока не будут выполнены все опкоды или не встретится сломанная инструкция».

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

Вернитесь к таблице в разделе «Какие модели действительно уязвимы». Форматы в нижних строках безопасны не потому, что они хорошо пропатчены, а потому, что в файле safetensors нет ничего, что могло бы выразить вызов — ни опкодов, ни вызываемых объектов, ни процедуры реконструкции. Свойство безопасности является следствием того, что формат не способен выразить, и именно поэтому ему не нужен номер версии, чтобы считаться доверенным.

В этом и заключается главный аргумент в пользу конвертации. Но конвертация доступна не всегда, и множество производственных систем загружают файлы pickle прямо сейчас. Поэтому следующий вопрос заключается в том, что именно вы можете увидеть при запуске одного из них.

Обнаружение

Есть два момента, когда можно перехватить вредоносную модель: до ее загрузки и во время ее работы. Они дают сбой по-разному, и эта разница имеет значение.

Сканирование в состоянии покоя

Сканирование — это основной элемент контроля. Это недорого, это работает в CI, это блокирует артефакт до того, как что-либо выполнится, и для стандартной полезной нагрузки это работает. Гаджет __reduce__, вызывающий os.system, — это именно то, для поиска чего созданы modelscan и picklescan.

CVE, перечисленные в третьем разделе, являются причиной того, что это не успокаивает. Каждый обход в этом списке побеждал сканер, который корректно работал с файлом, который, по его мнению, он читал. Сюда входят проверка расширений, парсинг ZIP, биты флагов, 7z и намеренно поврежденный поток. Ни одно из них не нарушило логику обнаружения, но они изменили то, чем файл являлся на входе.

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

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

Наблюдение за работой

Обнаружение во время выполнения — это уровень, который предлагается в качестве логичного ответа, поэтому давайте оценим его.

Мы создали пять враждебных семейств гаджетов, каждое из которых представляет собой пикл, чей метод __reduce__ выполняет различные постинвазивные действия, и запустили их против двух движков: открытого Falco 0.44.1 с набором правил по умолчанию и Sysdig Secure.

Обе проверки сначала вызвали положительный контроль. Все пять результатов были письменно предсказаны до запуска.

Семейство гаджетов

OSS Falco (набор правил по умолчанию)

Sysdig Secure

Чтение конфиденциального файла через оболочку

СБРАСЫВАЕТСЯ · Чтение конфиденциального файла (недоверенный)

СБРАСЫВАЕТСЯ · 1.6 с

Чтение конфиденциального файла, напрямую, без оболочки

СБРАСЫВАЕТСЯ · то же правило

СБРАСЫВАЕТСЯ · 1.9 с

Чтение конфиденциального файла в процессе, без порождения процессов

СБРАСЫВАЕТСЯ · то же правило

СБРАСЫВАЕТСЯ · 1.5 с

Составное: чтение плюс исходящий трафик

СБРАСЫВАЕТСЯ · только то же правило

СБРАСЫВАЕТСЯ · + сетевая активность системных процессов

.pth персистентность через хук запуска

Изменение файла хука запуска Python

СБРАСЫВАЕТСЯ · 1.5 с · Файл персистентности Python .pth записан не менеджером пакетов

Все пять семейств гаджетов вызвали срабатывание правил Sysdig Secure, причем все в течение двух секунд. Четыре из пяти вызвали срабатывание правил по умолчанию OSS Falco. Набор правил Falco с открытым исходным кодом по умолчанию содержит 26 правил по сравнению с 278 правилами коммерческого продукта. Сюда входит правило Falco «Изменение файла хука запуска Python», которое было создано после этого теста.

Однако три вывода из этой таблицы важнее, чем общая оценка.

Во-первых, ось порождения процессов не имеет значения. Мы ожидали, что гаджет, порождающий оболочку, будет выглядеть иначе, чем тот, который не покидает процесс Python, но обнаружения не отличаются. Гаджет с порождением оболочки был пойман за 1.6 секунды, прямой — за 1.9 секунды, а полностью внутрипроцессный — за 1.5 секунды. Все три были пойманы одним и тем же правилом. Порождает ли гаджет процессы — это характеристика его поверхности системных вызовов, а не его видимости.

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

Это звучит как формальность до тех правил, которые, как кажется, должны были это поймать. «Оболочка порождена с встроенной командой Python» проверяет proc.pcmdline, содержащую -c вместе с буквальным исходным текстом: import os и os.system. Выполнение скрипта Python, закодированного в Base64, делает то же самое на один слой кодирования ниже. Оба предполагают, что вредоносный Python виден в командной строке.

И в-третьих, загрузка пикла — это python3 load_pickle.py model.pkl. Гаджет находится в файле. Никакой этот текст никогда не появляется в командной строке, ни на каком уровне кодирования, вообще.

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

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

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

. Преобразуйте формат и избавьтесь от проблемы.

Большинству моделей не нужно сериализовывать ничего, кроме именованных массивов чисел. Если это верно для вашей модели, сохраняйте ее в контейнере, который не может выразить вызов: safetensors для весов, GGUF для квантованного вывода и ONNX, если вам нужен вычислительный граф.

Разница между этими тремя форматами важнее, чем может показаться. Safetensors структурно безопасен, так как состоит из тензоров и заголовка JSON, причем ничто в формате не способно выразить вызываемый объект. GGUF и ONNX не имеют известных путей обхода, что больше говорит о текущем состоянии исследований, чем о выразительных ограничениях формата. ONNX, в частности, содержит полный граф операторов и историю CVE парсеров. При развертывании новой модели выбирайте тот формат, который безопасен в силу того, что он не может выразить.

Предостережение: «Нет известных путей обхода» не означает «доказано безопасным», так как конвертация доступна не всегда. Модель, распространяемая исключительно в виде пикла, должна быть загружена один раз для конвертации. Делайте это в песочнице из пункта 5 ниже, а не на хосте сборки.

. Зафиксируйте версии загрузчиков за пределами обходов и проверьте фактически запущенную версию.

Для PyTorch наиболее безопасный подход означает использование версии 2.10.0 или новее. Значение по умолчанию weights_only=True появилось в версии 2.6 и широко освещалось как исправление, но CVE-2026-24747 поражает сам ограниченный десериализатор и затрагивает каждую версию до 2.10.0. Команда, зафиксировавшая версию 2.6 в начале 2025 года по совету по безопасности, оставалась уязвимой еще на четырех минорных версиях.

Для Keras используйте актуальную версию и отклоняйте устаревшие входы .h5 вместо того, чтобы доверять safe_mode для этого пути. CVE-2025-9905 — это случай, когда он игнорируется без предупреждения. Для NumPy оставляйте allow_pickle=False и рассматривайте любой код, который переключает это значение, как уязвимость.

Предостережение: Этот уровень имеет, пожалуй, самую худшую историю среди всех пунктов в этом списке. Каждая запись выше — это исправление, которое впоследствии само было обойдено. Зафиксируйте версию, но не полагайтесь слепо на доверие, которое она якобы покупает.

. Сканируйте в состоянии покоя, в CI, в качестве шлюза.

. Запускайте modelscan или picklescan при поступлении и вызывайте сбой сборки, а не развертывания. Это дешево и позволяет обнаружить типичные случаи, с которыми вы и столкнетесь в большинстве ситуаций.

Предостережение: Сканеры основаны на черных списках, и каждое оцененное CVE побеждало сканер, который работал корректно. Чистое сканирование — это лишь отсутствие доказательств. Никогда не позволяйте ему быть сигналом, переводящим артефакт в продакшн.

. Установите происхождение.

Отслеживайте, какая модель откуда появилась. Подписывайте то, что собираете, проверяйте то, что потребляете, и отдавайте предпочтение издателям, которые делают то же самое.

Предостережение: Подпись доказывает происхождение, а не намерение. Вредоносные модели, найденные на Hugging Face, были подлинно загружены теми аккаунтами, которые их загрузили. Происхождение сужает круг тех, кому приходится доверять, но оно не говорит вам, заслуживает ли это доверие.

. Загружайте внутри песочницы с граничным контролем исходящего трафика.

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

Это единственный элемент управления здесь, который не зависит от распознавания атаки; ему и не нужно. Он не решает, является ли соединение вредоносным, а только разрешено ли оно.

Предостережение: «Песочница» ограничивает радиус поражения, но не предотвращает выполнение. Код все равно выполняется. Вы сами выбираете, к чему он может получить доступ.

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

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

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

Почему этот порядок имеет значение

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

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

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

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

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

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

Ознакомьтесь с последними исследованиями угроз от Sysdig TRT

О чём эта статья

Ещё в разделе «Облака и инфраструктура»

Все →

Ещё от Sysdig