Телеметрия без раскрытия данных и контрольная плоскость
Здесь определяется, что разрешено пересекать границу между рабочей станцией и контрольной плоскостью.
Модель событий
Каждое решение о применении правил порождает событие безопасности:
версию схемы, случайный идентификатор события, идентификаторы организации, рабочей станции и агента,
идентификатор и отпечаток снимка политики, который привёл к решению, уровень серьёзности (по умолчанию
medium, если не указан), само решение, код причины и поверхность, на которой это произошло.
Это одна и та же схема события — независимо от того, предназначено ли оно только для
локальной очереди или в конечном счёте для контрольной плоскости.
Чувствительные данные удаляются при формировании события.
Когда механизм обнаружения сообщает о находке, событие содержит её тип, имя механизма обнаружения и
замещающую строку — само совпавшее значение заменяется буквальной строкой "redacted" ещё до
того, как объект события появляется в памяти, в том числе в локальном журнале на диске.
Это заметно более сильное свойство, чем «мы редактируем перед отправкой» — не существует
момента ни в памяти, ни на диске, когда сформированное событие несло бы реальное совпавшее
секретное значение.
Что именно удаляет очистка перед синхронизацией
Отдельный, дополнительный проход очистки выполняется непосредственно перед постановкой события в очередь на передачу в контрольную плоскость:
| Поле | Безопасная для синхронизации замена |
|---|---|
command |
command_hash (SHA-256) + command_length |
| Рабочий каталог | Хешируется + подсчитывается |
| Аргументы | Хешируется + подсчитывается |
resource_path, executable_path, parent_chain |
Хешируется + подсчитывается |
| Содержимое буфера обмена | Полностью отбрасывается — даже не хешируется |
Очищенное событие само указывает evidence_redacted: true, чтобы потребитель мог
отличить ситуацию «в этом событии нет доказательств, потому что ни одно не было
релевантным» от ситуации «доказательства этого события были намеренно удалены».
Механика локальной очереди
События ставятся в локальную очередь в формате JSONL, в каталоге с правами доступа 0700 и файлами с правами 0600. Некорректно сформированная строка пропускается. Подтверждение успешно синхронизированных событий происходит по порядковому номеру, через отдельный файл с отметкой о последней обработанной записи, поэтому повторное подтверждение идемпотентно, а параллельные добавления во время синхронизации безопасны. Записи превышающего размера или не поддающиеся декодированию пропускаются со счётчиком. Сама очередь ограничена по размеру; при заполнении самые старые записи отбрасываются, потеря подсчитывается, и специально генерируется событие безопасности, чтобы сделать эту потерю видимой. Сигналы состояния сообщают глубину очереди, накопленные счётчики отброшенных/пропущенных записей и время последней синхронизации. Сигнал состояния, в котором данные о состоянии очереди отсутствуют, оставляет предыдущее переданное значение в силе.
Эшелонированная защита на каждой границе
Очистка намеренно повторно применяется независимо на каждой границе — на агенте перед отправкой, снова при приёме контрольной плоскостью и снова на каждом пути экспорта (представления API событий, отправка в SIEM, экспорт аудита).
%%{init: {"theme": "base", "themeVariables": {"fontFamily": "-apple-system, Segoe UI, Helvetica, Arial, sans-serif", "primaryColor": "#eef2f7", "primaryTextColor": "#0b0b0b", "primaryBorderColor": "#5b6b7c", "lineColor": "#5b6b7c", "secondaryColor": "#eef4ff", "tertiaryColor": "#f4f3f0", "clusterBkg": "#f9f9f7", "clusterBorder": "#c3c2b7", "edgeLabelBackground": "#fcfcfb", "actorBkg": "#eef2f7", "actorBorder": "#5b6b7c", "actorTextColor": "#0b0b0b", "actorLineColor": "#5b6b7c", "signalColor": "#52514e", "signalTextColor": "#0b0b0b", "labelBoxBkgColor": "#eef4ff", "labelBoxBorderColor": "#5b6b7c", "labelTextColor": "#0b0b0b", "loopTextColor": "#0b0b0b", "noteBkgColor": "#fdf3d9", "noteBorderColor": "#c98500", "noteTextColor": "#3d2f00", "activationBorderColor": "#5b6b7c", "activationBkgColor": "#eef4ff", "sequenceNumberColor": "#ffffff"}}}%%
flowchart LR
Event["Событие сформировано\n(чувствительные данные уже удалены)"] --> Sync["Очистка для синхронизации\n(хеширование + удаление запрещённых полей)"]
Sync --> Queue["Локальная очередь JSONL\n(каталог 0700 / файлы 0600)"]
Queue --> Send["Отправка в контрольную плоскость"]
Send --> Ingest["Приём контрольной плоскостью:\nповторная очистка любого\nзапрещённого поля, если оно всё же есть"]
Ingest --> Store[("Хранилище аудита")]
Store --> Export["Каждый путь экспорта\n(API, SIEM, экспорт аудита):\nповторная очистка"]
Такой дизайн — осознанный выбор в пользу отказа от двух альтернатив:
| Альтернатива | Почему отклонена |
|---|---|
| Отклонять любое событие, содержащее запрещённое поле | Полностью теряется телеметрия от некорректно работающей или устаревшей версии агента, что ухудшает реконструкцию инцидента именно тогда, когда что-то уже пошло не так |
| Хранить исходные данные, очищать только при экспорте | Нарушает границу нераскрытия данных в самой критичной точке — исходные доказательства оказались бы в базе данных и резервных копиях, доступные любому, у кого есть доступ к БД или резервным копиям, а не только предполагаемому пути экспорта |
Принятая модель: принимать, очищать на входе и никогда не хранить то, что было
удалено — контрольная плоскость перезаписывает запрещённые поля при приёме, увеличивает
счётчик sanitized в своём ответе, чтобы производители событий могли обнаружить
собственное несоответствие требованиям, а действительно некорректно сформированные
(не-JSON) события по-прежнему отклоняются и учитываются как rejected.
Экспорт в SIEM
Записи аудита, события и метрики качества механизмов обнаружения отправляются напрямую по HTTP в Grafana Loki — без промежуточного процесса отправки или сбора. Экспорт повторно применяет тот же проход очистки (никогда не передаются исходные командные строки, аргументы, рабочие каталоги или пути к ресурсам/исполняемым файлам), использует однозначно воспроизводимый порядок и стабильные метки, поддерживает заголовок для разных организаций, ставит данные в очередь с повторными попытками и увеличением интервала при сбое и поддерживает режим пробного запуска, который возвращает сформированные данные без фактической отправки.