Слепая зона AppSec: почему проверки зависимостей не должны заканчиваться на CVE

18881
Слепая зона AppSec: почему проверки зависимостей не должны заканчиваться на CVE

Threat intelligence для AppSec — от списков уязвимостей к полноценному контролю цепочки поставок ПО.

image

Безопасная работа с внешними зависимостями в большинстве команд сводится к одному сценарию: есть CVE (common vulnerabilities and exposures — реестр общеизвестных уязвимостей), есть версия пакета, есть процесс — патч или замена. Уязвимости закрываются, метрики зеленеют. Но цепочка поставок ПО может быть под угрозой не только из-за уязвимостей.

Стандартные инструменты SCA (анализ состава ПО) анализируют внешние зависимости и подсвечивают уязвимые, сопоставляя название и версию релиза внешнего пакета с базой CVE. По возможности предлагают пользователю патч. Но на этом угрозы не заканчиваются.

В 2022 году департамент threat intelligence (киберразведка) Positive Technologies начал отслеживать атаки через ПО с открытым исходным кодом. Картина проявилась быстро: в PyPI (Python Package Index — репозиторий Python-пакетов) и npm (Node Package Manager — менеджер пакетов Node.js) обнаружились пакеты с вредоносным кодом, которые месяцами оставались незамеченными, а некоторые жили в репозиториях годами.

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

Когда начались первые атаки на цепочки поставок в России, мы в первую очередь проверили зависимости внутри собственной инфраструктуры Positive Technologies. Затем появился публичный сервис анализа Python-пакетов — PT PyAnalysis: за первые девять месяцев исследования он выявил более 200 вредоносных пакетов. Сегодня расширенные данные для защиты цепочек поставок доступны клиентам в виде фидов (машиночитаемых потоков данных) через TI-портал PT Fusion.

Что внутри фидов

Фиды поставляются в формате OSV (open source vulnerabilities) — это машиночитаемая схема описания уязвимостей с привязкой к пакетам, версиям и коммитам. Формат изначально создавался для поиска уязвимых зависимостей, но мы применяем его шире: через дополнительные поля и собственную таксономию OSV позволяет единообразно описывать вредоносные релизы, protestware и удаленные пакеты в рамках процессов DevSecOps (безопасной разработки приложений). Данные покрывают экосистемы PyPI и npm, а также плагины для VS Code и Firefox.

Четыре категории риска

AppSec-команды в большинстве случаев ищут только уязвимости во внешних зависимостях. Но пакет может нести и другие угрозы — каждая требует отдельной реакции в CI/CD.

Думал на протяжении 10s
Уязвимость

Ошибка в коде, которую можно эксплуатировать

protobuf.js ≤ 7.5.5, ветка 7.x, и ≤ 8.0.1, ветка 8.x; vm2 < 3.10.2

Реакция

Задача на обновление; блокировка развертывания при критическом уровне опасности

Вредоносный код

Намеренное внедрение через компрометацию проекта

xz-utils 5.6.0-5.6.1; polyfill.io

Реакция

Немедленная блокировка версии; расследование, если пакет уже в сборке

Protestware

Политически мотивированное деструктивное поведение

node-ipc, март 2022

Реакция

Блокировка версии; оценка репутационных рисков

Удаленный / заброшенный

Операционный риск: сборка ломается, патчи не выходят

left-pad, 2016

Реакция

Зеркалирование во внутренний репозиторий; планирование замены

Уязвимости

Рассмотрим классический пример. В protobuf.js — до версии 7.5.5 в ветке 7.x и до 8.0.1 в ветке 8.x — через поля type в protobuf-описаниях можно было внедрить JavaScript, который выполнялся при декодировании данных. В VM2 до версии 3.10.2 обход обработки Promise-колбэков позволял выйти из песочницы и выполнить произвольный код на хосте.

Такие данные попадают в AppSec-инструменты через фиды: зависимости проверяются при сборке, задачи на обновление создаются автоматически, а критически опасные находки блокируют выкладку.

Вредоносный код

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

Самый известный случай последних лет — xz-utils. В версиях 5.6.0 и 5.6.1 через подготовленные файлы в релизных архивах вредоносная логика встраивалась в сборочные скрипты и через них попадала в библиотеку liblzma — что при определенных условиях позволяло выполнять произвольные команды через sshd. Атаку готовили два года — вредоносный разработчик планомерно зарабатывал доверие сообщества.

Отдельный вектор — смена контроля над инфраструктурой проекта. Polyfill.io после продажи домена новому владельцу начал отдавать модифицированный JavaScript и перенаправлять пользователей на мошеннические сайты. Проблема была не в конкретной версии npm-пакета, а в доверии к внешней CDN (сеть доставки контента).

Реакция на вредоносные пакеты жестче, чем на CVE: подозрительные версии блокируются в CI/CD немедленно, а если пакет уже попал в сборку — данные фида становятся отправной точкой расследования.

Protestware

Protestware — это пакеты с политически или социально мотивированным деструктивным поведением. В марте 2022 года в версиях node-ipc 10.1.1 и 10.1.2 появился код, который затирал файлы на машинах пользователей из России и Беларуси. Дополнительно через зависимость peacenotwar выводилось политическое сообщение. Такие релизы часто классифицируются одновременно как вредоносные, но мотивация и паттерн распространения у них другие. Фиды помогают отсечь подобные версии до того, как пакет с деструктивным кодом окажется в продукте клиента.

Удаленные и заброшенные пакеты

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

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

Как устроен поиск таких зависимостей

Подход основан на практиках анализа вредоносного ПО, которые департамент threat intelligence накапливал годами при исследовании реальных атак. Масштаб задачи диктует автоматизацию: в сутки в PyPI и npm выходят десятки тысяч релизов с миллионами строк кода. Ручной анализ невозможен.

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

Что это дает AppSec-команде

Проверка зависимостей перестает сводиться к списку CVE. CI/CD получает дополнительный слой контроля: уязвимые версии, вредоносные релизы, protestware-код, сигналы о прекращении поддержки и компрометации инфраструктуры проекта. Все это превращается в правила, которые работают внутри SCA-платформ и конвейеров сборки.

Небольшой команде для начала достаточно внедрить osv-scanner в CI/CD или использовать pre-commit-хуки. Следующий шаг — проксирующий репозиторий (Nexus, Artifactory) с функцией карантина: новый пакет не попадает в сборку до прохождения проверки, а зеркало внутри периметра снижает зависимость от внешних реестров. Зрелая безопасная разработка требует более широкого набора источников — и именно здесь threat intelligence превращается из аналитической функции в рабочий инструмент AppSec.

ОР
50% / 50%

антипов жжёт

Ваш мозг проигрывает в рулетку,
даже когда вы не играете

// закон малых чисел →