Не так давно появились новости о векторе атаки Dependency Confusion. Это достаточно простой, но в то же время опасный вектор, позволяющий выполнять произвольный код. Давайте посмотрим на эту проблему с точки зрения команды ИБ.
Суть атаки
Современный сервис редко пишется полностью с нуля.Для решения большинства проблем уже написаны библиотеки для всех возможных языков.
Зачем писать велосипед, если можно взять готовую библиотеку, модуль или пакет? Ваша проблема уже решена в другом внутреннем проекте? Вы можете выполнить поиск в своей личной библиотеке.
Именно здесь узкое место может вызвать проблемы при работе с зависимостями.
Если есть два пакета с одинаковым именем, но один находится в локальном репозитории, а другой в публичном, то сборщик может предпочесть второй.
О самой атаке уже написано довольно много; Мне лично понравилась статья от Хакер 'А.
Я хочу поговорить о способе поиска уязвимых зависимостей в корпоративной кодовой базе.
Synopsys провела исследование в 2020 году исходный код 1253 проектов.Вы можете загрузить свой пакет в публичные репозитории:Оказалось, что 99% проектов содержат компоненты с открытым исходным кодом.
Более того, сами проекты на 70% имеют открытый исходный код.
- PHP, композитор, https://packagist.org/
- Питон, пип, https://pypi.org/
- JavaScript, НПМ, https://www.npmjs.com/ И т. д.
Ищем жучок дома
Как искать уязвимые зависимости? По сути, вам нужно найти все файлы зависимостей во всех проектах и проверить, не содержит ли какой-либо из них ссылки на несуществующие публичные репозитории.В нашем GitLab около 500 проектов, не все из них покрыты Security Pipeline (и не все в нем нуждаются), поэтому нужна какая-то автоматизация.
Есть несколько инструментов для автоматической проверки пакетов в публичных репозиториях: смущенный И репо-дифференциал .
Они принимают на вход файл с зависимостями и показывают, содержит ли он ссылки на зависимости, которых нет в публичных репозиториях.
API GitLab, очевидно, имеет возможность дайте файл , вам просто нужно создать правильную ссылку.
Файлы зависимостей бывают разные, они могут находиться в разных местах проекта.
А могут быть вообще проекты без зависимостей, и тогда нужен поиск файлов.
Для решения этой проблемы я использовал проект с открытым исходным кодом gitlab-поиск .
Этот пакет хорошо справляется с поиском файлов по имени, хотя и требует некоторой фильтрации вывода.
Ниже приведен пример запуска поиска из bash:
В результате получается следующая архитектура программного обеспечения:gitlab-search setup --api-domain <server> <token> gitlab-search -f composer.json '{' | grep <server> | grep composer.json | awk -F "#" '{print $1}' | sort -u | sed 's/\t//g' gitlab-search -f composer.lock '{' | grep <server> | grep composer.lock | awk -F "#" '{print $1}' | sort -u | sed 's/\t//g' gitlab-search -f package.json '{' | grep <server> | grep package.json | awk -F "#" '{print $1}' | sort -u | sed 's/\t//g' gitlab-search -f requirements.txt '==' | grep <server> | grep requirements.txt | awk -F "#" '{print $1}' | sort -u | sed 's/\t//g' gitlab-search -f pom.xml 'xml' | grep <server> | grep pom.xml | awk -F "#" '{print $1}' | sort -u | sed 's/\t//g' .
- Поиск файлов зависимостей в проектах GitLab (gitlab-search).
- Загрузка файлов (GitLab API).
- Проверка зависимостей файлов (в замешательстве).
Шариться в получившемся коде особого желания нет, так как, как и любая обертка над существующими инструментами, он пишется на коленке, и я уверен, что вы могли бы написать его лучше =).
Если есть необходимость тиражировать решение, не помешает собрать для него Docker-контейнер.
Окружающая среда должна содержать, как минимум, npm и путаницу.
Потенциально уязвимая зависимость.
В pypi отсутствует пакет pkg-resources. Мне удалось найти одну потенциально уязвимую зависимость в двух проектах.
Попробую ввести в эксплуатацию.
Для этого я создам модуль под названием pkg-resources и дождусь сборки проекта (или запущу сборку самостоятельно).
Но проблема в том, что в моем случае этот модуль нигде не вызывается и живет только в require.txt. Итак, код модуля не будет выполнено .
Более того, эта зависимость является следствием ошибка пипа и пакет с таким именем не может быть загружен в pypi.
Попытка загрузить пакет pkg-resources в pypi
? операция
На этот раз найти реальный пример уязвимости не удалось.Его невозможно использовать, если область зависимости используется правильно.
Что ж, давайте смоделируем синтетическую версию на примере pypi, поскольку мое внимание привлекли зависимости Python. Прежде всего вам нужно написать приложение , который импортирует уязвимую зависимость.
Затем давайте создадим модуль Python ( руководство по сборке , исходный код полученного модуля ).
Помимо метаданных и структуры самого пакета достаточно написать простейший код чтобы продемонстрировать уязвимость.
Далее вам нужно собрать пакет и загрузить его в pypi. python3 -m build
python3 -m twine upload --repository pypi dist/*
Теперь вам нужно установить вредоносную библиотеку; Я рекомендую использовать виртуальную среду Python (venv).
python3 -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
Но установка и наличие в системе вредоносного пакета еще не приводит к его исполнению.
Для выполнения модуля исполняемые файлы уязвимого приложения должны содержать конструкцию Импортировать , это выполнит код, содержащийся в файле __init__.py .
Пример работы.
Как лечить найденные ошибки
В моем случае с pkg-resources это даже не уязвимость; достаточно удалить строку с зависимостью из require.txt. В общем, стоит посмотреть эта статья Microsoft, там подробно описаны основные варианты исправлений для разных сборщиков:- Используйте единый частный реестр пакетов.
Большинство сборщиков не отдают приоритет источникам зависимостей и проверяют все, чтобы найти последнюю версию пакета.
Публичные пакеты также следует загружать в единый реестр частных пакетов.
- Используйте пространство имен зависимостей.
Некоторые сборщики, такие как npm, позволяют явно указывать источник зависимостей для области.
- Используйте проверку пакетов на клиенте.
Например, можно указать конкретную версию пакета (привязка версии), тогда атаковать с принудительным обновлением будет невозможно.
Вы также можете использовать хеши для контроля неизменяемости пакетов.
- Используйте прокси для загрузки пакетов из Интернета.
На уровне компании договоритесь о наличии общего списка или присвоении имен частным пакетам, например, имя_частного_пакета.
Запретить прокси скачивать пакеты из интернета из белого списка или с указанным префиксом
-
Rxjava. Удаление Магии
19 Oct, 24 -
Lumia Как Холст Художника
19 Oct, 24 -
Спасите Ie6 – Подпишите Петицию!
19 Oct, 24