Образовательная платформа для обучения уязвимостям веб-приложений через интерактивные задачи по программированию. Пользователи проходят уровни, используя подготовленные уязвимости: от простых HTTP-запросов до SQL-инъекций.
Сервис состоит из двух основных компонентов:
- Backend: сервис на Go, управляющий логикой игры, аутентификацией, прогрессом пользователя и выполнением кода в изолированных контейнерах
- Frontend: UI на React + Vite для решения задач
На каждом уровне пользователь встречает новую уязвимость, которую должен понять и использовать для прохождения.
Пользователь (браузер)
↓
React Frontend (8080)
↓
HTTP API (роутер go-chi)
├── Аутентификация: JWT через gRPC сервис
├── Управление пользователем: профиль, прогресс
├── Уровни: описание, подсказки, обработка вводов
├── Подсказки: контекстная помощь
└── Выполнение кода: обёртывание и отправка в очередь
↓
Очередь Code Runner (канал в памяти)
↓
Container Manager (оркестрация Docker)
├── Запуск изолированных окружений Python
├── Захват вывода
└── Применение ограничений ресурсов
↓
SQLite база данных
├── Пользователи (авторизация, прогресс)
├── Уровни (задачи)
├── Подсказки (по уровням)
└── Связь пользователь-уровень (статус завершения)
Также запускаются два дополнительных сервера:
- gRPC сервис аутентификации (127.0.0.1:8085): генерирует и валидирует JWT токены. Использует Google OAuth.
- Curl Server (порт 9086): уязвимый HTTP сервер, который пользователи используют для curl запросах. Демонстрирует SQL-инъекции, command injection.
- Go 1.23:
- go-chi: HTTP роутер и middleware
- SQLite:
- Docker SDK:
- gRPC + Protocol Buffers:
- JWT (golang-jwt):
- Google OAuth 2.0:
- slog:
- React + Vite:
- TypeScript:
Уровни хранятся в SQLite и представляют задачи по безопасности:
type Level struct {
Id int
Name string
Description string // Описание задачи
ExpectedInput string // Что должен ввести пользователь
StartInput string // Шаблон кода
}Каждый уровень посвящён классу уязвимостей:
- Уровни 1–2: HTTP запросы через curl, раскрытие информации
- Уровень 3: подбор слабых учётных данных
- Уровни 4–5: command injection (доступ к файловой системе)
- Уровни 6–7: SQL-инъекции (UNION SELECT)
- Уровень 8: ломающие запросы (DROP TABLE)
- Уровни 9–10: переполнение стека
type UserLevel struct {
UserId int
LevelId int
IsCompleted bool // Задача решена
LastInput string // Последняя отправка
AttemptResponse string // Ответ сервера
Attempts int // Количество попыток
}Когда пользователь отправляет код на уровнях 9–10:
- Код оборачивается контекстом уровня (например, ограничения памяти для тестов ОПМ)
- Задача ставится в очередь code runner
- Container manager берёт из очереди и выполняет в изолированном Docker контейнере
- Вывод захватывается и сравнивается с ожидаемым результатом
- Ответ содержит статус прохождения/непрохождения
func (r *CodeRunner) NewTask(ctx context.Context, ...) func(context.Context) (domain.Response, error) {
// Оборачивает код, ставит задачу, ждёт результата с таймаутом 10 секунд
}Каждый уровень может иметь несколько подсказок.
- JWT токены генерируются сервисом gRPC
- TTL токена настраивается (по умолчанию 1 час)
- Secret хранится в переменной окружения
- Middleware валидирует подпись и извлекает email пользователя в контекст
Миграции запускаются при старте через cfg.MigrationPath (по умолчанию ./internal/db/init.sql). Схема включает:
users: Email, хеш пароля, интеграция OAuth, статистика прогрессаlevels: определение задачhints: подсказки по уровнямuser_levels: прогресс пользователя на каждом уровнеapps: OAuth приложения
Конфигурация загружается из ./internal/cfg/cfg.yaml с возможностью переопределения переменными окружения:
http_server:
storage_path: "./internal/db/storage.db"
address: "0.0.0.0:8080"
orchestrator_config:
image_name: "code-runner" # Docker образ для выполнения кода
target_dir: "/home" # Где выполняется код
grpc_config:
address: "127.0.0.1:8085" # Сервис аутентификации
token_ttl: 1hТребуемые переменные окружения:
JWT_SECRET: secret для подписи JWT токеновGOOGLE_CLIENT_ID: Google OAuth client IDGOOGLE_CLIENT_SECRET: Google OAuth secret
Container manager:
- Берёт образ
code-runner(предоставляется пользователем) - Монтирует временную директорию с кодом
- Запускает Python с файлом решения
- Захватывает stdout/stderr и код выхода
- Очищает контейнеры после выполнения
Ограничения ресурсов применяются per-level. На уровне 10 память ограничивается до 100МБ для тестирования ОПМ.
Порядок обработки запроса:
- CORS:
- RequestID: уникальный ID для трассировки
- Logger: стандартное HTTP логирование
- Recoverer: ловит паники
- Custom Auth: валидирует JWT и извлекает контекст пользователя
# Убедитесь, что конфиг существует
# backend/internal/cfg/cfg.yaml
# Установите переменные окружения
export JWT_SECRET=ваш-secret-ключ
export GOOGLE_CLIENT_ID=...
export GOOGLE_CLIENT_SECRET=...
# Из директории backend
go run main.go
# или
make runBackend запускает:
- HTTP сервер на порту 8080 (настраивается)
- gRPC сервис аутентификации на 127.0.0.1:8085
- Curl server на 9086
Запустите скрипт заполнения базы:
bash backend/internal/db/fill_db_script.shСоздаёт SQLite БД со всеми уровнями, подсказками и таблицами пользователей.
cd frontend
npm install
npm run devFrontend запускается на http://localhost:5173 (по умолчанию Vite).
docker build -f backend/Dockerfile -t code-runner .make testPOST /auth/google- Google OAuth входPOST /auth/google/callback- OAuth callback
GET /user?email=...- Профиль пользователя (email, попытки, пройденные уровни)
GET /levels- Список всех уровнейGET /levels/{id}- Один уровень с подсказками
POST /submit- Отправить решение (body:{levelId, input})
GET /hints?levelId=...- Получить подсказки уровня
Ключевые директории:
-
backend/- Go бэкендmain.go- точка входа сервераinternal/api/- HTTP handlers (auth, levels, submit, hints, user)internal/db/- слой хранения SQLiteinternal/cfg/- загрузка конфигурацииinternal/codeRunner/- обёртывание выполнения кодаinternal/containerMgr/- оркестрация Dockerauth/- gRPC сервис аутентификацииcurlServer/- уязвимый HTTP сервер для curl задач
-
frontend/- React + Vite фронтенд -
.github/- конфигурация GitHub