Аудит экспозиции — что субъект уже может достать
census audit — это read-only обзор фактического состояния прав файловой
системы. Он отвечает на вопрос, на который подготовка ответить не может: при
имеющихся на устройстве объектах доступа — не тех, что объявил Census, а всём,
что уже лежит на диске, — что субъект реально может прочитать и записать сверх
того, что задумывал принцип наименьших привилегий?
Это обратная сторона apply. apply выдаёт доступ вперёд (роль-учётки, группы,
sudoers.d, файловые ACL). audit смотрит на устройство, как оно есть, и
вскрывает фоновую переизбыточность прав (ambient over-permission), которая тихо
подрывает ограниченную учётку: доступный на запись всем (world-writable)
спул cron, читаемый всеми ключ, drop-in в sudoers.d, который может
отредактировать сервисная учётка. Вы делаете учётку ограниченной, а
world-writable файл всё равно позволяет ей подняться — audit показывает, где
именно.
audit никогда ничего не мутирует. Как и doctor, он только читает. Он не
делает и не может сделать chmod или setfacl над файлом — он сообщает о
проблеме и подсказывает исправление.
Два режима, один движок:
| Команда | На какой вопрос отвечает |
|---|---|
census audit fs | Какие опасные классы прав есть на этом устройстве? (карта позиции, не зависящая от субъекта) |
census audit expose --principal <name|uid> | Что конкретно эта учётка реально может достать — сверх того, что ей выдали? |
Запускайте от root для полной картины. Аудит читает режимы файлов, владельцев и POSIX-ACL; чтобы оценить экспозицию secret-класса (например
/etc/shadow), нужно его прочитать, а для этого нужен root. Запускайте подsudoради полного покрытия — он read-only, так что запуск от root безопасен.
1. audit fs — карта позиции устройства
Заголовок раздела «1. audit fs — карта позиции устройства»audit fs обходит деревья в области сканирования и перечисляет опасные классы
прав, независимо от какого-либо субъекта:
- world-writable объекты в чувствительных деревьях (cron,
sudoers.d, systemd-юниты, конфиги, бинарники изPATH); - инвентаризация setuid/setgid — каждый setuid/setgid-бинарник, причём те, что вдобавок world-writable, помечаются как критичные;
- секреты, читаемые всеми — файлы класса ключ/credential/shadow, которые
может прочитать
other; - объекты, доступные на запись широкой группе — записываемые широкой группой
(
adm,wheel,sudo,staff,users).
sudo census audit fs --root /etc --root /var/spool# audit fs: 1 finding(s)# high leak secret /etc/ssl/certs/ssl-cert-snakeoil.pem (access r--, via other_bits, fix ambient)# — remove world read of a secret manually: `chmod 640 /etc/ssl/certs/ssl-cert-snakeoil.pem`Каждый finding несёт: путь, эффективный доступ (rwx), способ
получения доступа (via — other_bits, group:<g>, acl_user:<u>, …),
класс объекта, риск (escalation / leak / tamper), производную
severity, класс исправления (remediation_class, §4) и конкретную
подсказку по исправлению.
2. audit expose — что достаёт одна учётка
Заголовок раздела «2. audit expose — что достаёт одна учётка»audit expose прорезает то же сканирование сквозь одного субъекта. Он разрешает
идентичность учётки — UID плюс первичную и дополнительные группы — и для этого
субъекта прогоняет POSIX-проверку доступа против каждого объекта в области
сканирования, затем сообщает только то, что учётка реально может достать.
sudo census audit expose --principal daemon --root /etc --root /var/spool# audit expose: principal daemon (unmanaged)# note: verdict is DAC-only (mode, owner, POSIX ACL) and is an upper bound:# MAC layers (SELinux, AppArmor, PARSEC) may restrict actual access further# 1 finding(s)# high leak secret /etc/ssl/certs/ssl-cert-snakeoil.pem (access r--, via other_bits, fix ambient) — …Субъект именуется именем входа или числовым UID. Идентичность разрешается
только из локальных /etc/passwd и /etc/group — членство в группах из
NSS/LDAP не учитывается (это сознательное ограничение: на хосте, опирающемся на
каталог, групповая досягаемость может быть недооценена). Голый UID без записи в
passwd всё равно аудируется — по сырой досягаемости, без членства в группах.
2.1 Досягаемость строга — никаких ложных срабатываний из-за закрытого предка
Заголовок раздела «2.1 Досягаемость строга — никаких ложных срабатываний из-за закрытого предка»Файл «досягаем» субъектом, только если каждый каталог-предок даёт ему поиск
(x). Файл с режимом 0777 за каталогом 0700, которым владеет root,
недосягаем для не-владельца и не попадает в отчёт — ровно то ложное
срабатывание, которое поднял бы наивный find -perm. Сама проверка доступа
следует алгоритму POSIX-ACL (владелец → именованный пользователь → класс группы с
маской → other), уважая маску ACL и правило «совпало, но запрещено — не
проваливается в other».
2.2 Вердикт — только DAC, честная верхняя граница
Заголовок раздела «2.2 Вердикт — только DAC, честная верхняя граница»В open-билде audit оценивает только дискреционное управление доступом
(DAC): биты режима, владение и POSIX-ACL. Он не моделирует мандатное
управление доступом (SELinux, AppArmor или мандатную целостность PARSEC в Astra).
Мандатный (MAC) слой может ограничить доступ ещё сильнее, поэтому вердикт —
верхняя граница, «досягаемо при DAC». Каждый отчёт expose это проговаривает.
Чтобы уточнить вердикт по MAC хоста, см. §2.4.
2.3 Killer-фильтр — только избыток для managed-учётки
Заголовок раздела «2.3 Killer-фильтр — только избыток для managed-учётки»Когда субъект — роль-учётка под управлением Census, expose вычитает её
намеченный базис (intended baseline) — её домашний каталог плюс пути, которые
выдал каталог, — и сообщает только тот доступ, что у неё есть сверх этого
замысла. Вы объявили, что учётка должна доставать /etc/ssh; если она вдобавок
может писать в /var/spool/cron, остаётся только finding про cron. Для учётки,
которой Census не управляет, базиса для вычитания нет, поэтому показывается сырая
досягаемость.
Именно это делает expose специфичным для Census, а не очередным generic-
сканером прав: он знает, что учётка должна была иметь, и показывает разницу.
2.4 Вердикт с учётом MAC (enterprise)
Заголовок раздела «2.4 Вердикт с учётом MAC (enterprise)»Open-билд работает только с DAC (§2.2). Коммерческий MAC-провайдер может уточнить вердикт по мандатному управлению доступом хоста — сегодня Astra PARSEC, позже SELinux — через seam, нейтральный к MAC-системе, так что один и тот же аудит работает поверх разных MAC-систем. Когда провайдер активен:
- Finding, досягаемый при DAC, но заблокированный MAC в каждом контексте безопасности, который может принять субъект, подавляется — он доказанно недосягаем, а не просто верхняя граница. Finding, всё ещё досягаемый в каком-то контексте, сохраняется и аннотируется этим контекстом (контекстами).
- Каждый finding получает поле
mac:{ system, object_label, reachable_in }(илиnull, когда провайдера нет либо объект без метки). В режимеaudit fs(позиция) субъекта нет, поэтому провайдер лишь аннотирует метку каждого объекта — он никогда не подавляет. - Заметка в отчёте меняется с оговорки «только DAC» на
DAC + <system>.
Мандатные правила (целостность/конфиденциальность PARSEC, type-enforcement
SELinux) живут целиком в коммерческом провайдере — открытое ядро не несёт
MAC-логики и зависимости от libpdp/libselinux. --mac в open-билде
честно отказывает с «no MAC backend in this build», а не молча ничего не делает;
на хосте без запрошенной MAC-системы провайдер — no-op, и вердикт остаётся
только-DAC. Аудит остаётся read-only — он осматривает метки, но никогда их не
выставляет.
3. Риск, severity и классы объектов
Заголовок раздела «3. Риск, severity и классы объектов»Каждый объект в области сканирования классифицируется по glob-таблице (и битам setuid/setgid):
| Класс | Примеры |
|---|---|
cron | /var/spool/cron/**, /etc/cron*/**, /etc/crontab |
systemd-unit | /etc/systemd/**, /lib/systemd/system/** |
sudoers | /etc/sudoers, /etc/sudoers.d/** |
path-binary | /usr/bin/**, /bin/**, /usr/local/bin/**, /sbin/** |
secret | /etc/shadow*, **/*.key, **/*.pem, **/id_rsa*, **/.env*, **/*credentials* |
config | security-значимая конфигурация в /etc |
setuid-binary | любой setuid/setgid-исполняемый файл |
generic | всё остальное |
Риск и severity выводятся детерминированно:
- запись в cron / sudoers / systemd-unit / бинарник из
PATH/ setuid- бинарник →escalation, High; - чтение секрета →
leak, High; - запись в конфиг-файл →
tamper, Medium; - world-writable generic-объект → Low;
- чтение не-секретного файла finding’ом не является.
audit завершается с ненулевым кодом, когда хотя бы один finding имеет
severity High или выше (та же конвенция, что у doctor), — так его можно
завести в CI или мониторинг; чистое сканирование (или только подпороговые
findings) выходит с 0.
4. Класс исправления — Census честен в том, что он может починить
Заголовок раздела «4. Класс исправления — Census честен в том, что он может починить»Каждый finding помечен классом исправления (remediation_class), который
говорит, кто его чинит:
ambient— доступ исходит из объекта, которым Census не владеет: чужой world-writable каталог, читаемый всеми секрет, чужая группа. Census не может это убрать — декларация подготавливает собственные объекты Census, она не трогает базовый режим файла или чужой ACL. Подсказка — это ручная команда (chmod o-w …,chmod 640 …,setfacl -x …); Census никогда не утверждает, что починит за вас.in-model— доступ исходит из объекта, которым Census владеет: членство в группе под управлением Census либо один из собственных файловых grant’ов учётки, более широкий, чем нужно. Здесь исправление и есть изменение декларации, и подсказка так и говорит («сузьте декларацию»).
Это разделение снимает очевидное возражение — «декларация не может отозвать
world-write на каждом файле». Верно: не может, и audit не делает вид, что
может. Для фоновой переизбыточности прав его задача — точно сообщить о
проблеме: какой субъект, какой путь, почему доступ существует и какая ручная
команда его закрывает.
Сам отчёт — чувствительный артефакт. Это карта слабых мест устройства. Вывод несёт только метаданные — путь, режим, класс — и никогда содержимое секретного файла, но и сам отчёт держите как конфиденциальный: не вставляйте его в публичный канал или в незащищённый лог.
5. Область, вывод и флаги
Заголовок раздела «5. Область, вывод и флаги»census audit fs [--root <PATH>]… [--full] [--format text|json] [--config <PATH>] [--managed <PATH>]census audit expose --principal <name|uid> [--root <PATH>]… [--full] [--format text|json] [--config <PATH>] [--managed <PATH>]| Флаг | Смысл |
|---|---|
--root <PATH> | Корень сканирования (повторяемо). Конфликтует с --full. Должен быть абсолютным. |
--full | Обойти всю файловую систему от / (псевдо-ФС всё равно пропускаются). |
--principal <name|uid> | (только expose) учётка для оценки. |
--format text|json | Формат вывода. text (по умолчанию) — для человека; json — стабильный, контрактно-залоченный вывод на stdout. |
--config <PATH> | Конфиг аудита (по умолчанию /etc/census/exposure.toml); отсутствие файла ⇒ встроенные дефолты. |
--managed <PATH> | Managed-реестр (по умолчанию /var/lib/census/managed.toml), для базиса managed-учётки. |
--mac | Уточнить вердикт по MAC хоста (§2.4). Нужен коммерческий MAC-провайдер; в open-билде честно отказывает с «no MAC backend in this build». |
Область по умолчанию — курируемый набор security-значимых деревьев (/etc,
/var, /opt, /usr/local, /srv, /home, /root). Псевдо-ФС (/proc,
/sys, /dev, /run) и сетевые точки монтирования всегда пропускаются —
включая под --full, — и любая пропущенная точка отмечается в уведомлении, так
что покрытие никогда не урезается молча. Сканирование не переходит на другой
локальный том неявно: локальные суб-монты (отдельный раздел /var/log или
/home) обходятся; сетевые ФС (NFS, CIFS, …) — нет.
При запуске в интерактивном терминале без --root/--full audit
предлагает выбор области (security-значимая / полная / свои корни).
Неинтерактивный запуск (CI, пайп) никогда не блокируется на этом запросе — он
молча использует область по умолчанию. Диагностика и запрос идут в stderr,
так что --format json оставляет stdout чистым и парсимым.
JSON-вывод залочен golden-схемой (contract/exposure-report.schema.json).
6. Конфигурация — exposure.toml
Заголовок раздела «6. Конфигурация — exposure.toml»Область сканирования и классификаторы настраиваются. Файл парсится строго
(deny_unknown_fields); отсутствие файла или отсутствие ключа откатывается к
встроенному дефолту, но присутствующий, но битый файл — это честная ошибка
(никогда не молчаливый дефолт).
# /etc/census/exposure.toml — все ключи опциональны; отсутствие ⇒ встроенный дефолт
# Деревья, которые покрывает сканирование по умолчанию. Должны быть абсолютными# путями; пустой список отвергается (security-инструмент, который ничего не# сканирует и рапортует «всё чисто», — это ловушка).scan_roots = ["/etc", "/var", "/opt", "/usr/local", "/srv", "/home", "/root"]
# Globs, помечающие объект как secret-класс. Каждый шаблон несёт не более одного# `**` (матчер бэктрекает через `**`; несколько были бы экспоненциальны на# --full-сканировании).secret_globs = ["/etc/shadow*", "**/*.key", "**/*.pem", "**/id_rsa*", "**/.env*", "**/*credentials*"]
# Имена групп, считаемых «широкими» для оси broad-group-writable. Сопоставляются# по реальному имени группы, разрешённому из /etc/group (так что перенумерованный# gid всё равно ловится).broad_groups = ["adm", "wheel", "sudo", "staff", "users"]Заметка по тюнингу. Дефолтный glob
**/*.pemловит и публичные сертификаты (например/etc/ssl/certs), которые читаемы всеми по замыслу, — они всплывают как малосигнальные findings классаsecret. Сузьтеsecret_globsили исключите дерево публичных сертификатов, если этот шум на ваших хостах нежелателен.
См. справочник TOML для таблицы полей.
7. Типовое применение
Заголовок раздела «7. Типовое применение»# Сканирование позиции всего устройства, JSON для пайплайна мониторинга:sudo census audit fs --full --format json > posture.json
# Что реально достаёт эта ограниченная сервисная учётка?sudo census audit expose --principal app-svc
# Прицельная проверка после подготовки новой ограниченной роли:sudo census audit expose --principal kiosk-oper --root /etc --root /varaudit read-only и не нуждается в декларации — наведите его на устройство, и он
рапортует. Заведите audit fs в тот же путь мониторинга, что и doctor (оба
выходят с ненулевым кодом при реальной проблеме), и запускайте audit expose
всякий раз, когда создаёте или ужесточаете ограниченную учётку, чтобы убедиться:
фоновая файловая система не выдаёт ей больше, чем вы задумали.
Дальнейшее чтение
Заголовок раздела «Дальнейшее чтение»getting-started.md— установка, настройка, первый apply, эксплуатация.toml-reference.md— каждый TOML-файл, который читает Census, включаяexposure.toml.README.mdрепозитория — модель продукта, свойства безопасности и полный справочник CLI.