[Информационная безопасность, Python] Поиск Dependency Confusion в корпоративном GitLab

Автор Сообщение
news_bot ®

Стаж: 6 лет 2 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
23-Апр-2021 13:31

Не так давно на слуху была новость о векторе атаки Dependency Confusion. Это довольно простой, но в тоже время опасный вектор, позволяющий выполнять произвольный код. Давайте рассмотрим эту проблему с точки зрения команды ИБ.Суть атакиСовременный сервис редко пишется полностью с нуля. Для решения большинства задач уже написаны библиотеки под все возможные языки. Зачем писать велосипед, если можно взять готовую библиотеку, модуль или пакет? Вашу задачу уже решили в другом внутреннем проекте? Можно пошарить приватную библиотеку. Именно тут узкое место возможны проблемы при работе с зависимостями. Если есть два пакета с одинаковым названием, но один в локальном репозитории, а другой находится в публичном репозитории, то сборщик может отдать предпочтение второму. Про саму атаку написано уже достаточно много, лично мне понравилась статья от Хакер'а. Я хочу рассказать о способе поиска уязвимых зависимостей в корпоративной кодовой базе.
Synopsys в 2020 году провела исследование исходного кода 1 253 проектов. Оказалось, что 99 % проектов содержат open-source компоненты. При этом сами проекты на 70 % состоят из open-source.
Вы сами можете загрузить свой пакет в публичные репозитории: Ищем багу у себяКак искать уязвимые зависимости? По сути, нужно найти во всех проектах все файлы зависимостей и проверить, нет ли среди них ссылок на несуществующие публичные репозитории. В нашем GitLab около 500 проектов, далеко не все из них покрыты Security Pipeline (и далеко не всем это требуется), поэтому нужна какая-нибудь автоматизация.Есть пара инструментов для автоматической проверки наличия пакетов в публичных репозиториях: confused и repo-diff. Они принимают на вход файл с зависимостями и выдают, есть ли в нём ссылки на несуществующие в публичных репозиториях зависимости. У GitLab API, очевидно, есть возможность отдать файл, нужно только сформировать правильную ссылку. Файлы зависимостей бывают разные, они могут лежать в разных местах проекта. А могут вообще быть проекты без зависимостей, и тогда нужен поиск по файлам. Для решения этой задачи я воспользовался open-source проектом gitlab-search. Этот пакет хорошо справляется с поиском файлов по имени, хотя и приходится немного фильтровать вывод. Ниже пример запуска поиска из 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).
  • Проверка зависимостей файлов (confused).
Скрипт состоит примерно из 200 строк. Шарить получившийся код нет особого желания, поскольку, как и любая обертка над существующими инструментами, он написан на коленке, и я уверен, что вы могли бы написать лучше =). Если возникнет необходимость тиражировать решение, то не помешает собрать под него Docker-контейнер. В окружении должны быть, как минимум, npm и confused.
Потенциально уязвимая зависимость.
Отсутствие пакета pkg-resources в pypi.Мне удалось найти одну потенциально уязвимую зависимость в двух проектах. Попробую провести эксплуатацию. Для этого создам модуль с именем pkg-resources и дождусь сборки проекта (или инициирую сборку сам). Но проблема в том, что в моем случае этот модуль нигде не вызывается и живет только в requirements.txt. Значит, код модуля не будет выполнен. Более того, эта зависимость является следствием бага pip и пакет с таким именем нельзя загрузить в 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
Но установка и наличие вредоносного пакета в системе еще не приводит к его выполнению. Чтобы модуль выполнился, в исполняемых файлах уязвимого приложения должна находиться конструкция import, при этом будет выполнен код, содержащийся в файле __init__.py.
Пример эксплуатации.Как лечить найденные багиВ моем случае с pkg-resources это даже не уязвимость, достаточно удалить строчку с зависимостью из requirements.txt. В более общем случае стоит посмотреть эту статью Microsoft, в ней подробно расписаны основные варианты фиксов под разные сборщики:
  • Используйте единый приватный package registry. Большинство сборщиков не приоритизируют источники зависимостей и опросят всё в поисках свежей версии пакета. Публичные пакеты также стоит загрузить в единый приватный package registry. 
  • Используйте пространство имен (scope) зависимостей. Некоторым сборщикам, например, npm, можно явно указать источник зависимостей для скоупа.
  • Используйте проверки пакетов на клиенте. Например, можно указывать конкретную версию пакета (version pinning), тогда не удастся атаковать с принудительным upgrade’ом. Также можно использовать хеши для контроля неизменности пакетов.
  • Используйте прокси для скачивания пакетов из интенет. На уровне компании договоритесь о наличии общего списка или нейминге приватных пакетов, например, private_package_name. Запретите на прокси скачивание из сети Интернет пакетов из белого списка или с указанными префиксом

===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_informatsionnaja_bezopasnost (Информационная безопасность), #_python, #_dependency_confusion, #_gitlab, #_informatsionnaja_bezopasnost (информационная безопасность), #_pypi, #_python3, #_python, #_blog_kompanii_sitimobil (
Блог компании Ситимобил
)
, #_informatsionnaja_bezopasnost (
Информационная безопасность
)
, #_python
Профиль  ЛС 
Показать сообщения:     

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

Текущее время: 30-Апр 13:37
Часовой пояс: UTC + 5