🔓
1. Что здесь по сути сломано?
Мы говорим не про логин/пароль пользователя.
Мы говорим про контроль прав внутри приложения.
У нас есть эндпоинт /admin/exportUsers, который делает очень чувствительную вещь:
даёт полный список пользователей с их признаками (например, VIP-клиенты).
Этот эндпоинт должен быть доступен только роли ADMIN.
Но проверка роли отсутствует. В итоге любой пользователь (а иногда вообще аноним)
может выкачать то, что должно видеть только руководство / служба качества / финконтроль.
💼
2. Почему бизнесу от этого реально больно?
- 📥 Утечка клиентских данных. Если наружу уходит e-mail, статусы, VIP-метки, суммы трат — это персональные данные и коммерческая инфа.
- 📣 PR-ад. Любой журналист может написать: «Из внутреннего админ-интерфейса компании Х можно скачать базу клиентов в один клик».
- ⚖️ Регуляторка. В некоторых отраслях (банк, телеком, госсектор) это автоматически трактуется как инцидент безопасности с обязательной отчетностью.
- 🤝 Потеря доверия крупных клиентов. Если внезапно выясняется, что статус «VIP» + e-mail легко достать — вы выглядите небезопасными.
И хуже всего: в логах видно будет, что это был не «внешний взлом фаервола»,
а ваше приложение само всё отдало. Это очень тяжело оправдывать.
🧪
3. Как такое вообще попадает в прод? Это же очевидно, да?
Сценарий очень бытовой:
- 👨💻 Делали отладочный эндпоинт «для себя», чтобы быстрее выгружать данные и проверять качество.
- 🚀 Этот эндпоинт попал в релиз «временно», чтобы «быстро помочь саппорту/аналитикам».
- 🙃 Никто не добавил проверку роли, потому что «мы ж этим только внутри пользуемся».
- 🌍 Через месяц оказалось, что эндпоинт доступен и из не тех сред (staging → dev proxy → прод и т.д.).
Это не звучит как «хакеры взломали нашу суперадминку», это звучит как
«мы выкатили техдолг в прод и забыли закрыть дверь».
🔁
4. Почему просто "добавить @PreAuthorize" недостаточно?
Даже если мы сейчас навесим
@PreAuthorize("hasRole('ADMIN')"),
та же ошибка может повториться в другом «временном» эндпоинте через две недели.
Почему?
- Появится новый
/admin/downloadStats, «тоже временный».
- Его сделает другой разработчик, который не в курсе прошлой истории.
- Он тоже забудет про проверку роли, потому что «мы же все внутри».
Это не проблема конкретного метода exportUsers().
Это паттерн культуры: «в админку можно не ставить авторизацию, потому что это типа внутрянка».
Пока паттерн не убили — уязвимость вернётся.
📏
5. Что мы считаем стандартом после этой лабораторной
- 🔐 Любой эндпоинт с
/admin/, /internal/, /export, /download обязан иметь явную проверку роли/привилегии.
- 🚫 Недопустимы «скрытые URL» в стиле «ну этот путь просто никто не знает» — безопасность через секретный путь не считается защитой.
- 📣 Любой доступ к данным, которые нельзя показывать обычному пользователю, должен возвращать
403 Forbidden, если роль не совпадает.
Это должно стать правилом ревью, не «рекомендацией безопасности».
То есть это техническое требование качества кода.
🛡️
6. Зачем нужен регрессионный тест в пайплайне
Без регресса всё снова упрётся в «ну давайте надеяться, что все не забудут».
Нам так не подходит.
- 🤖 Мы автоматом ходим в чувствительный эндпоинт ТЕСТОВЫМ (не админским) токеном.
- ⛔ Если получили 200 OK и чувствительные данные — билд стопается, релиз не уезжает.
- 📉 В итоге фраза «ой, забыли повесить роль» превращается не в аварийку на проде, а в «упал билд на стейдже, почини и откатывайся».
Это разница между «федеральные новости о сливе базы клиентов» и «CI упал, поправили аннотацию, через 15 минут всё зелёное».
📄
7. Что мы теперь можем показать руководству / аудитору
- ✅ Мы обнаружили факт небезопасного доступа к административному интерфейсу.
- 👩💻 Мы обучили команду и зафиксировали обязательный паттерн авторизации.
- 🔐 Мы внедрили проверку роли в коде (теперь нужен ADMIN).
- 🚦 Мы поставили регрессионный тест, который не даст этому вернуться в прод тихо.
Это звучит не как «у нас нашли дыру», а как
«мы закрыли класс рисков и теперь он под техническим контролем».
✅
8. Что нужно запомнить команде
- Админ-эндпоинт без проверки роли — это утечка клиентских данных в один клик.
- Спрятать URL недостаточно. Нужна проверка роли в коде.
- 403 для неадмина — это норма, не «мешает тестировщику».
- Регресс в CI/CD следит, чтобы мы не забыли это завтра.
Это не «сделайте, пожалуйста, безопасно».
Это стандарт качества продукта.