Files
ayurishchevandClaude Opus 5.5 744a025960 Задачи 032-033: ролевая модель с привязкой к организации, исправления по ревью
Пентест (docs/reviews/2026-09-27-pentest.md) и план 031 (Swagger, TLS) — план, не реализован.
032 Роль superadmin (без организации) и привязка admin/viewer к одной организации:
    users.organization_id + CHECK, audit_log.organization_id (миграции 0010-0012);
    require_org/scope_org во всех чтениях и записях, журнал и «Обзор» в границах
    организации; пользователи, организации, типы устройств, настройки журнала — только superadmin.
033 Исправление находок ревью 032 (docs/reviews/2026-09-27-changes-032-review.md,
    docs/reviews/2026-09-27-codebase-review.md):
    - FK audit_log.organization_id ON DELETE SET NULL (миграция 0013) — удаление организаций;
    - проверка организации в предпросмотре подсети;
    - инвариант «роль — организация» по итоговому состоянию (повышение снимает организацию,
      понижение требует её), 422/404 вместо обезличенных 409;
    - одинаковый 404 для чужих и несуществующих объектов (VRF, устройство, parent_id, оператор);
    - отказы удаления в журнале организации, счётчики типов в пределах организации;
    - UI: живое поле «Организация» в диалоге пользователя, бейдж superadmin; род в текстах 404.
README актуализирован под ролевую модель.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 11:26:57 +03:00

5.2 KiB

Пентест приложения (чёрный ящик) — 2026-09-27

Цель: 192.168.5.9:8088 (стенд ipam_control_006). Условия игры: известны только адрес и порт. Задача — по уровням: (1) доступ к приложению с записью, (2) root в контейнере, (3) побег из контейнера. Метод: внешняя разведка и проверка авторизации по чёрному ящику. Часть наступательных векторов (подделка JWT, SQL-инъекция, спуфинг X-Forwarded-For) заблокирована предохранителем среды как «ослабление защиты» и по факту не исполнялась; их оценка ниже — по знанию кода, без эксплуатации.

Результат по уровням

Уровень 1 — доступ с записью: НЕ получен. Уровни 2 и 3 — недостижимы: без плацдарма на уровне 1 разговора о root и побеге нет. Приложение не исполняет пользовательский ввод, не читает файлы по имени от клиента, не ходит по URL из запросов — готового foothold-вектора (RCE, upload, SSRF) нет.

Что проверено на живом стенде

Вектор Результат
POST /organizations без токена 401
GET /users без токена 401
Типовые пароли admin (admin, admin123, password, 123456, changeme, change-me, ipam, ipam123, Admin123, root) 401, после 5-й попытки — 429 (лимит «логин+IP», изменение 026)
Заголовки ответа / CSP, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: no-referrer; сервер только uvicorn
/healthz {"status":"ok"}
/docs, /openapi.json Открыты анонимно — полная карта из 28 эндпоинтов выдаётся без авторизации

Оценка заблокированных векторов (по коду, без эксплуатации)

  • Подделка JWT — не проходит: секрет случайный (64 символа из scripts/gen_env.py), старт с заглушкой/коротким ключом запрещён (изменение 017); alg=none и пустой HMAC-ключ отклоняются PyJWT.
  • SQL-инъекция — исключена: запросы параметризованы (SQLAlchemy), поиск LIKE экранирует % и _ (изменение 023).
  • Спуфинг X-Forwarded-For для смены IP и обхода лимита — не работает: заголовок учитывается только от TRUSTED_PROXIES, список пуст (адрес берётся из сокета).
  • Брутфорс пароля — argon2 + три уровня лимитов (5 логин+IP, 20 IP, 50 логин со всех IP кроме известных).
  • Эскалация в контейнере — даже с foothold-ом процесс работает от uid 10001, не root (изменение 022): «root в контейнере» требовал бы отдельной local-priv-esc уязвимости базового образа.

Находки (для защиты)

# Серьёзность Суть
1 Низкая–средняя Swagger /docs, /redoc, /openapi.json открыты анонимно — карта всей поверхности API выдаётся без авторизации
2 Низкая–средняя Приложение слушает 0.0.0.0:8088 по HTTP: токены и пароли идут по LAN открытым текстом; reverse-proxy + APP_BIND=127.0.0.1 из плана 022 на стенде не задействованы
3 Низкая (заметка) Логин admin документирован как дефолт; лимит «логин со всех IP кроме известных» (50) допускает распределённый брутфорс с многих IP при слабом пароле/утечке хеша

Находки 1 и 2 берутся в работу (план — отдельный документ). Находка 3 — организационная (смена дефолтного логина/пароля при развёртывании), отдельной доработкой не оформляется.

Вывод

Приложение по чёрному ящику устойчиво: авторизация, лимиты входа, экранирование, заголовки и непривилегированный контейнер держат периметр. Реальные улучшения — сузить раскрытие API (Swagger) и включить TLS/loopback-привязку в проде.