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

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

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

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

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

Категории

Все категории
Loading categories
gortex-PoC — PoC — переход по символической ссылке к раскрытию содержимого за пределами репозитория через search_text в Gortex (GHSA-6vhf-4wcm-2r83, CVE-2026-87003, CVSS 5.5). | Kitploit
Инструменты/GitHubGitHub/squeeze440/gortex-poc
Статический анализАнализ уязвимостейАнализ КодаЭксплуатацияСбор информацииВеб-безопасностьСтатьи и Исследования
GitHubsqueeze440/gortex-poc

gortex-PoC

PoC — переход по символической ссылке к раскрытию содержимого за пределами репозитория через search_text в Gortex (GHSA-6vhf-4wcm-2r83, CVE-2026-87003, CVSS 5.5).

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

Популярное

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

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

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

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

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

Следование по символическим ссылкам при обходе файлов индексатором → Раскрытие содержимого за пределами репозитория через search_text

Статус CVE: запрошен, ожидает присвоения. Данная находка опубликована как GHSA-6vhf-4wcm-2r83. При присвоении CVE данный репозиторий будет переименован в CVE-YYYY-NNNNN-gortex-PoC, а этот баннер заменён ссылкой на CVE.

ИсследовательDostxodjayev Abdullox (@squeeze440)
РекомендацияGHSA-6vhf-4wcm-2r83
CVSS 3.15.5 (Средний)
СлабостьCWE-59, CWE-200

Следование по символическим ссылкам при обходе файлов индексатором → Раскрытие содержимого за пределами репозитория через search_text

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

Недостаток корректного разрешения ссылок (CWE-59) в индексаторе репозиториев gortex позволяет записи файла, являющейся символической ссылкой и указывающей за пределы корня индексируемого репозитория, быть незаметно обойдённой, проиндексированной по содержимому и впоследствии отданной дословно — в том числе для цели, полностью находящейся за пределами корня — через живой приёмник повторного чтения MCP-инструмента search_text, который никогда не применяет собственную проверку ограничения guardSymlinkWithinRepo проекта.

Продукт

zzet/gortex — https://github.com/zzet/gortex

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

Коммит b5a63e25c0719c8ce935e59abf85618e2b4b1e64 (git describe: v0.62.0-35-gb5a63e25), HEAD репозитория на момент аудита. Подтверждено, что проблема всё ещё присутствует в последнем помеченном релизе v0.62.0, то есть после того, как исправление для несвязанной GHSA-w42c-h7hr-f67p (v0.55.0) было применено.

Оценка CVSS v3.1

CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N — 5.5 (Средний)

  • AV:L — соответствует собственному прецеденту оценки данного проекта для его MCP-поверхности (GHSA-w42c-h7hr-f67p также использовала AV:L): развёртывание по умолчанию — это локальный MCP-демон, доступный через stdio процессу агента на том же хосте; AV:N применялся бы только к опциональному режиму --http-addr.
  • UI:R — требует, чтобы MCP-клиент (LLM-агент или человек через gortex call) выполнил вызов search_text / search_text regexp:true. Широкого литерала (например, одного распространённого символа) или совпадающего регулярного выражения (.) против индексируемого репозитория, содержащего внедрённую символическую ссылку, достаточно для выгрузки целевого файла — секретного знания о его содержимом не требуется — так что это низкий порог, но это отдельное действие, отличное от простого индексирования.
  • C:H — раскрытие содержимого произвольных файлов, не ограниченное границами репозитория, всего, что может прочитать OS-пользователь демона (SSH-ключи, файлы облачных учётных данных, репозитории соседних арендаторов в многорепозиторном демоне и т. д.), возвращаемое дословно в ответе инструмента.
  • I:N / A:N — это чистая ошибка пути чтения; ничего не записывается и не становится недоступным.

Детали

Первопричина 1 — обход индексатора никогда не проверяет записи файлов, являющихся символическими ссылками

internal/indexer/indexer.go:2549-2604, основной обход допуска в корпус:

err = filepath.WalkDir(absRoot, func(path string, d os.DirEntry, err error) error {
    if err != nil { return nil }
    if d.IsDir() {
        if idx.shouldPruneDir(path, absRoot) { return filepath.SkipDir }
        return nil
    }
    lang, ok := idx.effectiveLanguage(path, nil)   // detects by extension; symlink name is enough
    if !ok { return nil }
    if idx.shouldExclude(path, absRoot, false) { return nil }
    info, statErr := d.Info()                      // Lstat'd DirEntry.Info() — no ModeSymlink check
    ...
    files = append(files, walkedFile{path: path, lang: lang, size: info.Size(), mtimeNano: info.ModTime().UnixNano()})
    return nil
})

filepath.WalkDir использует семантику Lstat, поэтому символическая ссылка на каталог естественно защищена — d.IsDir() для неё ложно, и в неё никогда не происходит рекурсивный спуск. Запись файла, являющегося символической ссылкой, не получает эквивалентной защиты: ничто здесь (ни в shouldExclude/shouldPruneDir, internal/indexer/indexer.go:5724-5813, которые сопоставляют только шаблоны путей в стиле gitignore) не вызывает d.Type()&os.ModeSymlink, os.Lstat или filepath.EvalSymlinks для записи файла перед постановкой её в очередь. Файл с именем, например, pwn.go, целью которого является /etc/passwd, ~/.ssh/id_rsa или репозиторий соседнего арендатора, допускается исключительно потому, что его имя соответствует зарегистрированному расширению (effectiveLanguage, internal/parser DetectLanguageContent, на основе пути). Именно этот список обойдённых файлов становится idx.fileMtimes (internal/indexer/indexer.go:3760: idx.fileMtimes[idx.relKey(f.path)] = f.mtimeNano).

Первопричина 2 — приёмник search_text перечитывает живые файлы без проверки ограничения

internal/indexer/grep.go:17-64 (GrepText / warmTrigramSearcher) строит триграммный поисковик непосредственно из ключей idx.fileMtimes:

rels := ... // from idx.fileMtimes, i.e. includes the symlinked file's rel path
idx.trigramSearcher = trigram.Build(root, rels)

internal/search/trigram/searcher.go:32-48 (Build) и :55-86/:102-176 (Grep/GrepRegexp) затем выполняют:

content, err := os.ReadFile(filepath.Join(root, filepath.FromSlash(rel)))  // Build — follows symlink
...
f, err := os.Open(filepath.Join(s.root, filepath.FromSlash(rel)))          // Grep/GrepRegexp — follows symlink

os.ReadFile/os.Open по умолчанию следуют по символическим ссылкам (без O_NOFOLLOW). Ни одна из этих функций, ни internal/mcp/tools_search_text.go:35-126 (handleSearchText, MCP-обработчик, вызывающий s.indexer.GrepText/GrepRegexp), никогда не вызывают resolveFilePath или guardSymlinkWithinRepo. Эти две функции ограничения существуют и корректно подключены ко всем остальным путям обслуживания содержимого — internal/mcp/tools_fileops.go (read_file, write_file/edit_file начиная с исправления v0.55.0), internal/mcp/tools_coding.go:919 (get_symbol_source), internal/mcp/tools_lsp.go:264, internal/mcp/tools_export.go:95 — но триграммный путь grep в search_text является отдельным приёмником, которому никогда не был дан тот же защитный механизм. grep -rn guardSymlinkWithinRepo по всему дереву подтверждает ноль ссылок в tools_search_text.go, grep.go или trigram/searcher.go.

Проверка на дублирование риска / отличимость

Это действительно отличается от GHSA-w42c-h7hr-f67p:

  • Та рекомендация: путь записи, resolveFilePath освобождающий абсолютные пути + write_file/edit_file/move_inline, никогда не вызывающие guardSymlinkWithinRepo (исправлено в v0.55.0).
  • Данная находка: путь чтения, собственный обход обнаружения индексатора (а не какой-либо MCP-обработчик) допускает файл, являющийся символической ссылкой, без проверки Lstat, и другой MCP-инструмент (search_text, а не read_file/get_symbol_source) обслуживает его содержимое через приёмник (internal/search/trigram), который независимо никогда не вызывает guardSymlinkWithinRepo. Исправление пути записи не затрагивало ни одно из этих двух мест. Это соответствует паттерну родственного инструмента, уже подтверждённому в ozgurcd/gograph (GHSA-6h6w-vhgr-2hp6) и vitali87/code-graph-rag (GHSA-85gg-2gfq-q95m): обход обнаружения файлов без защиты от символических ссылок в паре с приёмником обслуживания содержимого, который независимо лишён проверки ограничения.

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

Скачать инструмент