Уязвимое банковское приложение 🏦
Намеренно уязвимое веб-приложение для отработки навыков тестирования безопасности веб-приложений, API и LLM, безопасного ревью кода и внедрения безопасности в CI/CD-конвейеры.
⚠️ ПРЕДУПРЕЖДЕНИЕ: Это приложение намеренно уязвимо и должно использоваться только в образовательных целях в изолированных средах.

Обзор
Этот проект представляет собой простое банковское приложение со встроенными многочисленными уязвимостями безопасности. Он создан, чтобы помочь инженерам безопасности, разработчикам, стажёрам, QA-аналитикам и DevSecOps-специалистам узнать о:
- Распространённых уязвимостях веб-приложений и API
- Уязвимостях AI/LLM
- Практиках безопасного написания кода
- Автоматизации тестирования безопасности
- Внедрении DevSecOps
Возможности и уязвимости
Основные банковские функции
- 🔐 Аутентификация и авторизация пользователей
- 💰 Управление балансом счёта
- 💸 Денежные переводы
- 📝 Заявки на кредит
- 👤 Загрузка фото профиля
- 📊 История транзакций
- 📈 Панель аналитики транзакций (на базе GraphQL)
- 🔑 Система сброса пароля (3-значный PIN-код)
- 💳 Управление мультивалютными виртуальными картами
- 💱 Пополнение виртуальной карты с основного USD-баланса со встроенной конвертацией валют (
USD, GBP, NGN, JPY, EUR, QAR, BTC, ETH)
- 🛒 Публичный Merchant Payment API для намеренно уязвимых ecommerce/демо-интеграций
- 📱 Система оплаты счетов
- 🤖 ИИ-агент поддержки клиентов (реальная LLM с DeepSeek API / режим заглушки)

Реализованные уязвимости
-
Аутентификация и авторизация
- SQL-инъекция при входе
- Слабая реализация JWT
- Нарушенная авторизация на уровне объектов (BOLA)
- Нарушенная авторизация на уровне свойств объектов (BOPLA)
- Массовое присваивание и чрезмерное раскрытие данных
- Слабый механизм сброса пароля (3-значный PIN-код)
- Токен хранится в localStorage
- Отсутствует инвалидация токена на стороне сервера
- Отсутствует истечение срока сессии
-
Безопасность данных
- Раскрытие информации
- Раскрытие чувствительных данных
- Хранение паролей в открытом виде
- Точки SQL-инъекций
- Раскрытие отладочной информации
- Раскрытие подробных сообщений об ошибках
-
Уязвимости транзакций
- Отсутствует проверка суммы
- Возможны переводы с отрицательной суммой
- Отсутствуют лимиты транзакций
- Состояния гонки при переводах и обновлении баланса
- Раскрытие информации из истории транзакций
- Отсутствует проверка счетов получателей
-
Операции с файлами
- Неограниченная загрузка файлов
- Уязвимости обхода пути (path traversal)
- Отсутствует проверка типа файла
- Обход каталогов
- Отсутствуют ограничения размера файла
- Небезопасное именование файлов
- Подделка серверных запросов (SSRF) через импорт изображения профиля по URL
-
Управление сессиями
- Уязвимости токенов
- Отсутствует истечение срока сессии
- Слабые секретные ключи
- Раскрытие токена в URL
-
Недостатки на стороне клиента и сервера
- Межсайтовый скриптинг (XSS)
- Межсайтовая подделка запросов (CSRF)
- Небезопасные прямые ссылки на объекты
- Отсутствует ограничение частоты запросов
-
Уязвимости виртуальных карт
- Массовое присваивание при обновлении лимитов карты
- Массовое присваивание при обработке обменного курса при пополнении карты
- Предсказуемая генерация номеров карт
- Хранение данных карты в открытом виде
- Отсутствует проверка лимитов карты
- BOLA при операциях с картами
- Состояния гонки при обновлении баланса
- Раскрытие данных карты
- Отсутствует проверка транзакций
- Отсутствие мониторинга активности карты
- Конвертация валюты, управляемая клиентом, при пополнении карты
-
Уязвимости оплаты счетов
- Отсутствует проверка сумм платежей
- SQL-инъекция в запросах поставщика услуг
- Раскрытие информации в истории платежей
- Предсказуемые номера ссылок
- Раскрытие истории транзакций
- Отсутствует проверка счетов поставщиков услуг
- Состояния гонки при обработке платежей
- BOLA при доступе к истории платежей
- Отсутствуют лимиты платежей
-
Уязвимости Merchant Payment API
- Пароли мерчантов и API-ключи в открытом виде
- API-ключи возвращаются в ответах при регистрации и входе
- Номер карты и CVV принимаются Merchant Payment API в открытом виде
- Поиск мерчантов и карт, подверженный SQL-инъекциям
- Отсутствуют идемпотентность, защита от повторов, лимиты платежей и ограничение частоты запросов
- Пробелы в авторизации на уровне объектов при поиске платежей мерчанта
- Раскрытие подробных причин отклонения платежей и отладочных данных
- Предсказуемая генерация кодов авторизации
-
Уязвимости ИИ-поддержки клиентов
- Инъекция в промпт (CWE-77)
- Раскрытие информации через ИИ (CWE-200)
- Нарушенная авторизация в контексте ИИ (CWE-862)
- Раскрытие информации о системе ИИ (CWE-209)
- Недостаточная проверка входных данных для промптов ИИ (CWE-20)
- Прямой доступ к базе данных через манипуляцию ИИ
- Атаки с переопределением роли ИИ
- Уязвимости инъекции в контекст
- Несанкционированный доступ к данным с помощью ИИ
- Раскрытие системных промптов и конфигураций ИИ
-
Уязвимости GraphQL
- Включённая интроспекция схемы на конечной точке аналитики транзакций
- Слабая JWT-аутентификация, унаследованная конечной точкой
/graphql
- SQL-инъекция при построении запросов в GraphQL-резолверах
- Отсутствие контроля глубины / сложности GraphQL
- Раскрытие необработанных ошибок GraphQL
- Раскрытие аналитики транзакций через запросы с правами администратора
Установка и настройка 🚀
Предварительные требования
- Docker и Docker Compose (для запуска в контейнерах)
- PostgreSQL (при локальном запуске)
- Python 3.9 или выше (для локальной установки)
- Git
Вариант 1: Использование Docker (рекомендуется)
Использование Docker Compose (самый простой способ)
- Клонируйте репозиторий:
git clone https://github.com/Commando-X/vuln-bank.git
cd vuln-bank
- Запустите приложение:
docker-compose up -d --build
Приложение будет доступно по адресу http://localhost:5000
Поведение восстановления контейнера
Настройка Docker включает несколько эксплуатационных защитных механизмов, чтобы приложение могло восстановиться без ручного вмешательства через SSH:
web и db используют restart: unless-stopped, поэтому Docker перезапускает их автоматически, если процесс завершается.
db предоставляет проверку состояния (health check), а web ожидает готовности Postgres перед запуском.
web запускает сервер разработки Flask с debug=True (намеренно — сохраняет учебные сценарии, нацеленные на отладчик Werkzeug).
web предоставляет GET /healthz, чтобы контейнер мог сообщать, действительно ли приложение и база данных работоспособны.
Это сохраняет поведение намеренно уязвимого приложения неизменным, делая жизненный цикл контейнера более устойчивым.
Локальный смоук-тест
Вы можете проверить локальную связку окружения без запуска реальных контейнеров:
python3 -m unittest discover -s tests -v
Это проверяет поведение конечной точки /healthz и подтверждает, что start.sh ожидает базу данных, а затем запускает приложение Flask.
Если зависимости приложения Flask не установлены в вашем текущем окружении Python, тест маршрута /healthz пропускается, а смоук-тест стартового скрипта всё равно выполняется.