Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
terrapod-PoC — PoC — отсутствие авторизации в общеплатформенном хранилище доверенных якорей GPG в Terrapod (GHSA-6qrc-597p-mrp9, CVE-2026-87006, CVSS 6.5). | Kitploit
Инструменты/GitHubGitHub/squeeze440/terrapod-poc
Аутентификация и авторизацияАнализ уязвимостейЭксплуатацияВеб-безопасностьТестирование на ПроникновениеБезопасность Цепочки ПоставокСтатьи и Исследования
GitHubsqueeze440/terrapod-poc

terrapod-PoC

PoC — отсутствие авторизации в общеплатформенном хранилище доверенных якорей GPG в Terrapod (GHSA-6qrc-597p-mrp9, CVE-2026-87006, CVSS 6.5).

Репозиторий
7 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Terrapod: уведомление о безопасности

Статус CVE: запрошен, ожидает присвоения. Эта находка опубликована как GHSA-6qrc-597p-mrp9. После присвоения CVE этот репозиторий будет переименован в CVE-YYYY-NNNNN-terrapod-PoC, а этот баннер заменён ссылкой на CVE.

ИсследовательDostxodjayev Abdullox (@squeeze440)
УведомлениеGHSA-6qrc-597p-mrp9
CVSS 3.16.5 (Medium)
СлабостьCWE-862, CWE-284

Краткое описание

Отсутствие авторизации в API управления GPG-ключами в Terrapod (main @ b36d953, после v1.3.1) позволяет любому аутентифицированному субъекту — включая пользователя с единственной встроенной ролью everyone и без каких-либо предоставленных прав, либо ограниченный токен runner — создавать и удалять записи в общеплатформенном хранилище доверенных GPG-якорей, используемом для проверки подписей на каждом провайдере, публикуемом в приватный реестр, через POST /api/terrapod/v1/gpg-keys и DELETE /api/terrapod/v1/gpg-keys/{key_id}.

Продукт

Terrapod (mattrobinsonsre/terrapod) — самостоятельно размещаемая замена Terraform Enterprise / HCP Terraform.

Протестированная версия

Коммит b36d9535dedc31d85a02093d78f04da748492a2d (main), на 10 коммитов впереди ближайшего релизного тега v1.3.1. (v1.3.2 существует как тег, но находится в ветке release/v1.3 и ещё не слит в main; ошибка присутствует в обеих.)

Оценка CVSS v3.1

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N — 6.4 (Medium)

PR:L (не N): каждый запрос всё ещё требует действительных учётных данных — сессии, API-токена или даже ограниченного запуском токена runner runtok: — просто не привилегированных. I:H/C:N/A:N: ошибка позволяет непривилегированному вызывающему нарушить целостность общего хранилища доверенных ключей подписи реестра (удалить легитимные ключи, вставить свои), но сама по себе не раскрывает секретный ключевой материал (приватные ключи никогда не сериализуются ни в одном ответе) и не выводит сервис из строя.

Детали

services/terrapod/api/routers/gpg_keys.py реализует CRUD для строк GPGKey — публичных ключей в ASCII-armor, которым Terrapod доверяет при проверке отсоединённой подписи SHA256SUMS.sig на каждой версии провайдера, публикуемой в приватный реестр (services/terrapod/services/registry_provider_service.py:191-201, _verify_and_store_shasums_signature). Каждый маршрут в роутере защищён только Depends(get_current_user) — то есть «некоторым аутентифицированным субъектом» — без какой-либо проверки роли или прав:

  • create_gpg_key_endpoint — services/terrapod/api/routers/gpg_keys.py:104-130
  • list_gpg_keys_endpoint — gpg_keys.py:133-146
  • show_gpg_key_endpoint — gpg_keys.py:149-166
  • revoke_gpg_key_endpoint — gpg_keys.py:168-193
  • delete_gpg_key_endpoint — gpg_keys.py:195-213

Базовые сервисные функции (services/terrapod/services/gpg_key_service.py:144 create_gpg_key, :316 delete_gpg_key) вообще не принимают аргумент вызывающего/владельца — у GPGKey нет столбца пространства имён или владельца (_gpg_key_to_jsonapi жёстко задаёт "namespace": "default"; поле namespace, принимаемое при создании, разбирается моделью запроса, но никогда не передаётся дальше). Набор ключей — это один глобальный общий список для всей платформы.

Сравните это с любым другим административным ресурсом платформы в той же кодовой базе — tokens.py, roles.py, vcs_connections.py, role_assignments.py — которые все защищают изменяющие маршруты за require_admin или явной проверкой владения bound_to == user.email or is_admin. gpg_keys.py — единственный роутер в api/routers/, который управляет общеплатформенным критичным для безопасности ресурсом без всего этого.

Цепочка воздействия: get_gpg_key_by_key_id() (registry_provider_service.py:195) выполняет глобальный поиск без привязки к пространству имён — любой ключ, когда-либо зарегистрированный кем угодно, является действительным доверенным якорем для публикации любого провайдера (это сделано намеренно для самостоятельной регистрации ключей издателя — сообщение об ошибке даже гласит add it via /api/terrapod/v1/gpg-keys first). Поскольку регистрация не имеет проверки авторизации, а удаление тоже не имеет проверки авторизации:

  1. Любой аутентифицированный пользователь (или утёкший/замеченный токен runner, который require_non_runner существует специально, чтобы не допускать к «endpoints создания и управления ресурсами» согласно его собственному docstring в services/terrapod/api/dependencies.py:387-400, но который этот роутер никогда не использует) может удалить зарегистрированный ключ подписи любого другого арендатора, нарушив проверку подписи для каждой версии провайдера, которую этот арендатор уже опубликовал — межарендаторная атака на целостность, не требующая никакой связи с целевым пространством имён.
  2. Тот же вызывающий может зарегистрировать новый доверенный ключ, расширив общий набор доверенных якорей платформы без каких-либо ограничений, кроме наличия любых учётных данных.

Собственный набор тестов проекта документирует этот пробел, не подвергая его сомнению — services/tests/api/test_gpg_keys.py строит свои happy-path тесты create/delete/revoke с AuthenticatedUser(roles=["everyone"], ...) (см. _user(), строка 23, используется повсюду в TestCreate/TestDelete/TestRevoke) и утверждает 201/204 для этого непривилегированного пользователя — то есть тесты утверждают уязвимое поведение как корректное, они просто никогда не были написаны так, чтобы задать вопрос «должна ли роль everyone иметь право это делать?»

Доказательство концепции

Динамически проверено на реальном приложении (реальные Postgres + Redis через собственный интеграционный тестовый стенд проекта docker-compose.test.yml — без моков, без посторонних модификаций кода приложения):

  1. Написан services/tests/integration/test_gpg_key_missing_authz_poc.py:
    • test_everyone_role_user_can_delete_admins_signing_key — admin регистрирует реальный публичный PGP-ключ RSA-2048 через POST /api/terrapod/v1/gpg-keys (201, подтверждено наличие в Postgres), затем второй пользователь, аутентифицированный только с roles=["everyone"] (без admin, без предоставленных прав), отправляет DELETE /api/terrapod/v1/gpg-keys/{key_id}, и это succeeds (204); строка подтверждённо исчезает из Postgres после этого.
    • test_everyone_role_user_can_register_new_trusted_key — тот же непривилегированный пользователь регистрирует совершенно новый ключ через POST /api/terrapod/v1/gpg-keys (201).
  2. Собран тестовый образ и запущен против реальной инфраструктуры:
    root@kitploit:~
    docker build -f docker/Dockerfile.test -t terrapod-test:local .
    docker compose -f docker-compose.test.yml run --rm test \
      pytest tests/integration/test_gpg_key_missing_authz_poc.py -v -m integration
    
    Результат: — оба утверждения (успешное неавторизованное удаление и фактическое исчезновение строки из реальной базы данных) подтвердились. Скриншот: .

Воздействие

Любой аутентифицированный пользователь экземпляра Terrapod — независимо от роли, доступа к рабочему пространству или прав в реестре, вплоть до встроенной непривилегированной роли everyone или ограниченного одним запуском токена runner — может подменить общее хранилище доверенных GPG-якорей платформы: удалить зарегистрированный ключ подписи другой команды (нарушив проверку подписи terraform init для каждой версии провайдера, которую они уже опубликовали, в масштабе всей платформы) и/или добавить новые ключи в доверенный набор. Это подрывает гарантию цепочки поставок «приватный реестр модулей + провайдеров с GPG-подписью», которую проект рекламирует как ключевую функцию, не требуя от атакующего каких-либо привилегий в рабочем пространстве или реестре.

Слабости

  • CWE-862: Missing Authorization
  • CWE-284: Improper Access Control

Устранение

Добавьте проверку прав/роли на изменяющие маршруты в services/terrapod/api/routers/gpg_keys.py, следуя шаблону, уже используемому в tokens.py/roles.py/vcs_connections.py — например, Depends(require_admin) на create_gpg_key_endpoint, delete_gpg_key_endpoint и revoke_gpg_key_endpoint (revoke отдельно защищён требованием действительного сертификата самоподписи, но всё равно не должен быть доступен произвольному вызывающему для ключей других арендаторов). list/show менее рискованны (блоки armor по своей природе являются публичными ключами), но, вероятно, также должны требовать как минимум require_non_runner для согласованности. Рассмотрите также введение столбца пространства имён/владельца в GPGKey, если предполагаемая модель — самостоятельное управление ключами издателя по пространствам имён, чтобы владелец пространства имён мог управлять только своим ключом(ами), а не единым глобальным списком.

Благодарность: Dostxodjayev Abdullox

Канал сообщения об уязвимости: Согласно SECURITY.md, не открывайте публичный issue. Используйте приватное сообщение об уязвимостях GitHub: перейдите на https://github.com/mattrobinsonsre/terrapod/security/advisories/new, нажмите «Report a vulnerability» и заполните описание, шаги воспроизведения и затронутые версии. (Если PVR недоступен, политика предписывает написать мейнтейнеру напрямую.)

Скачать инструмент
2 passed
evidence/gpg_key_authz_poc_run3.png