Руководства по безопасности
Код, написанный ИИ, привёл к утечке API-ключа и мошенническим списаниям — настоящей причиной была незакрытая уязвимость CVSS 10.0
У приложения, собранного с помощью ИИ, крадут API-ключ, и появляются мошеннические списания — частый сценарий инди-разработки. Но настоящая причина не код от ИИ, а незакрытая публичная RCE с CVSS 10.0. Разбираем механизм и профилактику.
Случай, с которым часто сталкиваются инди-разработчики без опыта в безопасности, с убранными всеми идентифицирующими деталями и превращённый в урок. Здесь нет воспроизведения атаки — цель защита, чтобы та же ошибка не случилась с вами.
- Класс
- Утечка API-ключа / мошеннические списания
- Серьёзность
- Критическая (злоупотребление опубликованной CVSS 10.0)
- Корневая причина
- Pre-auth RCE в веб-фреймворке, месяцами оставшаяся незакрытой
- Масштаб утечки
- Все секреты окружения (вся связка ключей)
- Масштаб выполнения
- Осталось внутри непривилегированного контейнера (root хоста не пострадал)
- Постоянное решение
- ①обновиться до исправленной версии ②сменить все ключи ③машинный мониторинг CVE
«Остановили списания» ≠ «разобрались»
Остановить счёт — это первая помощь. Закрыть путь утечки — отдельная операция. Вы закончили только тогда, когда сделали и то, и другое.
Что произошло (хронология)
День 0 — выкатили и запустили
Приложение, собранное с помощью ИИ, было выпущено и работало в продакшене.Однажды — счёт взлетает
Счёт за облачный ИИ внезапно подскакивает. Массовые задания на модели, которой никогда бы не пользовались, делающие чужую работу.Расследование — злоупотребление со стороны
«Наше приложение сошло с ума» этого не объясняет. Кто-то посторонний запускал его с украденным ключом.Погоня — начинается настоящее расследование
«Так откуда утёк ключ?» — вот это и было настоящим расследованием.
Почему сразу не поймали (ложные пути)
В том порядке, в котором совершались ошибки, — потому что именно ошибки и есть урок.
Поспешный вывод о виновнике
→ Прежде чем решить «моя вина» или «их вина», сначала посмотрите на данные.
Чистый grep чуть не принёс облегчение
Скрытие симптома показалось исправлением
Чистый grep — это не отбой тревоги
Даже если ни в одном файле нет ключа, уязвимость может вытащить переменные окружения из работающего процесса. Утечки случаются в среде выполнения (RCE, HTTP-заголовки), а не только в файлах. См. Что такое RCE.
Настоящая причина: заброшенная опубликованная CVSS 10.0
Странная сигнатура в старых логах доступа мгновенно совпала с threat intel. У используемого диапазона версий веб-фреймворка была опубликованная pre-auth RCE (CVSS 10.0), которую уже эксплуатировали в дикой природе, — и она месяцами оставалась незакрытой.
- Это была не пассивная ошибка — злоумышленник выполнял код на сервере и выкачивал окружение.
- Спасло то, что выполнение осталось внутри непривилегированного контейнера (root хоста не захватили). Разбор взлома не нашёл устойчивого бэкдора, майнера или C2 — подтверждённым ущербом была кража секретов.
- Поскольку внутренняя БД была достижима, в ответных мерах исходили из того, что содержимое БД тоже утекло.
Урок: когда что-то ведёт себя странно, первым делом подозревайте известную CVE. Не считайте по умолчанию, что это ваш собственный баг.
Подсчёт тоже был неверным — судите по работающей версии
По ходу разбора сообщили о «ещё 8 уязвимых зависимостях» — тоже неверно. Их посчитали по нижней границе в package.json (диапазон с символом ^). По-настоящему опасными были лишь 2 зафиксированные (pinned) зависимости, оставшиеся позади.
Проверяйте свои реально работающие версии
Смотрите версии, которые на самом деле разрешились, — в lock-файле или в работающем контейнере.
# npm: посмотреть, что реально установлено
npm ls next react react-dom
# внутри работающего контейнера
docker exec <container> npm ls <package>Истина здесь — эти числа, а не ^ в package.json.
Что сделали в первую очередь (воспроизводимые шаги)
Немедленно отозвать ключ, которым злоупотребляли
Обновить фреймворк до исправленной версии
Сменить каждый секрет
Разбор взлома
Защита на стороне аккаунта
Настоящая профилактика: пусть следят машины
Если свести к сути, этот инцидент был «человек не заметил опубликованную CVSS 10.0». Ручные обходы всегда что-то пропускают. Машины — нет.
Сканирование зависимостей, которое можно начать сегодня
Бесплатно для старта — один шаг в CI.
# OSV scanner (Google) проверяет ваш lock-файл
osv-scanner --lockfile=pnpm-lock.yaml
# На GitHub включите Dependabot (Settings репозитория → Security)Этот сайт, согласно тому же уроку, сам мониторит свои зависимости на предмет CVE — мы практикуем то, что советуем.
Уроки
Частые ошибки
- Считать делом сделанным на «остановили списания»
- Расслабляться, потому что grep чистый
- Маскировать симптом на прокси и чувствовать, что исправлено
- Считать уязвимости по нижней границе
package.json - Менять лишь один ключ, по которому подтверждено злоупотребление
Правильная защита
- Считать первую помощь и «закрытие пути утечки» двумя разными задачами и делать обе
- Подозревать и утечки в среде выполнения (RCE, заголовки)
- Обновлять корень (фреймворк)
- Судить по реально работающей версии
- Заменять всё окружение, если оно утекло
В одну строку: взлетевший счёт был верхушкой айсберга. Настоящей причиной была заброшенная RCE с CVSS 10.0 — и истина пришла не от одной удачной догадки, а от того, что ошибались, сталкивались и стачивали ошибки.
Читать дальше
- Глоссарий: Что такое RCE · Что такое CVE · Что такое CVSS
- Защита: Безопасный запуск Next.js (гигиена CVE)
- Инцидент: Когда .env был доступен всему миру
FAQ
QЕсли утёк API-ключ, достаточно ли отозвать только тот ключ, которым злоупотребляли?
Нет. Когда путь утечки лежит в среде выполнения (RCE или утечка через заголовки), исходите из того, что разом утекли все секреты окружения, и меняйте их все. Ключ, злоупотребление которым вы заметили, — лишь верхушка айсберга.
QЕсли grep по коду и по git не находит ключей, я в безопасности?
Не обязательно. Даже если ни в одном файле нет ключа, уязвимость фреймворка может выкачать переменные окружения прямо из работающего процесса. Утечки случаются и в среде выполнения, а не только в файлах.
QЧто надёжнее всего предотвратит повторение?
Машинный мониторинг ваших зависимостей на предмет CVE. Корневой причиной здесь был человек, месяцами не замечавший опубликованную CVSS 10.0; Dependabot или osv-scanner структурно закрывают этот пробел.