РАЗБОР На проверке 

CVE-2026-60004: RCE в Gitea от регистрации до shell

Сергей Попов
Сергей Попов Red Team · 6,4 тыс. сообщений
Подписаться
83
Режим чтения
Плата одноплатного компьютера с сервером Gitea лежит на антистатическом лотке, зонд диагностики касается контактов у разорванного шлейфа. Экран ноутбука рядом светится холодным белым текстом с надп...


По данным The Shadowserver Foundation, более 8300 серверов Gitea с непропатченной CVE-2026-60004 торчат в интернет - большинство в Китае, Германии и США. В задокументированном инциденте автоматизированный exploit прошёл полную цепочку от регистрации аккаунта до выполнения shell-команды за 11 секунд. Без SSH, без украденных кредов, через обычный HTTPS. Просто открыл форму регистрации - и через 11 секунд id выполнился на хосте.

EPSS - 0.8678 при percentile 0.9973, это top 1% по вероятности эксплуатации среди всех CVE в базе. Ниже - механика бага, цепочка атаки с маппингом на MITRE ATT&CK и конкретные шаги для fingerprinting своего инстанса.

Механика CVE-2026-60004: удалённое выполнение кода Gitea через diffpatch

CVE-2026-60004 - уязвимость типа CWE-94 (Improper Control of Generation of Code) в API-эндпоинте POST /api/v1/repos/{owner}/{repo}/diffpatch. CVSS 3.1 - 9.8 (Critical), вектор: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. Каждый компонент тут работает против защитника: Подробнее - в нашем материале про cve эксплойт разработка.
  • AV:N - эксплуатация по сети, физический доступ не нужен
  • AC:L - условия воспроизведения тривиальны
  • PR:N - в дефолтной конфигурации с открытой регистрацией «нужен аккаунт с write-доступом» превращается в «нужен браузер»
  • UI:N - действий жертвы не нужно, exploit полностью автономен
  • C:H / I:H / A:H - полная компрометация конфиденциальности, целостности и доступности хоста
Затронуты все версии Gitea от 1.17.0 до 1.27.0 включительно - примерно четыре года продакшн-релизов. Обнаружил уязвимость ИБ-исследователь Шай Род (NightRang3r), security advisory - GHSA-rcr6-4jqh-j84m.

Bare clone и путь от патча до Git hook​

Эндпоинт diffpatch принимает пользовательский патч и применяет его к содержимому репозитория. Для обработки Gitea создавала временный bare clone. И вот тут - ключевой архитектурный просчёт. В bare-репозитории корневая директория совпадает с $GIT_DIR - служебной директорией Git, где лежат hooks, objects, refs. Рабочего дерева нет, всё в одной куче.

При вызове Gitea использовала git apply с флагами --index, --recount, --cached, --binary. На хостах с Git >= 2.32 добавлялся -3 (three-way merge fallback). Атака эксплуатирует именно поведение three-way merge:
  1. Атакующий отправляет один и тот же патч дважды через diffpatch
  2. Возникает add/add collision - конфликт при попытке добавить файл, уже существующий в индексе
  3. Three-way merge fallback записывает файл на диск, хотя флаг --cached должен ограничивать операцию индексом (должен - но не ограничивает)
  4. Поскольку clone - bare, путь hooks/post-index-change попадает прямо в директорию hooks Git
  5. Git автоматически исполняет этот hook при следующей операции с индексом внутри той же цепочки запросов diffpatch
Результат - произвольные shell-команды выполняются с привилегиями пользователя ОС, под которым работает Gitea (обычно git). Для пентестера тут важна бизнес-логика: Git-серверы по определению хранят исходный код, CI/CD-конфиги, deployment keys, переменные окружения с секретами, database credentials. Shell на таком хосте - immediate access к самым чувствительным активам engineering-команды. Lateral movement не нужен - всё уже здесь.

Эксплуатация RCE Gitea: от регистрации до shell​

📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

В файле proof лежало: uid=1000(git) gid=1000(git) groups=1000(git). Команда id реально выполнилась внутри контейнера.

Постэксплуатация и маппинг на MITRE ATT&CK​

После подтверждения RCE hook запускал вторую задачу в фоне - base64-encoded shell-loader. Loader последовательно пробовал curl, wget, python3 urllib, perl HTTP::Tiny, perl IO::Socket::INET для скачивания следующего stage. Прагматичный подход: автор payload заранее не знает, какие утилиты доступны в целевом контейнере, поэтому тупо перебирает все варианты. Загруженный dropper очищал переменные окружения, убивал конкурирующие процессы (стандартная техника crowding-out для cryptojacking), скачивал payload под архитектуру хоста и запускал его. CPU уходил в 70%.

Но криптомайнинг - пол, а не потолок ущерба. Тот же вектор даёт доступ к приватным репозиториям, CI/CD-секретам, OAuth-токенам, database credentials из app.ini и всей инфраструктуре, достижимой с хоста. Модификация кода в репозиториях и supply chain compromise - реалистичный сценарий, который куда сложнее заметить, чем майнер, сжирающий CPU. На одном из проектов я видел ситуацию, когда в зависимости тихо подмешали однострочный бэкдор - обнаружили через полгода, случайно.

Цепочка атаки в терминах MITRE ATT&CK:

ФазаТехникаТактикаID
Доступ через публичный эндпоинтExploit Public-Facing ApplicationInitial AccessT1190
Self-registrationValid AccountsInitial AccessT1078
Выполнение hookUnix ShellExecutionT1059.004
Закрепление через hookWeb Shell (Git hook как аналог)PersistenceT1505.003
Чтение секретов из конфиговCredentials In FilesCredential AccessT1552.001
Доступ к репозиториямCode RepositoriesCollectionT1213.003
Supply chainCompromise Software Dependencies and Development ToolsInitial AccessT1195.001

Как проверить Gitea на уязвимость CVE-2026-60004​

Fingerprinting версии​

Первый шаг - определить версию Gitea. API-эндпоинт /api/v1/version возвращает её в JSON:
Bash:
curl -s https://target:3000/api/v1/version | jq .version
Если API закрыт или требует аутентификации, версия часто торчит в HTTP-заголовке X-Gitea-Version - проверяется через curl -sI https://target:3000 | grep -i gitea. На главной странице большинства инстансов версия отображается в footer. Для массового fingerprinting по списку хостов подойдёт nmap -sV -p 3000,443,80 --script http-headers target с последующим парсингом вывода.

Уязвимы все версии от 1.17.0 до 1.27.0 включительно. Версия >= 1.27.1 - эндпоинт пропатчен. Но аудит конфигурации нужен и на обновлённом инстансе: открытая регистрация усиливает любую будущую уязвимость, требующую write-доступа.

Сканирование nuclei​

ProjectDiscovery выпустили шаблон для CVE-2026-60004 в официальном репозитории nuclei-templates (http/cves/2026/CVE-2026-60004.yaml):
Bash:
nuclei -t http/cves/2026/CVE-2026-60004.yaml -u https://target:3000
Для массового скана по списку целей заменяем -u на -l targets.txt. Шаблон проверяет версию и доступность уязвимого эндпоинта. Если на пентесте встретился Gitea - имеет смысл прогнать оба варианта.

Аудит конфигурации и предусловия эксплуатации​

Быстрая проверка без доступа к серверу: открыть https://target/user/sign_up. Форма регистрации отдаётся - self-registration включена. На пентесте это первый индикатор: сервер с открытой регистрацией и версией < 1.27.1 - pre-auth RCE без дополнительных условий.

Ключевые параметры в app.ini секции [service] для hardening:
  • DISABLE_REGISTRATION = true - закрыть регистрацию, если публичный доступ не нужен
  • REGISTER_EMAIL_CONFIRM = true - обязательное подтверждение email
  • ENABLE_OPENID_SIGNUP = false - отключить OpenID, если не используется
  • REQUIRE_SIGNIN_VIEW = true - скрыть содержимое от неаутентифицированных
Предусловия эксплуатации, которые стоит проверить при оценке конкретного инстанса: Git >= 2.32 на серверной стороне (нужен для three-way fallback), маршрут diffpatch включён (по умолчанию - да), временная файловая система writable и executable. Монтирование tmpfs с флагом noexec - один из mitigation'ов, который снижает риск до патча, но не устраняет уязвимость. Блокировка маршрута /api/v1/repos/.../diffpatch на уровне reverse proxy (Caddy, nginx) - ещё один вариант для случаев, когда немедленное обновление невозможно.

Патч Gitea CVE-2026-60004 и скорость weaponization​

Исправление в 1.27.1 - точечное и красивое: временный clone для обработки diffpatch изменён с bare на non-bare. В non-bare репозитории рабочая директория отделена от $GIT_DIR. Файл, записанный three-way merge fallback, попадает в рабочее дерево, а не в директорию hooks. Hook не создаётся, RCE не происходит. Одна строка - и уязвимости нет.

Деталь, которую подмечает CyCognito: в release notes 1.27.1 исправление указано в секции MISC как «patch-apply refactor», а не в секции SECURITY. Security advisory GHSA-rcr6-4jqh-j84m опубликован 28 июля - на день позже самого релиза. Команды, которые триажат обновления по наличию security-метки в changelog, пропустили этот релиз как рутинный. Урок для операторов: подписка на GitHub Security Advisories проекта (а не только на changelog) - единственный надёжный канал оповещения. Changelog вам соврёт.

Хронология от патча до подтверждённой эксплуатации в дикой природе:
  • 27 июля 2026 - выход Gitea 1.27.1
  • 28 июля 2026 - публикация advisory GHSA-rcr6-4jqh-j84m
  • Начало августа - появление публичных PoC на GitHub (наиболее известный - imbas007/CVE-2026-60004-POC, 17 звёзд на момент написания)
  • Середина августа - задокументированный инцидент с cryptominer-dropper'ом
  • 25 августа 2026 - CISA добавляет CVE-2026-60004 в каталог KEV, SSVC-решение: Act
  • 28 августа 2026 - дедлайн CISA на патч для федеральных агентств США
  • Сентябрь 2026 - Shadowserver фиксирует 8393 уязвимых IP
Меньше месяца от патча до confirmed in-the-wild exploitation. EPSS на сентябрь 2026 - 0.8678 при percentile 0.9973: из всех CVE в базе FIRST.org только 0.27% имеют более высокую вероятность эксплуатации в ближайшие 30 дней.

Безопасность сервера Gitea: детект компрометации​

Если инстанс работал на уязвимой версии с открытой регистрацией хотя бы несколько дней после публикации advisory - исходите из того, что компрометация произошла. Не «возможно произошла», а произошла. CISA в SSVC-решении явно указывает: exploitation - active, automatable - yes.

Поведенческие индикаторы​

Авторитетных IOC (хэши, домены, IP) по кампаниям с CVE-2026-60004 не опубликовано ни CISA, ни вендорами на момент написания. Детект строится на поведенческих признаках:
  • Аномальные аккаунты - пользователи, зарегистрированные после 28 июля 2026. В логах (docker logs gitea или journalctl -u gitea) искать POST /user/sign_up с последующим немедленным созданием репозитория и парным вызовом diffpatch
  • Парные вызовы diffpatch - два POST /api/v1/repos/.../diffpatch подряд к одному репозиторию от свежего аккаунта. Это сигнатура add/add collision exploit'а
  • Нехарактерные ветки - rce-proof, poc-*, test-hook в репозиториях неизвестных пользователей
  • Дочерние процессы Gitea - ps auxf для поиска shell'ов или неизвестных бинарников, порождённых процессом Gitea
  • Аномальная нагрузка CPU - устойчивые 50%+ без объяснимой причины (cryptojacking). Но тихий атакующий, нацеленный на exfiltration исходного кода, этого следа не оставит
  • Исходящие соединения - через ss -tnp или netstat -tnp проверить нетипичные outbound-подключения от процесса Gitea. Контейнер, подключающийся к неизвестным IP - повод для немедленного расследования

Что ротировать при подтверждённой компрометации​

Атакующий получил shell с правами пользователя Gitea. Считайте скомпрометированными: database credentials из app.ini и переменных окружения, OAuth и API-токены, SSH-ключи на хосте, CI/CD-секреты (если настроены Gitea Actions), deployment keys для связанных сервисов, любые секреты в приватных репозиториях (пароли в конфигах, .env-файлы). Проверьте приватные репозитории на несанкционированные коммиты. Если Gitea связана с CI/CD-пайплайнами - анализируйте downstream-системы на признаки Exploitation of Remote Services (T1210).

Паттерн: системные проблемы безопасности Gitea​

CVE-2026-60004 - не изолированный случай. Ранее в 2026 году была раскрыта CVE-2026-27771 (CWE-862, EPSS 0.0139) - недостаточная проверка прав доступа к Composer package source links, позволявшая раскрыть информацию об источниках приватных пакетов. Обе уязвимости объединяет одно: быстрый рост функций Gitea - package registry, patch API, hook automation - опережает глубину security review контроля доступа и обработки ввода. Для операторов self-hosted Gitea это означает: подписка на security advisories и мониторинг GHSA - обязательная часть операционного цикла, а не «когда-нибудь настроим».

CVE-2026-60004 высветила фундаментальное противоречие self-hosted решений. Gitea выбирают за лёгкость, минимальный overhead и независимость от облачных провайдеров. Эта же лёгкость создаёт иллюзию, что маленький Git-сервер «никому не интересен». Автоматическим сканерам не нужно знать название вашей компании - достаточно fingerprint'а сервиса и рабочего PoC. Восемь тысяч непропатченных инстансов через месяц после выхода фикса - это не «люди не успели». Это «люди не знали, что нужно». Changelog назвал критический патч рефакторингом, advisory вышел на день позже релиза, а кто триажит обновления по security-меткам - пропустил.

Криптомайнер на 70% CPU - самый безобидный исход. На каждом из 8393 серверов - чей-то исходный код, CI/CD-секреты, deployment keys. Атакующий, который вместо майнера тихо сливает репозитории и внедряет backdoor в зависимости, не оставит алерта по CPU и не привлечёт внимания хостера. Учитывая паттерн с CVE-2026-27771 (годы незамеченного auth bypass в registry), следующая уязвимость аналогичного калибра в Gitea - вопрос ближайших месяцев. Фичи растут быстрее, чем security review успевает их покрывать. Если хочешь разобрать подобную цепочку diffpatch-hook-shell на контролируемом стенде - web-задачи на HackerLab дают как раз этот формат.
Полезно

Комментарии

0

Ещё по теме