Bug2Lab · Secure Code · Java / Spring

Утечка секрета в конфигурации

В этой лабораторной мы разбираем классическую ситуацию: секреты (пароли, токены, ключи) попадают в конфигурацию приложения и могут быть считаны извне. Цель — понять, как выглядит атака, почему так вообще случается и какой паттерн кода должен стать стандартом в команде.

1
Как выглядит атака
Злоумышленник обращается к внутреннему служебному эндпоинту конфигурации и получает чувствительные значения, включая пароли к БД и API-ключи.
GET /internal/config
200 OK
{
  "datasource.password": "P@ssw0rd123",
  "payment.apiKey": "LIVE_API_KEY_9f3a..."
}
2
Почему это стало возможным
Секреты захардкожены прямо в application.yml. Конфигурация не должна содержать реальные пароли продакшена, но они попали в билд как есть.
Проблемный код
12 spring:
13 datasource:
14 url: "jdbc:postgresql://internal-db.example.local:5432/prod"
15 username: "app_user"
16 password: "P@ssw0rd123" # ❌ секрет в явном виде
17 payment:
18 apiKey: "LIVE_API_KEY_9f3a..." # ❌ продовый ключ в коде
3
Как это чинится правильно
Секреты не живут в репозитории. Они подтягиваются во время деплоя из секрет-хранилища (Vault / KMS / Secret Manager и т.д.). В коде и в конфиге остаются только ссылки.
Исправленный паттерн
12 spring:
13 datasource:
14 url: "jdbc:postgresql://internal-db.example.local:5432/prod"
15 username: "app_user"
16 password: ${DB_PASSWORD_FROM_VAULT} # ✅ подтягивается на деплое
17 payment:
18 apiKey: ${PAYMENT_API_KEY_FROM_VAULT} # ✅ нет ключа в репо

bug2regress Регрессионный тест (стоп-кран в релизе)

По этой уязвимости создаётся автоматическая проверка, которая крутится в пайплайне. Если приложение снова начнёт отдавать секреты наружу — релиз блокируется. То есть эта же проблема не сможет тихо вернуться в прод.

#!/bin/bash
# smoke-secrets-check.sh
# Цель: убедиться, что сервис НЕ светит чувствительные значения

RESPONSE=$(curl -s -H "Authorization: Bearer test-token" \
  https://staging.example.internal/internal/config)

# Если в ответе есть потенциальный секрет — завали билд
if echo "$RESPONSE" | grep -E '(P@ssw0rd|API_KEY|SECRET|BEGIN RSA PRIVATE KEY)'; then
  echo "[BLOCK] Sensitive data exposed in /internal/config"
  exit 1
fi

echo "[OK] No secrets leaked"
exit 0

Этот скрипт подключается в CI/CD. Если он падает — билд считается небезопасным и дальше не едет. Это и есть техническая гарантия «эта боль не повторится без вашего ведома».

Проверка понимания Что именно было не так?

Отметьте корневую причину уязвимости. Это фиксируется как новый стандарт код-ревью.

Правильный стандарт после этой лабораторной: в репозитории и в образе не остаётся продовых секретов. Секреты приезжают во время деплоя из секрет-хранилища.

Теория (по желанию) Почему утечка секрета — это катастрофа для бизнеса