Бессмертные токены: почему смена пароля не спасёт от слива репозитория
Разработчик уволился, вы сменили ему пароль в AD, но его статический Personal Access Token продолжает пуллить код из GitLab. Разбираем анатомию скрытых бэкдоров.
«Мы сменили ему пароль, всё чисто»: величайшее заблуждение ИБ
Когда из компании с шумом или конфликтом уходит ведущий инженер, служба безопасности действует строго по инструкции: блокирует доменную учётку в Active Directory, меняет пароль на рабочей почте и сбрасывает сессии в корпоративном VPN.
На совещании отчитываются: *«Доступ закрыт, угроза нейтрализована»*.
Но через неделю исходный код закрытого микросервиса или свежий дамп клиентской базы всплывает на теневом форуме. Как?
Ответ прост: разработчики ненавидят вводить пароли. Для работы с Git по HTTPS, выкачивания артефактов и локального тестирования они генерируют Personal Access Tokens (PAT) и API-ключи. И эти токены живут совершенно отдельной жизнью.

---
Почему токены переживают увольнение сотрудников
Давайте разберёмся, как устроена жизнь типичного PAT в GitLab, GitHub, Grafana или внутренней системе документации:
1. Генерация внутри приложения. Токен выпускается в личном кабинете сервиса. Он представляет собой случайную криптографическую строку (например, glpat-xxxxxxxxxxxxxxxxxxxx).
2. Автономное хранение. Хеш токена сохраняется в локальной таблице базы данных приложения (personal_access_tokens).
3. Полная изоляция от пароля. Когда разработчик делает git clone https://oauth2:token@gitlab.company.ru/project.git, сервис даже не пытается проверять пароль пользователя в Active Directory или LDAP. Он просто ищет токен в своей базе.
В результате вы можете десять раз сменить доменный пароль, удалить пользователя из групп и вообще отключить контроллер домена — токен продолжит работать, пока не наступит дата его истечения.
А какую дату истечения разработчики выбирают при создании токена, если политика безопасности не закручена гайками? Правильно: «No expiration date» или максимум на год вперёд.
---
Где прячутся неучтённые токены
Если вы проведёте аудит в компании на 100 человек, вы гарантированно найдёте десятки «спящих» ключей доступа:
- Локальный файл
~/.gitconfigи~/.netrcна личном домашнем ноутбуке разработчика; - CI/CD пайплайны сторонних проектов, куда инженер однажды вставил свой токен для быстрого деплоя;
- Cron-скрипты на тестовых серверах, собирающие бэкапы или выгружающие логи;
- Скрипты аналитиков, тянущие данные из Grafana или ClickHouse через статический API Key.
Каждый такой токен — это прямой бэкдор в обход любого Active Directory и любого второго фактора.
---
Как закрыть дыру: 4 уровня защиты
Чтобы ликвидировать риск утечек через персональные токены, нужен системный подход:
1. Запрет бессрочных токенов на уровне политик
В настройках GitLab (Admin Area → Settings → General → Account and limit) необходимо принудительно выставить максимальный срок жизни токенов:
- Максимальный срок: не более 30 дней;
- Автоматическое напоминание об истечении за 7 дней.
Да, разработчикам придётся обновлять их раз в месяц. Но это снижает окно риска в двенадцать раз по сравнению с годовыми токенами.
2. Привязка профиля к состоянию в шлюзе доступа
При интеграции GitLab через единый шлюз доступа (OIDC) профиль пользователя жёстко связан с его статусом в шлюзе.
При блокировке сотрудника в Active Directory шлюз передаёт статус блокировки в приложение, и GitLab переводит учётную запись в статус Blocked. В заблокированном состоянии GitLab автоматически аннулирует все Personal Access Tokens и SSH-ключи, привязанные к этому профилю.
3. Отказ от парольного Git через HTTPS в пользу SSH с сертификатами
Персональные токены стали популярны именно потому, что вводить пароль при каждом пуше неудобно. Альтернатива — использование SSH-ключей с подписью корпоративного центра сертификации или работа через короткоживущие сессионные токены, получаемые через SSO CLI.
4. Регулярная инвентаризация статических ключей
Раз в квартал запускайте простой аудит по API:
# Получить список активных токенов со сроком действия более 60 дней
curl --header "PRIVATE-TOKEN: <ADMIN_TOKEN>" \
"https://gitlab.company.ru/api/v4/personal_access_tokens?revoked=false"
Все подозрительные или забытые токены должны безжалостно отзываться.
---
Вывод
Пароль — это лишь вершина айсберга корпоративного доступа. Если ваша процедура увольнения заканчивается галочкой в Active Directory, уволенный сотрудник остаётся с ключами от ваших репозиториев.
Безопасность достигается только тогда, когда блокировка пользователя в единой точке автоматически деактивирует не только веб-сессии, но и все порождённые им статические ключи доступа во всех сервисах компании.