Исследователи Kaspersky нашли в репозитории Python Package Index три пакета, которые тайно устанавливали новую вредоносную программу ZiChatBot на Windows и Linux. Инцидент важен для разработчиков, администраторов и компаний, где зависимости из открытых репозиториев попадают в рабочие проекты без строгой проверки.

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

Как вредоносные пакеты попали к разработчикам

По данным Kaspersky, злоумышленники загрузили в PyPI три пакета: uuid32-utils, colorinal и termncolor. Все они появились за короткий период — с 16 по 22 июля 2025 года.

До удаления uuid32-utils набрал 1479 загрузок, colorinal — 614, termncolor — 387. На страницах PyPI пакеты выглядели правдоподобно и даже выполняли заявленные функции. Это и делало схему опасной: пользователь видел рабочую библиотеку, но вместе с ней получал скрытую нагрузку.

Два первых пакета, uuid32-utils и colorinal, использовали похожие вредоносные компоненты. termncolor выглядел безобиднее, но указывал colorinal как зависимость. Такой приём часто помогает атакующим провести вредоносный код через цепочку установок, когда разработчик проверяет только верхний уровень пакетов.

Что делает ZiChatBot и почему его сложнее заметить

ZiChatBot отличается от многих вредоносных программ тем, что не связывается с отдельным сервером управления. Вместо этого программа использует REST API публичного корпоративного чата Zulip как канал команд. C2, или command and control, — это инфраструктура, через которую оператор отдаёт команды заражённой системе и получает ответы.

Такой подход усложняет обнаружение. Сетевой трафик может выглядеть как обращение к обычному сервису командной переписки, а не как связь с подозрительным доменом. Для корпоративной защиты это неприятный сценарий: фильтры часто доверяют известным облачным платформам больше, чем неизвестным адресам.

ZiChatBot получает и запускает shellcode — небольшой фрагмент машинного кода, который выполняет команды на заражённой системе. После успешного выполнения вредоносная программа отправляет в ответ эмодзи с сердцем. Для пользователя это незаметная деталь, но для оператора атаки — сигнал, что команда прошла.

Windows и Linux: разные следы, один риск

На Windows вредоносный код извлекает DLL-файл terminate.dll и записывает его на диск. Когда библиотеку импортируют в проект, DLL загружается и запускает установку ZiChatBot. Затем код добавляет запись автозапуска в реестр Windows и пытается удалить следы первоначального файла.

На Linux схема устроена иначе. Вредоносный компонент terminate.so размещает ZiChatBot по пути /tmp/obsHub/obs-check-update и добавляет задачу в crontab. Так программа получает запуск по расписанию и может пережить перезагрузку или завершение пользовательской сессии.

Для защитников важны оба набора признаков. Если в проекте использовали uuid32-utils или colorinal, стоит проверить не только каталог с зависимостями, но и автозагрузку, временные директории, задачи планировщика и сетевые обращения к сервисам командной переписки.

Почему открытый репозиторий не равен безопасному коду

PyPI остаётся ключевым источником библиотек для Python-разработки. Но открытый репозиторий не проверяет каждую строку кода так, как это делает внутренняя команда безопасности. Злоумышленники пользуются привычкой быстро ставить зависимости по инструкции из README или ответа в рабочем чате.

Особенно опасны бинарные wheel-пакеты. В них может лежать уже собранный компонент, который сложнее проверить беглым просмотром. Если библиотека подтягивает DLL или SO-файл, команда должна понимать, зачем он нужен и кто его собрал.

Та же логика работает не только для Python. Любая цепочка зависимостей, плагинов и вспомогательных инструментов может стать каналом атаки. Ранее мы разбирали, как уязвимость Ollama грозит утечкой ключей API и переписок: там проблема тоже касалась данных, которые разработчики часто считают внутренними и недоступными извне.

Кто может стоять за атакой

Kaspersky пишет, что авторов кампании точно не установили. Исследователи нашли 64 % сходства между дроппером ZiChatBot и другим дроппером, который связывают с OceanLotus, также известной как APT32. Эту группу обычно описывают как связанную с Вьетнамом.

В конце 2024 года специалисты уже фиксировали активность OceanLotus против китайского сообщества специалистов по кибербезопасности. Тогда атакующие распространяли заражённые проекты Visual Studio Code, которые маскировались под плагины для Cobalt Strike и запускали троян при сборке проекта. По анализу ThreatBook, вредоносная программа использовала сервис заметок Notion как канал управления.

Если связь подтвердится, кампания с PyPI покажет расширение тактики: вместо писем с фишингом атакующие всё чаще идут через инструменты разработки. Для компаний это сигнал пересмотреть правила работы с внешними пакетами, а не ограничиваться антивирусом на конечных устройствах. Пользователям Windows также стоит следить за изменениями в системе: часть практических ориентиров мы собрали в материале о том, что важно для безопасности в новых бета-сборках Windows 11.

Что сделать разработчикам и администраторам

  • Проверьте, не использовали ли проекты пакеты uuid32-utils, colorinal и termncolor, включая старые сборки и тестовые окружения.
  • Удалите подозрительные зависимости и пересоберите окружения из чистых lock-файлов.
  • Проверьте Windows на записи автозапуска, связанные с неизвестными DLL, особенно terminate.dll.
  • На Linux проверьте /tmp/obsHub/obs-check-update и задания crontab для системных и пользовательских учётных записей.
  • Посмотрите журналы сетевых подключений к неожиданным сервисам командной переписки и облачным API.
  • Включите правило: новые зависимости проходят ревью, а бинарные wheel-пакеты — отдельную проверку.
  • Храните токены, ключи API и пароли вне кода; после инцидента меняйте их, даже если утечка не подтверждена.
  • Для работы из кафе, гостиниц и коворкингов используйте сервис безопасного интернет-соединения, чтобы снизить риск перехвата данных в публичных сетях.
  • Настройте внутренний репозиторий или зеркало пакетов, где команда хранит только проверенные версии зависимостей.
Поделиться: