Что такое Umbryx¶
Note
Umbryx разрабатывается с использованием AI-инструментов. Каждый релиз проходит автоматизированный тестовый прогон и проверку безопасности.
Не приложение для заметок. Платформа, где разведка, операции, доказательства и отчётность живут в одном пространстве — и питают друг друга.
Какую проблему решает¶
Типичный engagement размазан по дюжине инструментов и трём открытым терминалам. Результаты сканов живут в текстовых файлах. Креды — в таблице. Сетевая диаграмма — в отдельной вкладке draw.io. Findings — в Word-документе, который обновляется в конце.
Umbryx собирает всё состояние engagement в одном месте:
- Операции выполняются из платформы, а не просто логируются в неё
- Результаты обновляют состояние — скан создаёт хосты, валидация учётных данных отмечает рёбра доступа, найденные хэши попадают в loot
- Граф отражает то, что вы знаете прямо сейчас, а не статичную диаграмму, нарисованную один раз
- Отчётность собирается из реальных данных, а не из памяти
Текущее состояние¶
Активно развивается — см. Планируемые функции. Недавний фокус:
- Пул workstation (EE) — подготовка атакующих машин заранее через провайдеров Platform Ops (Hetzner, Proxmox, Docker, Kubernetes, чистый SSH), привязка их к пользователям через профильные SSH-ключи с полным журналом grant/revoke
- Platform Ops (EE) — infrastructure-as-catalog: стеки C2+redirector, фишинг-киты и pivot-цепочки развёртываются с автоматическим конвейером после развёртывания (файрвол, discovery, DNS, учётные данные, VPN)
- Постоянная работа по усилению безопасности: контроль ROE/scope, тайминги аутентификации и границы админской авторизации
Основные возможности¶
Оркестрация¶
Запускайте инструменты через платформу. Каждая операция — Job со статусом, выводом и структурированным результатом, который возвращается в состояние проекта.
| Сканы | nmap, nuclei, httpx, ffuf — через атакующий SSH или глобальный connector |
| Массовые операции | Исполнение на динамических коллекциях хостов: все Windows, все с валидным SMB-учётной записью, все в подсети |
| Валидация учётных данных | SMB, WinRM, SSH, LDAP, MSSQL, RDP — результаты создают рёбра доступа и кандидатов в findings |
| Рабочие процессы AD | SPN enum, ASREP, delegation, ADCS, BloodHound collect, domain enum |
| C2-интеграции | Adaptix, Mythic, Sliver — получение сессий/колбэков и учётных данных, исполнение команд из панели действий над хостом или как шаг плейбука |
| Плейбуки | Упорядоченные последовательности операций с live-поллингом шагов и выделенным шагом c2:exec |
| Отмена | Запущенные задания можно убить — останавливается subprocess, а не только запись в БД |
Отслеживание состояния¶
Операции меняют проект. Автоматически.
- nmap-скан → хосты создаются/обновляются с портами и ОС
- Валидация учётных данных → рёбра доступа в графе, статус хоста обновляется
- Вывод задания → NTLM-хэши, Kerberos-тикеты, секреты авто-извлекаются в Loot
- Структурированные результаты заданий → кандидаты в findings, передаваемые аналитику на ревью
Аналитика¶
Всё, что команде нужно знать об engagement, в одном месте.
- Hosts — инвентарь со статусом (
up / access / pwned), ролями, портами, сервисами, тегами, связанными учётными данными; панель деталей со вкладками (Details · Activity · Creds · Path) - Credentials — plaintext, NTLM, Kerberos-тикеты; доменные/локальные; состояние крэка; привязка к хостам
- Findings — критичность, CVE/CVSS, proof, рекомендации, MITRE ID, статус рабочего процесса
- Notes — Markdown с вложениями, фазами, тегами, живой коллаборацией
- Knowledge Base — Markdown-статьи (глобальные или проектные) с полнотекстовым поиском
- Attack Path — упорядоченные шаги эскалации с полями MITRE-техник; привязка шагов к реальным хостам
- Scope — записи CIDR/домен/hostname с шлюзом, флагом entry-point и pivot-хостом «reachable via»
Визуализация¶
Два графа, показывающих разные ракурсы одного и того же состояния engagement.
Network Map — топологический канвас с VLAN-регионами, режимами оверлеев (Threats · Sessions · Access · Roles · Pivots), drag-and-drop-раскладкой, инспектором хостов с таймлайном активности. Рёбра entry uplink показываются оранжевым. Подсети, доступные только через pivot-хост, показывают ⇄ via [host] на регионе.
Attack Graph — интерактивный канвас, где хосты соединены путями по учётным данным, рёбрами доступа, pivot-маршрутами и цепочками повышения привилегий. Бейджи узлов для статуса DA/DC и дистанции достижимости. Боковая панель показывает путь привилегий и pivot-маршруты выбранного хоста.
C2-фреймворки¶
Umbryx интегрируется с тремя операторскими C2-фреймворками. Все три предоставляют одинаковый набор возможностей (синхронизация ✓ живые агенты ✓ исполнение ✓ история задач ✓), поэтому панель действий над хостом и шаг плейбука c2:exec работают одинаково независимо от того, в каком фреймворке живёт сессия.
| Фреймворк | Транспорт | Аутентификация | Примечания |
|---|---|---|---|
| Adaptix | REST поверх HTTPS | username + password (или токен) | Тянет хосты, агентов, учётные данные и каталог BOF; поддерживает исполнение сырой командной строки |
| Mythic | GraphQL (Hasura) | заголовок apitoken или username/password → JWT | Тянет колбэки + учётные данные; мутация createTask для исполнения с опциональным префиксом !command args для указания команды Mythic, отличной от стандартной |
| Sliver | Нативный gRPC через sliver-py |
operator config JSON (вставьте файл, созданный sliver-server operator --save) |
Сессии + биконы; интерактивный interact_session.execute для сессий, асинхронные задачи биконов для биконов |
Сессии появляются в панели действий над хостами, чей IP совпадает с RemoteAddress агента; оттуда оператор может либо выполнить разовую команду, либо поставить в очередь многошаговый плейбук против агента.
Пивоты¶
- Ручное создание пивотов из тулбара Network Map (инструмент, тип, route CIDR, статус)
- Автосбор из chisel / ligolo / Adaptix через SSH-коллектор
- Рёбра pivot-маршрутов: все хосты в route CIDR связываются с pivot-узлом на Attack Graph
via_host_idв scope: пометьте подсеть как доступную только через конкретную машину — Smart Build добавит рёбра маршрутов, а регион покажет pivot-аннотацию
Platform Ops (инфраструктура)¶
Проектируйте, разворачивайте и управляйте атакующей инфраструктурой из каталога вместо ручного сочинения docker-compose-файлов на каждый engagement.
- Templates — предсобранные стеки (C2 + Redirector, C2 + Redirector + DNS, C2 Cluster, Phishing Kit, Pivot Chain) и конструктор с чистого канваса
- Stacks — развёрнутый шаблон становится
InfraStack: сервисы создаются средствами provisioning, затем запускается конвейер автоинтеграции — правила файрвола, discovery сервисов, сшивка nginx/Cloudflare-линков, генерация учётных данных, WireGuard VPN и DNS-записи — каждый шаг отслеживается per-service со статусом - Nodes / Providers — регистрация вычислительных ресурсов, на которые разворачивается стек (Hetzner, Proxmox, Docker-хосты, Kubernetes, чистый SSH)
- DevOps-лог — централизованный, фильтруемый журнал каждой инфраструктурной операции, независимый от отдельного стека
Workstation¶
Атакующие десктопы как управляемый ресурс вместо общего jump-хоста.
- Workstation на проект — поднимите контейнер Kali/Parrot/BlackArch/Ubuntu (или облачную VM), скоупированный на один engagement, из шаблона или кастомного образа
- Пул workstation — подготовьте общий пул машин заранее через тех же инфраструктурных провайдеров, храните SSH public key пользователей в их профиле и выдавайте/отзывайте доступ per-user (добавляет/удаляет помеченную строку в
authorized_keysпо SSH) — каждый grant, revoke и шаг provisioning зеркалируется в таймлайн проекта и журнал аудита - Поддержка hetzner, proxmox, Docker, Kubernetes и зарегистрированных вручную SSH-хостов как нижележащего субстрата
Конвейер доказательств¶
- Loot: файлы, хэши, секреты, конфиги — загрузка/скачивание с авторизацией, привязка к хосту + заданию + учётной записи
- Автоизвлечение из вывода заданий: NTLM-хэши, Kerberos-тикеты, секреты, ссылки на файлы
- sha256 на каждую загрузку; классификация типа артефакта
Отчётность¶
Executive summary собирается из реальных данных проекта: скомпрометированные хосты, крэкнутые учётные данные, критичные findings, таймлайн активности операторов, нарратив пути атаки.
Скриншоты¶
Network Map — топологический канвас с VLAN-регионами и режимами оверлеев¶

Attack Graph — пути привилегий, pivot-маршруты, бейджи узлов DA/DC¶

Hosts — панель со вкладками: Details · Activity · Creds · Path¶

Credentials¶

Findings¶

Notes (Markdown)¶

Loot¶

Knowledge Base¶

Scope — с полями gateway, entry-point и pivot-хоста¶

Attack Path¶

Jobs¶

Report¶

Timeline¶

Scans¶

Playbooks¶

Automations¶

Commands (шпаргалка)¶

Platform Ops — каталог инфраструктуры и стеки¶

Workstations¶

ROE (Rules of Engagement)¶

Checklist¶

Objectives¶

Операционный цикл¶
Каждый слой питает следующий. Данные не вводятся дважды.
Развёртывание¶
Important
Umbryx спроектирован для внутренних доверенных сетей — VPN, air-gapped-лаборатория, jump host. Здесь нет харденинга под публичный интернет (вход ограничен по IP — 5 попыток в минуту, — но WAF и капчи нет). Не выставляйте его напрямую в интернет. Если нужен удалённый доступ — поставьте за VPN или reverse proxy с mTLS.
Быстрая установка (TUI)¶
Интерактивный мастер с text-UI (whiptail, с запасным текстовым режимом, если недоступен) генерирует секреты, пишет .env/.env.ha и поднимает стек за вас — без ручного редактирования. Покрывает оба режима развёртывания:
- All-in-one — один хост, всё в одном
docker compose up. - Multi-node HA — проводит через точную последовательность из HA-развёртывания (монитор pg_auto_failover, создание ролей БД, HAProxy/keepalived VIP, Redis Sentinel) на seed-узле: подключение второго узла и направление слоя приложения на кластерный VIP. Регистрация pg_auto_failover — одноразовое рукопожатие — читайте подтверждения перед продолжением на живом кластере.
Запустите сначала ./install.sh --dry-run, чтобы увидеть точно, что он сделает, ничего не меняя. Ручные шаги ниже по-прежнему здесь — для тех, кто хочет понять или кастомизировать действия инсталлятора.
Предварительные требования¶
- Docker ≥ 24.0 с плагином
compose(docker compose versionдолжен работать) - Linux-хост с минимум 2 GB RAM и 5 GB свободного диска под базу данных + loot-артефакты
- OpenSSL для генерации секретов (
openssl version) - Опционально: отдельная атакующая машина, доступная по SSH, если вы хотите запускать сканы (nmap, nuclei, netexec, donpapi) — платформа не поставляет эти инструменты сама
1. Получите проект¶
Репозиторий Community Edition (Core) публично доступен на GitHub:
Образы Enterprise Edition распространяются отдельно по лицензии — см. установку EE.
2. Сгенерируйте секреты¶
Два значения должны быть заданы перед любым не-одноразовым развёртыванием:
# JWT signing key — sessions are issued and verified with this
openssl rand -hex 32
# Encryption key — Fernet key used to encrypt credentials, sensitive notes, loot text
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
Сохраните оба — вы вставите их в .env на следующем шаге. Потеря
ENCRYPTION_KEY после первого старта делает существующие
зашифрованные данные навсегда нечитаемыми. Создайте резервную копию до перехода в промышленную эксплуатацию.
3. Настройте .env¶
Откройте .env в редакторе и заполните все значения с change_me:
# Database
DB_USER=umbryx
DB_PASSWORD=<a-strong-password>
DB_NAME=umbryx
# Secrets — paste the generated values from step 2
JWT_SECRET=<openssl rand -hex 32 #1>
ENCRYPTION_KEY=<python3 Fernet.generate_key() #2>
# Initial admin account — auto-created on first start if no users exist
ADMIN_USERNAME=admin
ADMIN_PASSWORD=<a-strong-password>
# Host port — change if 3000 conflicts with something else
PORT=3000
# Cookie security — set true ONLY when serving over HTTPS
COOKIE_SECURE=false
Файл .env подхватывается docker compose автоматически. Никогда не
коммитьте его — .gitignore уже исключает его.
4. (Опционально) Настройте пул воркеров¶
Задания из очереди (nmap, nuclei, donpapi) привязаны к SSH — большую часть времени они ждут сетевой I/O, а не CPU. Значения по умолчанию консервативны:
WORKER_POOL_MAX_WORKERS=8 # total parallel jobs across all projects
WORKER_POOL_MAX_PER_PROJECT=3 # max concurrent jobs for one project
Поднимите значения, если ваша атакующая машина выдержит больше параллельных сканов, не упираясь в рейт-лимиты целей.
5. Сборка и запуск¶
Первая загрузка занимает 1–3 минуты (инициализация Postgres, сборка фронта, alembic-миграции). Последующие рестарты — секунды.
6. Проверка¶
# Core services should be Up; db/redis/backend/frontend should report healthy
docker compose ps
# Published health probe through nginx (should return 200)
curl -i http://localhost:${PORT:-3000}/health
# Tail logs in case something failed
docker compose logs backend --tail=30
docker compose logs frontend --tail=10
Откройте http://localhost:${PORT} и войдите с админскими учётными данными из
.env.
7. Первичная настройка внутри приложения¶
- Создайте проект — левый сайдбар → New project
- Настройте атакующую цель (Infra → Connections) — вставьте SSH-хост, порт и учётные данные, которые платформа будет использовать для запуска сканов. Это единственный способ, которым сканы реально выполняются.
- Пригласите членов команды (Admin → Users) — создайте обычные аккаунты
user, затем добавьте их в проекты с проектными ролями — 11 ролей отownerдоauditor - Опционально: добавьте C2-интеграции (Admin → Modules) — Adaptix, Mythic, Sliver
Обновление¶
Alembic-миграции запускаются автоматически при старте бэкенда. Всегда создавайте резервную копию тома с данными PostgreSQL и data/uploads/ перед обновлением через мажорную версию.
Important
При пересборке образа автосгенерированный JWT-секрет сохраняется: он
записывается в /data/.jwt_secret (см. Security overview). Регенерируется он, только
если каталог данных потерян или был недоступен для записи — это завершает сеансы
всех пользователей и ломает API-токены. Задавайте JWT_SECRET явно в .env, чтобы
сеансы не зависели от каталога данных.
Заметки по обновлению¶
Политика версионирования¶
Umbryx использует версионирование по мотивам semver
(MAJOR.MINOR.PATCH) с одним явным послаблением: patch-релизы могут включать Alembic-миграции, если те являются аддитивными (новые
колонки, новые индексы, новые таблицы). Это соответствует реальному
ритму внутреннего red-team-инструмента, где добавление колонок
сопровождает патчи возможностей.
Исключение, которое нужно проговорить: любая миграция, которая удаляет строки, дропает колонки или необратимо трансформирует данные, считается data-breaking-патчем. Такие релизы помечаются ⚠ DATA. Создавайте резервную копию перед обновлением до релиза с меткой ⚠ DATA.
Что означает каждая метка¶
| Метка | Тип миграции | Можно пропустить резервное копирование? |
|---|---|---|
| (нет) | Только аддитивное (новые колонки/индексы, значения по умолчанию) | Рискованно, но обычно восстановимо |
| ⚠ DATA | Удаляет или трансформирует существующие строки | Нет — сначала резервная копия |
Data-breaking-релизы на текущий момент¶
| Версия | Что меняется | Миграция |
|---|---|---|
| v0.4.8 ⚠ DATA | Авто-дедупликация строк creds с идентичными (pid, username, domain, host) — дубликаты удаляются навсегда |
006_data_stability_unique |
Откат¶
Автоматического отката нет. Если миграция упала или дала неожиданные результаты, восстановитесь из резервной копии:
# Stop everything
docker compose down
# Restore DB and uploads from backup
tar -xzf umbryx-backup-YYYYMMDD.tar.gz
# Restart (runs migrations from current state)
docker compose up -d --build
Откат отдельных миграций (продвинутое):
# Identify the target revision
docker compose exec backend alembic history
# Downgrade one step
docker compose exec backend alembic downgrade -1
Примечание: downgrade() в каждой миграции восстанавливает схему
(дропает добавленные колонки), но не восстанавливает удалённые
строки. Для релизов ⚠ DATA даунгрейд требует восстановления из
резервной копии БД.
Устранение неполадок¶
| Симптом | Причина | Решение |
|---|---|---|
502 Bad Gateway от nginx после пересборки бэкенда |
nginx закэшировал старый IP контейнера бэкенда | docker compose restart nginx |
auth: 401 на каждый запрос |
JWT_SECRET изменился между рестартами |
Задайте JWT_SECRET явно в .env, разверните заново |
Ошибки Cannot read encrypted value |
ENCRYPTION_KEY изменился после записи данных |
Восстановитесь из резервной копии; зашифрованные колонки не восстановить без оригинального ключа |
| Фронт грузится, но данных нет | WebSocket блокируется промежуточным прокси | Добавьте proxy_http_version 1.1 + заголовки Upgrade/Connection на вашем reverse proxy |
| Сканы в очереди навсегда | Не настроена цель attacker_ssh |
Infra → Connections → добавить SSH executor-цель |
Ошибка alembic-миграции при старте |
Схема БД новее кода (даунгрейд) | Восстановите резервную копию БД или выполните alembic stamp <revision> вручную |
Бэкенд падает с Permission denied при записи в /data |
Автофикс владельца из entrypoint не поможет, если режим ./data (не только владелец) блокирует запись — например, он на noexec/read-only-маунте или был создан chmod 000 |
Проверьте сам хостовый маунт: stat ./data; это должна быть обычная записываемая директория. Несовпадение владельца обрабатывается автоматически — это проблема уровня маунта, а не UID |
Переменные окружения¶
Полный справочник. У всех разумные значения по умолчанию; только секреты и пароль админа обязаны быть заданы до промышленной эксплуатации.
| Переменная | По умолчанию | Обязательна? | Описание |
|---|---|---|---|
JWT_SECRET |
auto-generated | Да для промышленной эксплуатации | Ключ подписи JWT. Генерируйте через openssl rand -hex 32. Если не задан, бэкенд авто-генерирует и персистит в /data/.jwt_secret — ок для локальной разработки, не для промышленной эксплуатации. |
ENCRYPTION_KEY |
генерируется в /data/secret.key, если не задан в dev |
Да для промышленной эксплуатации | Fernet-ключ для шифрования учётных данных, чувствительных заметок, значений loot и шифрованных loot-файлов. Генерируйте через python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())". Храните резервную копию — потеря делает зашифрованные данные навсегда нечитаемыми. |
DB_USER |
umbryx |
Нет | Пользователь PostgreSQL |
DB_PASSWORD |
change_me_strong_password |
Да | Пароль PostgreSQL — смените перед любой не-одноразовой установкой |
DB_NAME |
umbryx |
Нет | Имя базы PostgreSQL |
ADMIN_USERNAME |
admin |
Нет | Имя изначального админа (используется только при первой загрузке, когда пользователей нет) |
ADMIN_PASSWORD |
auto-generated | Да для промышленной эксплуатации | Пароль изначального админа. Если не задан, бэкенд печатает сгенерированный в свой лог при первой загрузке. |
PORT |
3000 |
Нет | Хостовый порт, публикуемый nginx |
COOKIE_SECURE |
false |
Нет | Задайте true при работе по HTTPS, чтобы сессионные куки получали флаг Secure |
CORS_ORIGINS |
(пусто) | Нет | Разрешённые origins через запятую. Пусто = только same-origin |
WEBHOOK_HMAC_SECRET |
(пусто) | Нет | Если задан, каждый webhook-запрос обязан включать X-Hub-Signature-256: sha256=<hmac> |
WORKER_POOL_MAX_WORKERS |
8 |
Нет | Общее число параллельных слотов заданий по всем проектам |
WORKER_POOL_MAX_PER_PROJECT |
3 |
Нет | Максимум одновременных заданий для одного проекта (не даёт одному проекту морить остальных голодом) |
PUBLIC_BASE_URL |
выводится из запроса | Рекомендуется для промышленной эксплуатации | Используется для построения OIDC/SSO redirect_uri на стороне сервера (например, https://umbryx.example.com) — см. ACCESS_CONTROL.md. Запасной вариант — host самого входящего запроса, что нормально за хорошо настроенным reverse proxy, но не должно оставаться на спуфяемом заголовке Host при промышленной эксплуатации. |
DB_HOST / DB_PORT / DB_SSLMODE |
db / 5432 / prefer |
Нет | Направьте приложение на внешний Postgres вместо встроенного сервиса db — например, VIP кластера multi-node HA. См. «Multi-node HA» ниже. |
REDIS_SENTINEL_HOSTS / REDIS_SENTINEL_MASTER / REDIS_SENTINEL_PASSWORD |
(пусто) | Нет | Направьте Redis-доступ на кворум Sentinel вместо одиночного экземпляра Redis, заданного REDIS_URL — приоритетнее REDIS_URL, когда задано. |
Multi-node HA¶
Этот docker-compose.yml — одноузловой: одна db, один redis, и
хватит. Для автоматического failover на 2+ хостах (Postgres через
pg_auto_failover, Redis через Sentinel, плавающий VIP, без ручного
вмешательства при потере узла) см. docker-compose.ha.yml и
HA-развёртывание — отдельный
compose-файл для инфраструктурного слоя, запускаемый рядом с этим.
Проверено вживую: убили первичный Postgres-узел под реальным
трафиком — ноль зависших запросов, ~41 с до полного автоматического
восстановления, все данные (включая зашифрованные секреты учётных данных)
целы на любом из узлов после этого.
Архитектура¶
nginx ──► frontend (React + Vite, static build)
──► backend (FastAPI + SQLAlchemy + asyncio worker pool)
└──► PostgreSQL 16
- Аутентификация: JWT bearer-токены плюс проектный RBAC (11 проектных ролей от
ownerдоauditor) и глобальные админ-контролы - Realtime: WebSocket на проект — presence и live-синхронизация сущностей
- Воркеры: по умолчанию ограниченный внутренний async-пул воркеров, опционально Redis/
arq-бэкенд для исполнения через очередь, настоящая отмена через cancellation token + kill subprocess - Хранилище: загруженные файлы в
data/uploads/, данные PostgreSQL в Docker-волюмеpgdata. Контейнер бэкенда стартует под root, чинит владельца/data(и, в продовом compose-файле, его отдельные волюмыuploads/plugins) под app-пользователя, затем дропает привилегии черезsetprivперед запуском приложения — см.backend/scripts/docker-entrypoint.sh. Это выполняется на каждом старте, но реальноchownделает только при неверном владельце, так что волюм с корректным владельцем обходится одним вызовомstat, а не обходом содержимого. Ни ручногоdocker exec ... chownна первом старте, ни после рестарта не требуется. - Исполнение: атакующий SSH-connector или глобальная цель; SSH-команды запускаются через
Popenс потоком-наблюдателем отмены
Безопасность¶
- Смените
JWT_SECRETиDB_PASSWORDперед любым не-локальным развёртыванием - Спроектировано для внутренних доверенных сетей — публичный интернет не предполагается
- Все скачивания файлов требуют валидный auth-токен (
?token=или заголовокAuthorization) - Креды шифруются at rest
- Конфиденциальное содержимое заметок шифруется at rest, когда заметка несёт теги вроде
confidential,secret,sensitive,opsecилиrestricted - Чувствительные текстовые значения loot шифруются at rest для не-файловых артефактов
- События read-аудита записываются, когда пользователи просматривают секреты учётных данных, конфиденциальные заметки, чувствительный loot или скачивают защищённые файлы