При разработке программного обеспечения мы зависим как от собственных, так и от сторонних компонентов или артефактов. Гибкое управление зависимостями имеет важное значение для современного программного обеспечения. Менеджеры пакетов, такие как NPM, Специалист, типун or NuGet часто используются для указания зависимостей программного обеспечения. Эти инструменты были разработаны с учетом удобства и простоты использования, а не безопасности.
Проблема
Проблема в том, что гибкость и простота использования для разработчиков привлекают плохих парней, которые считают зависимости программного обеспечения непреодолимым очарованием для своего бизнеса. Результат: злоумышленники использовали все возможные пути атаки, показанные здесь. Источник: «Коллекция ножей Backstabber: обзор атак на цепочку поставок программного обеспечения с открытым исходным кодом».
В этом посте мы сосредоточимся на использовании объявлений открытой версии в том смысле, что загруженная версия не является фиксированной, а должна принадлежать определенному диапазону. Во время сборки самая высокая существующая версия, совместимая с указанным диапазоном версий, выбирается и загружается/устанавливается менеджером пакетов.
Проиллюстрируем открытые объявления в объявлениях зависимостей для разных менеджеров пакетов:
-
- НПМ: пакет.json
{
...
«зависимости»: {
...
«принимает»: «>=1.3.8»,
«лодаш»: «~4.16.0»,
...
},
...
}
Будет установлена самая большая существующая версия не ниже 1.3.8 для пакета Accepts, а также самое большое обновление «исправления» для lodash в диапазоне 4.16.x.
-
- Мейвен: пом.xml
...
...
Commons-IO
Commons-IO
ВЫПУСКАТЬ
...
...
Последний доступный выпуск, доступный для commons-io (файл jar), будет добавлен в качестве зависимости.
-
- Пип: setup.py
...
настраивать(
...
install_requires=['перчинка', 'launchpadlib'],
...
)
...
Такие схемы открытой версии имеют как хорошие, так и плохие стороны. Хорошо, что новые версии обычно содержат функциональные и качественные улучшения, исправления ошибок и исправления безопасности, которые обновляются автоматически. Обратите внимание, что для большинства реальных проектов исправления не переносятся в предыдущие второстепенные выпуски, за исключением, возможно, катастрофических уязвимостей безопасности. Открытые версии также хороши для использования в библиотеках, чтобы уменьшить количество версий, которые необходимо установить после разрешения всех зависимостей.
Но у открытых версий есть и обратная сторона. Вы не знаете точно, какие версии будут установлены во время сборки, и сборки не повторяются. А еще есть темно сторона с открытыми версиями. Если злоумышленнику удастся опубликовать вредоносный компонент в общедоступном репозитории с высокой версией, совместимой с вашим открытым диапазоном, ваша следующая сборка будет включать вредоносный компонент, возможно, даже выполняя вредоносное ПО в сценариях установки, которые могут выполняться автоматически. Запутывание полезной нагрузки атаки — это своего рода искусство.
Это называется Отсутствие закрепления версий вопрос.
Злоумышленники всегда пытаются внедрить вредоносные версии популярных пакетов с открытым исходным кодом. Они могут получить доступ к ключам репозиториев пакетов в секретной утечке; они часто используют социальную инженерию или скрывают вложенную вредоносную зависимость в, по-видимому, полезном pull request. Даже некоторые авторы однажды решают, что мир несправедлив, и кусают своих клиентов протестное ПО в своих упаковках!
Теперь представьте, что вы работаете в организации, которая использует внутренние компоненты плюс компоненты с открытым исходным кодом.
Если злоумышленник знает имя таких внутренних компонентов, он/она может опубликовать компонент с таким же именем в публичном репозитории. Многие менеджеры пакетов сначала получают общедоступные компоненты, и если версия выбрана правильно и версия в объявленной вами зависимости открыта, ура! Эта проблема носит название Путаница зависимостей.
Давайте покажем пример. Предположим, что в нашем проекте NPM у нас есть зависимость от частного компонента:
-
- НПМ: пакет.json
{
"name": "мой-проект",
...
«зависимости»: {...
«my-private-dep»: «>=1.0.0»,...
}
...
}
Злоумышленник может создать старшую версию my-private-dep (например, 99.0.0) и опубликовать ее в общедоступном репозитории npm со своей собственной поддельной учетной записью (злоумышленнику не нужно ничего делать с моей организацией). Менеджер пакетов NPM установит вредоносную зависимость, часто с разрушительными последствиями.
решение
Чтобы избежать этих проблем в процессе сборки программного обеспечения, мы должны следовать строгим нормам объявления версий компонентов, которые зависят от используемой технологии. Важно то, что конкретная версия пакета, однажды опубликованная в репозитории, должна быть неизменяемой (чтобы избежать нарушения зависимостей не только по соображениям безопасности).
Общая идея - зафиксировать(сосна) версии, всегда проверяя, что фиксированные версии компонентов (включая ВСЕ транзитивные зависимости) не содержат вредоносного ПО, и это возможно благодаря файлы блокировки который предлагают многие менеджеры пакетов. Давайте посмотрим, как работает закрепление версий для разных менеджеров пакетов. Существует тонкий компромисс между частые обновления версий для исправления известных уязвимостей и закрепление версии чтобы избежать недетерминированных сборок и потенциальных атак на цепочку поставок.
-
- NPM:
Менеджеры пакетов npm или Yarn используют разные файлы блокировки (npm-shrinkwrap.json / package-lock.json или Yarn.lock соответственно), в которых перечислены фиксированные версии для всех зависимостей, прямых и косвенных. Файлы блокировки должны находиться под контролем версий, иначе у других разработчиков/узлов сборки могут оказаться другие версии. Избегайте установки npm, за исключением случаев, когда в процессе разработки вам необходимо обновить зависимости (например, для установки исправлений безопасности). В целом используйте более детерминированный npm ci (чистая установка), чтобы менеджер пакетов использовал файл блокировки или завершал работу с ошибкой, если файл блокировки отсутствует или он не соответствует package.json. Если перечисленные версии были проверены на наличие вредоносного ПО, файл блокировки гарантирует, что во время сборки не произойдет ничего плохого.Для внутренних компонентов рекомендуется создать Область применения НПМ управляемый организацией (например, @myorg), и используйте эту область в зависимости (например, @myorg/my-private-dep), которая может иметь только частную видимость. Это блокирует путаница с зависимостями атаки, поскольку только член организации с доступом на запись может публиковать пакеты в такой области.
- NPM:
-
- Специалист:
Maven/Gradle не имеет файлов блокировки (но см. эта статья StackOverflow).Диапазоны версий не используются в Maven/Gradle так часто, как в других экосистемах. Просто избегайте диапазоны версий и ПОСЛЕДНИЕ или ВЫПУСКНЫЕ мета-версии. Косвенные версии также следует проверять. Версии Плагин Maven — хороший инструмент для контроля версий.
Обратите внимание, что в Maven всегда существовала концепция области организации (часть groupId зависимости), и путаница в зависимостях, похоже, вообще не является проблемой для этой экосистемы.
- Специалист:
-
- Пип:
В Python существуют различные инструменты для работы с файлами блокировки:– пипенв, который генерирует файл блокировки Pipfile.lock.
– поэзия, который генерирует поэзию.lock.
– заморозка пипса, команда, которая генерирует файл require.txt, который действует как файл блокировки. Проверьте, все ли зависимости используют фиксированные версии с помощью оператора ==. Затем pip install -r require.txt использует фиксированные зависимости.
- Пип:
Напоминаем, что файлы блокировки, указанные выше, должны находиться под контролем версий и что выбранная команда сборки должна использовать файл блокировки.
Обычный репозиторий пакетов, используемый с pip (PyPI), не имеет областей именования и уязвим для атак, вызывающих путаницу зависимостей. Как избежать путаницы с зависимостями в экосистеме Python Это непросто, и некоторые авторы рекомендуют использовать внутренний репозиторий в качестве прокси для общедоступных зависимостей, полученных из PyPI, но сначала брать частные зависимости из внутреннего репозитория (-index-url должен указывать на внутренний репозиторий, а не на PyPI, и –extra-index- URL следует удалить).
Несколько реальных атак
Атака Getcookies: Актер пылин87 добавил в популярный пакет npm mailparser косвенную зависимость от вредоносного пакета с бэкдором RCE (gCOMMANDhDATAi):
JSON.stringify(req.headers).replace(/g([a-f0-9]{4})h((?:[a-f0-9]{2})+)i/gi, (o, р, v) => {})
Несмотря на то, что он был устарел (нет рецензентов!), mailparser все еще получал около 64,000 XNUMX еженедельных загрузок. Это был случай атаки с небольшим промахом, поскольку RCE на самом деле не был опробованcisредактор
НПМ опубликован это сообщение с подробностями об атаке getcookies.
Путаница зависимостей:
Алекс Бирсан обнаружил в 2021 году проблему путаницы в зависимостях и опубликовал сообщение под названием «Как я взломал Apple, Microsoft и десятки других компаний».
Помните, что для npm должна быть зарезервирована область организации, такая как @myorg, а внутренние пакеты должны быть изменены для использования этой области.
При использовании pip общий общедоступный реестр PyPI не имеет областей/пространств имен. Каждый частный пакет может иметь публичный пакет с тем же именем, что и внутренний пакет, но пустой и, возможно, вызывающий ошибку при использовании, чтобы его можно было идентифицировать в случае случайного извлечения.
Node-IPC:
Владелец пакета, когда началась российско-украинская война, внедрил вредоносный код для удаления случайных файлов, установленных на российских и белорусских хостах. Файл ssl-geospec.js выполнял такое географическое различие:
Интересно, что другие пакеты использовали открытые версии для зависимости node-ipc, например популярный фреймворк Vue.js, и его сопровождающие получили срочный призыв чтобы закрепить зависимость node-ipc на безопасной версии.
Этот пост содержит более подробную информацию об этом саботаже, который идет на шаг дальше от других Протестное ПО вопросы.
Заключительные замечания
Открытые версии должны “никогда не научится делать” использоваться в консолидированных проектах программного обеспечения. Они делают сборки невоспроизводимыми, и злоумышленники могут использовать их и внедрить вредоносное ПО посредством атак на деревья зависимостей, таких как вышеупомянутая путаница с зависимостями.
Неправильные конфигурации, такие как открытые версии, отсутствие закрепления версий или внутренние компоненты без области действия. необходимо избегать. Первое, что нужно сделать, — обнаружить такие проблемы, возможно, даже заблокировать сборку в случае их обнаружения, а также стандартизировать протокол действий.
Автоматическое обнаружение дефектов и неправильных конфигураций зависимостей, сообщение о подозрительных зависимостях, которые могут быть уязвимы для конкретных атак в цепочке поставок, таких как путаница с зависимостями, все с действенными инструментами исправления, является одной из основных целей Платформа Ксигени.
| Чтобы узнать больше |
| Ом М., Плейт Х., Сикош А., Мейер М.: «Коллекция ножей предателя: обзор атак на цепочку поставок программного обеспечения с открытым исходным кодом». DIMVA 2020. Конспекты лекций по информатике, том 12223. Springer – 2020 (источник рисунка дерева атак зависимостей). |
| @adam-npm: «Заявленный вредоносный модуль: getcookies«. Блог npm (в архиве) – 2 мая 2018 г. |
| Алекс Бирсан: «Как я взломал Apple, Microsoft и десятки других компаний». Средний – 9 февраля 2021 г. |
| Акс Шарма: «БОЛЬШОЙ саботаж: знаменитый пакет npm удаляет файлы в знак протеста против войны в УкраинеBleepingComputer – 17 марта 2022 г. |





