Обоснование надёжности
На этой странице доказывается, что DumbMonit отвечает своим требованиям безопасности: перечислены угрозы, границы, на которых меняется доверие, причины, по которым устройство системы ограничивает последствия ошибки, способы противодействия каждому распространённому классу уязвимостей и подтверждения для каждого утверждения. Она дополняет модель безопасности, где те же меры перечислены короче. Чтобы сообщить об уязвимости, следуйте политике безопасности.
Пути к файлам ниже указаны относительно корня репозитория.
Требования безопасности
Заголовок раздела «Требования безопасности»- Читать или изменять конфигурацию, оповещения и измерения может только аутентифицированный пользователь, чья роль это разрешает.
- Учётные данные, которые DumbMonit хранит для ваших мониторов, нельзя прочитать ни из файла базы данных, ни из резервной копии без парольной фразы, ни через API.
- Передавать измерения может только машина с действительным токеном, а утёкший токен можно отозвать отдельно.
- DumbMonit нельзя превратить в средство доступа к сервисам, к которым доступа быть не должно, в частности к собственному дочернему процессу VictoriaMetrics без аутентификации.
- Страница, отданная браузеру, не может выполнить скрипт, которого она с собой не поставляла, а сторонний сайт не может заставить вошедший в систему браузер что-либо изменить.
Модель угроз
Заголовок раздела «Модель угроз»| Злоумышленник | Возможности | В рамках модели |
|---|---|---|
| Анонимный сетевой клиент | Достигает HTTP-порта | Да |
| Вошедший пользователь с низкой ролью | Действительный сеанс или токен API только для чтения | Да (повышение привилегий) |
| Вредоносная веб-страница | Работает в браузере администратора | Да (CSRF, XSS, clickjacking) |
| Скомпрометированный или вредоносный отслеживаемый монитор | Отвечает на опросы враждебным содержимым | Да (парсеры, перенаправления) |
| Вредоносный или украденный агент | Владеет одним токеном агента | Да (область действия одного токена) |
| Администратор, вводящий враждебный URL | Настраивает вебхук или адрес монитора | Да, для собственных адресов сервера |
Тот, кто контролирует хост, том /data или среду выполнения контейнеров | Полный контроль | Нет: вне модели, как и в политике безопасности |
| Уязвимости внутри VictoriaMetrics или отслеживаемых мониторов | Сторонний код | Нет: сообщайте разработчикам upstream |
Границы доверия
Заголовок раздела «Границы доверия»| Граница | Что её пересекает | Как защищена | Подтверждения |
|---|---|---|---|
Браузер — /api/* | Сеансовый cookie или токен API, JSON | Один слой аутентификации, три роли, заголовок CSRF для записи с аутентификацией по cookie | crates/server/src/auth/middleware.rs; тесты auth_api.rs, operator_role_api.rs, api_open_security_api.rs, cors_policy_api.rs |
| Браузер — отдаваемые страницы | HTML, скрипты, стили | Content Security Policy с nonce для каждого ответа, nosniff, Referrer-Policy: same-origin, X-Frame-Options: DENY | crates/server/src/api/mod.rs (слой заголовков безопасности) |
| Провайдер идентификации — сервер | Перенаправление OpenID Connect и ID-токен | State, nonce и PKCE (S256); привязка локальной учётной записи выполняется явно | crates/server/src/auth/oidc/; тест oidc_api.rs |
Агент — /api/ingest | Измерения, результаты команд | Токен каждого агента, хранится как хеш SHA-256 (префикс dmon_) | crates/server/src/api/ingest.rs, crates/server/src/collectors/agent/token.rs; тест agent_binding_api.rs |
| Агент-ретранслятор — сервер | Результаты опросов из другой сети | Та же проверка токена агента (agent_commands::authenticate) | crates/server/src/api/relay.rs; тест relay_api.rs |
| Сервер — отслеживаемые мониторы | Запросы опроса, враждебные ответы | Перенаправления только в пределах того же хоста, ограниченное число перенаправлений, парсеры ответов с модульными тестами, проверка сертификатов включена по умолчанию | crates/collectors/src/http.rs (same_host_redirects) |
| Сервер — каналы уведомлений | Запросы вебхуков и SMTP | Та же политика перенаправлений плюс защита, отклоняющая собственные адреса сервера; проверка выполняется перед отправкой, при каждом перенаправлении и при разрешении DNS | crates/server/src/notify/guard.rs; тест notify_guard_api.rs |
| Сервер — VictoriaMetrics | Записи и запросы на чтение | Встроенный дочерний процесс по умолчанию слушает 127.0.0.1:8428; Prometheus-совместимый прокси пропускает только маршруты чтения (query, query_range, series, labels) | crates/server/src/config.rs (DUMBMONIT_VM_LISTEN), crates/server/src/api/prometheus.rs (readable_segments) |
| Сервер — SQLite | Конфигурация и состояние | Привязанные параметры через sqlx | crates/server/src/db/ |
Сервер — /data | База данных, секретный ключ | Секреты шифруются AES-256-GCM; пользователь контейнера владеет только /data | crates/server/src/crypto.rs, Dockerfile |
Аргументация безопасного проектирования
Заголовок раздела «Аргументация безопасного проектирования»Аргументация следует принципам проектирования Зальцера и Шрёдера.
- Экономичность механизма. Один бинарный файл, один файл SQLite, один
дочерний процесс на loopback, один вход для всех клиентов (
/api/*). - Безопасные значения по умолчанию. На свежем экземпляре каждый маршрут под
защитой аутентификации отвечает
401; отвечают только health, статус аутентификации, setup и login, поэтому никто не может подготовить экземпляр раньше его владельца (auth/middleware.rs, тестapi_open_security_api.rs). VictoriaMetrics слушает loopback, пока оператор не изменит это. Сертификаты TLS наблюдаемых сервисов проверяются, если оператор не задалinsecure_tls(crates/collectors/src/http.rs). - Полное посредничество. Слой аутентификации работает на каждом маршруте API, а не оставляет проверку каждому обработчику.
- Открытое проектирование. Код, описание API
(
crates/server/src/api/openapi.yaml) и эта страница общедоступны. Безопасность не зависит от секретности устройства системы. - Разделение привилегий. Сеансы, токены API и токены агентов — разные
учётные данные. Токены API имеют область
readилиwrite(auth/token.rs), а у пользователей роль наблюдателя, оператора или администратора. - Наименьшие привилегии. Образ работает с UID 65532 (
Dockerfile). Запущенный от root (user: "0:0", для bind mount), сервер лишь передаёт каталог данных этому пользователю, не переходя по ссылкам, затем навсегда отказывается от root и проверяет, что вернуть его нельзя, прежде чем открывать что-либо ещё (privileges.rs). Файл Compose оставляет только четыре capabilities, нужные этому шагу, делает корневую файловую систему доступной только для чтения и задаётno-new- privileges(docker-compose.yml). - Наименьший общий механизм. Агенты аутентифицируются собственным токеном, поэтому отзыв одной машины не затрагивает ни пользователей, ни других агентов.
- Психологическая приемлемость. Безопасное поведение включено по умолчанию и
не требует лишних шагов: cookie имеет флаги
HttpOnlyиSameSite=Lax, заголовок CSRF добавляется веб-клиентом, секреты в интерфейсе доступны только для записи. - Эшелонированная защита. Шифрование при хранении поверх контроля доступа;
заголовок CSRF поверх
SameSite; ограничение частоты входа поверх хеширования Argon2; политика перенаправлений поверх защиты от собственных адресов.
Криптография
Заголовок раздела «Криптография»- Пароли: Argon2 (
auth/password.rs). Секреты сеансов и токенов API хранятся в виде хешей SHA-256 от случайных значений (auth/session.rs,auth/token.rs). - Секреты при хранении: AES-256-GCM со свежим nonce при каждом шифровании
(
crypto.rs). Ключ получается с помощью Argon2id изDUMBMONIT_SECRETили сгенерированного файла ключа с постоянной солью; секрет короче 16 символов отклоняется, а контрольное значение при запуске выявляет неверный ключ. - Резервные копии: ключ выводится из парольной фразы оператора с помощью Argon2id,
параметры хранятся в самом архиве, поэтому алгоритм можно менять, не ломая
старые архивы (
backup/bundle.rs). - Второй фактор: TOTP с хешированными одноразовыми резервными кодами
(
auth/totp.rs). - OpenID Connect: state, nonce и PKCE
S256(auth/oidc/pkce.rs). - Все примитивы взяты из поддерживаемых библиотек (
aes-gcm,argon2,sha2); ничего самодельного. Встроенный обработчик принимает только HTTPS (обычный HTTP-запрос получает перенаправление), а cookie получает флагSecure(auth/cookie.rs).
Меры противодействия распространённым уязвимостям
Заголовок раздела «Меры противодействия распространённым уязвимостям»| Уязвимость (OWASP Top 10, CWE) | Мера противодействия | Подтверждения |
|---|---|---|
| Нарушенный контроль доступа, CWE-862, CWE-285 | Слой аутентификации, роли, области токенов | operator_role_api.rs, api_tokens_api.rs, api_open_security_api.rs |
| Криптографические сбои, CWE-327, CWE-312 | AES-256-GCM при хранении, Argon2, API не возвращает секреты | модульные тесты crypto.rs; has_secret / credential_kind вместо секрета |
| SQL-инъекция, CWE-89 | Привязанные параметры через sqlx | crates/server/src/db/ |
| Межсайтовый скриптинг, CWE-79 | Svelte экранирует вывод; CSP с default-src 'none', скрипты только из 'self' и с nonce; base-uri 'none' | api/mod.rs |
| Межсайтовая подделка запросов, CWE-352 | Запись через cookie требует X-Requested-With: DumbMonit или метаданные fetch того же источника; CORS не разрешает этот заголовок никому; SameSite=Lax | auth/middleware.rs, auth/cors.rs; тест cors_policy_api.rs |
| Clickjacking, CWE-1021 | X-Frame-Options: DENY и frame-ancestors 'none', кроме публичных страниц статуса, которые включены явно и предназначены для встраивания | api/mod.rs |
| Подделка запросов со стороны сервера, CWE-918 | Перенаправления только в пределах того же хоста; защита уведомлений отклоняет собственные адреса сервера и VictoriaMetrics, в том числе после разрешения DNS (rebinding). Loopback и частные диапазоны намеренно остаются доступными, потому что там живут сервисы домашней лаборатории | notify/guard.rs; тест notify_guard_api.rs |
| Сбои аутентификации, CWE-307, CWE-287 | Ограничение частоты входа с растущей задержкой по адресу и по учётной записи, необязательный TOTP, OIDC с PKCE, сброс второго фактора администратором | auth/rate_limit.rs, auth/totp.rs, auth/oidc/ |
| Небезопасная десериализация, исчерпание ресурсов, CWE-400 | Типизированный JSON через serde, тела запросов ограничены 16 МиБ, число перенаправлений ограничено | api/mod.rs, collectors/src/http.rs |
| Безопасность памяти, CWE-787, CWE-416 | Rust; unsafe встречается только в коде счётчиков производительности агента для Windows (crates/agent/src/collect/perf_counters.rs) | поиск unsafe через grep |
| Уязвимые компоненты, CWE-1104 | cargo deny (лицензии, запреты, рекомендации); Dependabot; сканирование опубликованных образов Trivy; actions закреплены по коммиту; сборки с --locked | .github/workflows/ci.yml, security.yml, .github/dependabot.yml, deny.toml |
| Целостность программ и данных, CWE-494 | Установщики агента проверяют SHA-256 загруженного бинарного файла | crates/agent/install/install.sh, install.ps1 |
| Сбои журналирования и мониторинга, CWE-778 | Журнал безопасности входов и важных изменений | auth/audit.rs; тест security_audit_api.rs |
Известные остаточные риски перечислены в модели безопасности (самоподписанный сертификат по умолчанию,
незашифрованные параметры мониторов, встроенная VictoriaMetrics
без аутентификации). CSP допускает встроенные стили (style-src 'unsafe-inline'),
что ослабляет защиту от внедрения стилей, но не от выполнения скриптов.
Существует одна принятая рекомендация, RUSTSEC-2023-0071, которая игнорируется в
deny.toml с указанием причины: крейт rsa проверяет подписи RS256 открытым
ключом провайдера и никогда не использует закрытый ключ.
Подтверждения
Заголовок раздела «Подтверждения»- Непрерывная интеграция (
.github/workflows/ci.yml):cargo fmt --check,clippy -D warnings, полный набор тестов Rust,cargo deny check licenses bansиcargo deny check advisories, проверка типов веб-части, веб-тесты и сборка, а также сборка образа Docker при каждом push и pull request. - Сканирование по расписанию (
.github/workflows/security.yml): Trivy для опубликованных образов сервера и агента и OpenSSF Scorecard — еженедельно и после каждой публикации:edge. Результаты отображаются на вкладке Security репозитория, куда также поступают отчёты GitHub code scanning (CodeQL). - Тесты: тесты API, аутентификации, ролей, CORS, OIDC, защиты и аудита в
crates/server/tests/, модульные тесты рядом с кодом и веб-тесты вweb/tests/. Покрытие строк Rust, измеренное с помощьюcargo-llvm-cov, составляет 91 %. - Политика регрессий: исправление сопровождается тестом, который без него
не проходит (см. политику тестирования в
CONTRIBUTING.md). - Публичная запись: исправления безопасности публикуются как advisories и перечисляются в примечаниях к релизу.