
PoC и разбор повышения привилегий в HackTheBox "Nexus": запускаемая от root служба синхронизации шаблонов Gitea, уязвимая к обходу пути через поддельные Git-объекты. Только для образовательных целей.
Обход пути при синхронизации шаблонов Gitea через поддельные Git-объекты → root
Proof-of-concept эксплойта для повышения привилегий на машине HackTheBox Nexus.
Принадлежащий root systemd-сервис синхронизирует шаблонные репозитории Gitea на диск
без очистки имён записей, что позволяет аутентифицированному низкопривилегированному пользователю
записывать произвольные файлы от имени root через обход каталога — здесь это используется для внедрения
SSH-ключа в /root/.ssh/authorized_keys.
Этот код предоставлен исключительно в образовательных целях и для авторизованного тестирования безопасности — то есть для лабораторных сред, таких как HackTheBox, или систем, которыми вы владеете или на тестирование которых у вас есть явное письменное разрешение. Неавторизованное использование против систем, которые вы не контролируете, незаконно. Автор не несёт ответственности за неправомерное использование.
Если машина Nexus всё ещё активна на HackTheBox, не публикуйте и не распространяйте этот эксплойт — правила HTB запрещают распространение решений для активных машин.
Скрипт синхронизации читает файлы из репозиториев, помеченных как шаблоны в Gitea, и записывает их в локальную файловую систему. Путь назначения строится примерно так:
dest = os.path.join(base_dir, name) # name comes straight from the Git tree
open(dest, "w").write(content)
os.path.join() не нейтрализует последовательности ... Поэтому запись дерева, имя которой
является путём обхода (например, ../../../../../root/.ssh/authorized_keys), заставляет
привилегированный процесс записать файл вне предполагаемого каталога.
Git хранит содержимое и имена отдельно:
name → object (именно здесь хранится имя файла);Имя файла в записи дерева — это просто текст, поэтому оно может быть .. — но стандартный
клиент Git отказывается создавать такую запись, именно чтобы предотвратить эту атаку.
Этот PoC обходит клиентскую проверку, записывая необработанные Git-объекты напрямую
в .git/objects/ (вычисляя SHA-1 идентификаторы вручную) и вручную формируя refs/heads/main.
Отправленный репозиторий затем содержит запись дерева с именем .., которую
root-процесс синхронизации разрешает и следует по ней.
www-data..env, переиспользованные как
системный пароль → SSH от имени низкопривилегированного пользователя.root.Повторяющаяся тема на всех трёх этапах: привилегированный процесс доверяет контролируемым атакующим данным без валидации (подделанный MIME-тип, переиспользованный пароль, неочищенное имя файла).
http://localhost:3000.git, python3, curl и ssh (по умолчанию на машине).chmod +x nexus_privesc.sh
./nexus_privesc.sh -t <TARGET_IP> -u <GITEA_USER> -p <GITEA_PASS> [-d DEPTH]
Пример:
./nexus_privesc.sh -t 10.129.21.192 -u jones -p 'REDACTED' -d 5
/tmp/.exploit_key)..., которое сопоставляется с
/root/.ssh/authorized_keys, с публичным ключом атакующего в качестве содержимого.root с внедрённым ключом.Отслеживайте синхронизацию на цели с помощью:
tail -f /var/log/template-sync.log
Успешный запуск записывает строку вида:
synced: ../../../../../root/.ssh/authorized_keys
DEPTHDEPTH — это количество уровней .., необходимых для подъёма из каталога
синхронизации/подготовки до корня файловой системы (/). Если синхронизация в логе проходит успешно, но
root SSH не удаётся, обход попал на неверный уровень — повторите с -d 4 или
-d 6. Точное значение можно подтвердить, прочитав путь подготовки в
/etc/gitea/template-sync.py.
Никогда не строите пути файловой системы из недоверенных имён с помощью одного лишь os.path.join().
Нормализуйте и ограничивайте пути, например:
base = os.path.realpath(base_dir)
dest = os.path.realpath(os.path.join(base, name))
if not dest.startswith(base + os.sep):
raise ValueError("path traversal blocked")
Отклоняйте имена записей дерева, содержащие .., абсолютные пути или разделители путей.
Запускайте сервис синхронизации под выделенной низкопривилегированной учётной записью, а не root.
Включите receive.fsckObjects = true в Gitea, чтобы отклонять некорректные отправленные объекты.
<your name / handle> — для образовательного использования на HackTheBox.
| Класс | Обход каталога (CWE-22) → Локальное повышение привилегий |
| Компонент | gitea-template-sync.service (кастомный /etc/gitea/template-sync.py) |
| Запускается от | root, срабатывает каждые ~60 с через gitea-template-sync.timer |
| Первопричина | os.path.join() по неочищенным именам, взятым из объектов Git tree |
| Воздействие | Аутентифицированный низкопривилегированный пользователь → root |
| Флаг | Описание | По умолчанию |
|---|
-t | IP цели (для финального root SSH) | — (обязательно) |
-u | Имя пользователя Gitea | — (обязательно) |
-p | Пароль Gitea | — (обязательно) |
-d | Количество уровней .. для достижения / из каталога синхронизации | 5 |