Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
ubuntils — Python CLI/TUI для форензической триажной проверки систем Ubuntu — обнаруживает и устраняет механизмы персистентности с помощью сбора артефактов, корреляции временной шкалы и интеграции с Wazuh. | Kitploit
Инструменты/GitHubGitHub/asmitdesai/ubuntils
Оборонительные ИнструментыУправление индикаторами компрометации (IOC)Механизмы персистентностиАнализ уязвимостейСкриптинг и автоматизацияАудит конфигурацииФорензикаЦифровая криминалистикаРеагирование на ИнцидентыАнализ Журналов
GitHub
1483 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
asmitdesai/ubuntils

ubuntils

Python CLI/TUI для форензической триажной проверки систем Ubuntu — обнаруживает и устраняет механизмы персистентности с помощью сбора артефактов, корреляции временной шкалы и интеграции с Wazuh.

Репозиторий
Поделиться

ubuntils

Форензический триаж для работающих систем Ubuntu — автоматизированный сбор артефактов, обнаружение персистентности и управляемое устранение менее чем за 5 секунд.

CI Python Tests Coverage License Arch Ubuntu Offline analysis Detection rules SIEM


Проблема

Когда вы подозреваете, что система Linux скомпрометирована, первые 30-40 минут обычно уходят на последовательный запуск одних и тех же десяти команд: проверка запущенных процессов, поиск странных заданий cron, grep по LD_PRELOAD, сканирование authorized_keys на новые записи, аудит sudoers. Каждый шаг выполняется вручную, с переключением контекста и подвержен ошибкам в условиях стресса. Пропустите один источник — скажем, /etc/sudoers.d/ вместо только /etc/sudoers, или пользовательские crontab в дополнение к /etc/cron.d/ — и у вас будет неполная картина.

Существующие решения не решают эту задачу чисто. lynis — это аудитор укрепления, а не инструмент триажа: он сообщает о слабостях конфигурации на чистой системе и создаёт шум на заражённой. chkrootkit и rkhunter проверяют известные сигнатуры руткитов, но слепы к новым техникам персистентности, таким как злоупотребление systemd-таймерами или правдоподобно выглядящие записи cron. Обобщённые запросы к SIEM требуют лог-инфраструктуры, которой может не быть на исследуемой системе. А форензические комплексы вроде Volatility нацелены на образы памяти, а не на живую оболочку на работающем хосте.

Пробел — это инструмент, который работает на живой системе прямо сейчас, охватывает наиболее распространённые векторы персистентности, коррелирует активность из разных источников логов в единую временную шкалу и точно указывает, на что смотреть — без необходимости во внешнем агенте, базе данных или интернет-соединении.


Что делает ubuntils

ubuntils работает в четыре последовательных этапа:

  1. Сбор — Одиннадцать коллекторов параллельно собирают форензические артефакты из /proc, таблиц cron, юнитов systemd, SSH-ключей, файлов sudoers, определений окружения, целостности пакетов (dpkg --verify), конфигурации PAM/NSS и загруженных модулей ядра. Занимает примерно 2,5 секунды на типичной системе.
  2. Обнаружение — Движок обнаружения прогоняет все шестнадцать встроенных правил — плюс любые пользовательские правила, загруженные через --rules — по собранным артефактам, формируя ранжированный список находок с оценкой достоверности примерно за одну секунду.
  3. Временная шкала — Построитель временной шкалы параллельно читает syslog, journald и auditd и хронологически коррелирует события, добавляя примерно 0,3 секунды. Затем каждая находка автоматически коррелируется с временной шкалой, так что она несёт связанные с ней близлежащие события.
  4. Вывод — Результаты отображаются либо в интерактивном TUI с четырьмя вкладками (по умолчанию), либо в виде структурированного JSON в stdout (--json).

Сам ubuntils не делает сетевых вызовов, и каждая функция — включая пользовательские правила и корреляцию — работает с локально собранными артефактами. Единственный способ, которым находки могут покинуть хост, — это интеграция с Wazuh: если установлен агент Wazuh, живой scan записывает свои находки в локальный файл, который агент затем отправляет своему менеджеру. Передайте --no-wazuh, чтобы отключить это для запуска.

ubuntils scan не изменяется всем нижеописанным — он по-прежнему на 100% живой, однохостовый, и каждый существующий флаг работает идентично. Две дополнительные команды, collect и analyze, разделяют тот же конвейер обнаружения/временной шкалы на офлайн-дружественный рабочий процесс «сначала собрать, потом анализировать» для случаев, когда вы не можете (или не хотите) запускать обнаружение непосредственно на исследуемом хосте — см. Офлайн-анализ: collect и analyze ниже, включая оговорки о покрытии обнаружения.


Установка

Ubuntu 22.04+ и любая система с PEP 668 (рекомендуется):

Ubuntu 22.04+ блокирует общесистемный pip install. Используйте pipx — он прозрачно управляет окружением, так что вам никогда не придётся об этом думать:```bash sudo apt install pipx -y cd ubuntils pipx install -e . ubuntils scan

root@kitploit:~
**Устаревшие системы / ручная установка:**```bash
git clone https://github.com/asmitdesai/ubuntils.git
cd ubuntils
pip install -r requirements.txt -e .
ubuntils scan

ubuntils требует root для полного доступа к артефактам. Если вы запускаете ubuntils scan от имени непривилегированного пользователя, он автоматически перезапустит себя с sudo, используя тот же интерпретатор Python (по абсолютному пути), так что будет использовано правильное окружение без передачи вашего PATH в root-процесс. Каждая внешняя команда (ss, dpkg, systemctl, …) разрешается по фиксированному пути поиска, принадлежащему root, а не по вашему PATH. Запуск без root пропустит /etc/shadow, некоторые записи /proc и защищённые файлы cron, и для каждого будет записано предупреждение.


Быстрый старт

Только обнаружение — интерактивный TUI:```bash sudo ubuntils scan

root@kitploit:~
**Обнаружение с выводом JSON, сохранённым в файл:**```bash
sudo ubuntils scan --json > /tmp/triage-$(hostname)-$(date +%Y%m%d).json

Обнаружение с предварительным просмотром исправления через CLI (пробный запуск — изменения не применяются):```bash sudo ubuntils scan --remediate

root@kitploit:~
**Обнаружение с применением исправления через CLI:**```bash
sudo ubuntils scan --remediate --confirm

Версия для печати:```bash ubuntils version

root@kitploit:~
**Соберите защищённый от подмены пакет для последующего или офлайн-анализа:**```bash
sudo ubuntils collect --output /path/to/bundle.tar.gz

Анализ ранее собранного пакета (без прав root):```bash ubuntils analyze /path/to/bundle.tar.gz --json

root@kitploit:~
**Анализ смонтированного криминалистического образа или извлечённого дерева файловой системы вместо пакета:**```bash
ubuntils analyze --root /mnt/forensic-image --json

См. Офлайн-анализ: сбор и анализ для формата пакета и — что важно — того, что офлайн-анализ не может обнаружить по сравнению с живым scan.


Флаги и конфигурация```

ubuntils scan [OPTIONS] --json Output JSON to stdout instead of launching the TUI --output FILE Write the JSON report to FILE (implies --json) --remediate Run the remediation engine after detection --confirm Required with --remediate to actually apply changes (else dry-run) --min-confidence N Only auto-remediate findings with confidence >= N (default 40) --no-wazuh Never forward findings to a local Wazuh agent --config FILE YAML allowlist of findings to suppress (see below) --baseline FILE YAML baseline of environment-specific known-good fingerprints to suppress (see below) --since TIME Limit the timeline to events since TIME (e.g. '24h', '7d', '2026-05-20') --rules FILE YAML file of custom detection rules to add (see below) --verbose Verbose structlog output

ubuntils collect [OPTIONS] --output FILE Bundle path to write (default ./ubuntils-bundle-.tar.gz) --verbose Verbose structlog output

ubuntils analyze (BUNDLE | --root PATH) [OPTIONS] --root PATH Analyze a mounted image / artifact tree instead of a bundle --json Output JSON instead of launching the TUI --output FILE Write the JSON report to FILE (implies --json) --config FILE YAML allowlist of findings to suppress (same format as scan) --baseline FILE YAML baseline of environment-specific known-good fingerprints to suppress (same format as scan) --rules FILE YAML file of custom detection rules to add (same format as scan) --since TIME Limit the timeline to events since TIME (e.g. '24h', '7d', '2026-05-20') --verbose Verbose structlog output

ubuntils version Print version string and exit

root@kitploit:~
### Внесение ложных срабатываний в белый список (`--config`)

Только что подготовленный или управляемый CI хост генерирует ожидаемый шум — ключи развёртывания, crontab-задачи провижининга, встроенная инициализация оболочки. Вместо того чтобы приучать специалистов по реагированию мысленно его фильтровать, подавляйте его явно с помощью YAML-списка разрешённых элементов:```yaml
# allowlist.yaml
allowlist:
  rules:
    - SHELL_RC_MODIFICATION          # suppress this rule entirely
  paths:
    - /home/ci/.ssh/authorized_keys  # suppress any finding on this exact path
  • --no-verify — пропустить проверку TLS-сертификата (небезопасно, только для тестирования)
  • --timeout — таймаут запроса в секундах (по умолчанию: 10)
  • --retries — количество повторных попыток при неудачных запросах (по умолчанию: 3)
  • --proxy — прокси-сервер для использования (например, http://127.0.0.1:8080)
  • --user-agent — пользовательский User-Agent (по умолчанию: случайный)
  • --threads — количество параллельных потоков (по умолчанию: 10)
  • --output — путь к выходному файлу для сохранения результатов
  • --format — формат вывода: json, csv или text (по умолчанию: text)
  • --verbose — включить подробное логирование
  • --quiet — подавить весь вывод, кроме результатов
  • --config — путь к файлу конфигурации
  • --version — показать версию программы и выйти
  • --help — показать справочное сообщение и выйти

Примеры

root@kitploit:~
# Базовое сканирование одного URL
python3 scanner.py -u https://example.com

# Сканирование списка URL из файла
python3 scanner.py -f urls.txt

# Сканирование с пользовательскими параметрами
python3 scanner.py -u https://example.com --timeout 30 --retries 5 --threads 20

# Сохранение результатов в формате JSON
python3 scanner.py -f urls.txt --output results.json --format json

# Использование прокси и отключение проверки TLS
python3 scanner.py -u https://example.com --proxy http://127.0.0.1:8080 --no-verify

Вывод

Инструмент выводит результаты в следующем формате:

root@kitploit:~
[+] URL: https://example.com
    Status: 200 OK
    Server: nginx/1.18.0
    Technologies: PHP, jQuery, Bootstrap
    Vulnerabilities: CVE-2021-1234, CVE-2021-5678

При использовании --format json вывод будет следующим:

root@kitploit:~
{
  "url": "https://example.com",
  "status": 200,
  "server": "nginx/1.18.0",
  "technologies": ["PHP", "jQuery", "Bootstrap"],
  "vulnerabilities": ["CVE-2021-1234", "CVE-2021-5678"]
}

Лицензия

Этот проект распространяется под лицензией MIT. Подробности см. в файле LICENSE.

Отказ от ответственности

Данный инструмент предназначен только для образовательных целей и тестирования на проникновение в авторизованных средах. Использование этого инструмента против целей без предварительного взаимного согласия является незаконным. Авторы не несут ответственности за любое неправомерное использование или ущерб, причинённый этим программным обеспечением.```bash sudo ubuntils scan --json --config allowlist.yaml

root@kitploit:~
Подавление всегда явное — по идентификатору правила и/или точному пути к артефакту. Не существует универсального переключателя «игнорировать всё». Пример находится в [`examples/allowlist.yaml`](https://github.com/asmitdesai/ubuntils/blob/main/examples/allowlist.yaml).

### Базелинирование заведомо доверенных (`--baseline`)

`--config` подавляет правило или путь *везде, для всех, кто запускает ubuntils против этой кодовой базы*. `--baseline` действует уже и привязан к окружению: он говорит «в *этом* окружении именно этот артефакт — этот SSH-ключ, этот RC-файл — заведомо доверенный», не отключая правило или путь для всех остальных хостов, которые вы сканируете тем же инструментом. Хранится в отдельном файле от `--config` по той же причине, по которой `--rules` отделён: подавление и allowlisting на уровне правил — это разные задачи, которым не место в одном файле.```yaml
# baseline.yaml
baseline:
  - rule_id: SSH_UNAUTHORIZED_KEY
    fingerprint: ci@ci-runner          # substring match against the finding's raw_value
  - rule_id: SHELL_RC_MODIFICATION
    fingerprint: /home/deploy/.bashrc  # exact match against the finding's artifact_path

| --no-color | Отключить цветной вывод | | --debug | Включить режим отладки | | --verbose | Включить подробный вывод | | --silent | Подавить весь вывод, кроме ошибок | | --version | Показать версию программы и выйти | | --help | Показать справку и выйти |

Примеры

root@kitploit:~
# Сканировать один URL
python3 csp_scanner.py https://example.com

# Сканировать несколько URL из файла
python3 csp_scanner.py -f urls.txt

# Сканировать с подробным выводом и сохранить результаты в JSON
python3 csp_scanner.py https://example.com -v -o results.json

# Сканировать с пользовательским таймаутом и заголовками
python3 csp_scanner.py https://example.com -t 15 -H "Authorization: Bearer token"

# Сканировать с использованием прокси
python3 csp_scanner.py https://example.com -p http://proxy:8080

# Сканировать с отключённой проверкой SSL
python3 csp_scanner.py https://example.com -k

# Сканировать с пользовательским User-Agent
python3 csp_scanner.py https://example.com -A "Mozilla/5.0 (Custom)"

# Сканировать с ограничением скорости
python3 csp_scanner.py -f urls.txt -r 5

# Сканировать с повторными попытками
python3 csp_scanner.py https://example.com --retries 3

# Сканировать с параллельными потоками
python3 csp_scanner.py -f urls.txt --threads 10

# Сканировать с включённым режимом отладки
python3 csp_scanner.py https://example.com --debug

# Сканировать с отключённым цветным выводом
python3 csp_scanner.py https://example.com --no-color

# Сканировать с подавлением вывода
python3 csp_scanner.py https://example.com --silent

# Показать версию
python3 csp_scanner.py --version

# Показать справку
python3 csp_scanner.py --help

Форматы вывода

Инструмент поддерживает несколько форматов вывода:

  • text (по умолчанию): Удобочитаемый текстовый вывод
  • json: Формат JSON для машинной обработки
  • csv: Формат CSV для работы с электронными таблицами
  • html: Формат HTML для просмотра в браузере
root@kitploit:~
# Вывод в формате JSON
python3 csp_scanner.py https://example.com -o results.json -f json

# Вывод в формате CSV
python3 csp_scanner.py https://example.com -o results.csv -f csv

# Вывод в формате HTML
python3 csp_scanner.py https://example.com -o results.html -f html

Пример вывода

root@kitploit:~
[*] Сканирование https://example.com...
[+] Обнаружен заголовок Content-Security-Policy
[!] Обнаружены проблемы с политикой CSP:
    - Отсутствует директива 'default-src'
    - Директива 'script-src' содержит 'unsafe-inline'
    - Директива 'script-src' содержит 'unsafe-eval'
    - Отсутствует директива 'object-src'
    - Отсутствует директива 'base-uri'
    - Отсутствует директива 'frame-ancestors'
[+] Оценка безопасности: 45/100 (Средний риск)
[*] Сканирование завершено. Найдено 1 URL, 6 проблем.

Как это работает

Инструмент выполняет следующие шаги:

  1. Разбор аргументов командной строки: Анализирует входные данные и параметры
  2. Загрузка URL-адресов: Читает URL-адреса из аргументов командной строки или файла
  3. HTTP-запросы: Отправляет HTTP-запросы к каждому URL-адресу
  4. Извлечение заголовков: Извлекает заголовки Content-Security-Policy и Content-Security-Policy-Report-Only
  5. Анализ политики: Разбирает и анализирует директивы политики CSP
  6. Обнаружение проблем: Выявляет распространённые ошибки конфигурации и уязвимости
  7. Оценка безопасности: Вычисляет оценку безопасности на основе обнаруженных проблем
  8. Генерация отчёта: Форматирует результаты в выбранном формате вывода

Анализ политики CSP

Инструмент анализирует политику CSP на предмет:

  • Отсутствующие директивы: Проверяет наличие важных директив, таких как default-src, script-src, object-src, base-uri, frame-ancestors
  • Небезопасные значения: Обнаруживает небезопасные значения, такие как unsafe-inline, unsafe-eval, *, data:, http:
  • Слабые политики: Выявляет слишком разрешительные политики
  • Устаревшие директивы: Обнаруживает устаревшие или нерекомендуемые директивы
  • Синтаксические ошибки: Проверяет наличие синтаксических ошибок в политике

Оценка безопасности

Оценка безопасности рассчитывается на основе:

  • Количество обнаруженных проблем
  • Серьёзность каждой проблемы
  • Наличие важных директив
  • Общая строгость политики

Оценка варьируется от 0 (наихудшая) до 100 (наилучшая):

  • 90-100: Отлично
  • 70-89: Хорошо
  • 50-69: Средне
  • 30-49: Плохо
  • 0-29: Критично

Обнаруживаемые проблемы

Инструмент обнаруживает следующие типы проблем:

Отсутствующие директивы

  • Отсутствует default-src: Директива default-src является резервной для других директив
  • Отсутствует script-src: Директива script-src контролирует источники JavaScript
  • Отсутствует object-src: Директива object-src контролирует источники плагинов
  • Отсутствует base-uri: Директива base-uri контролирует допустимые URL-адреса в элементе <base>
  • Отсутствует frame-ancestors: Директива frame-ancestors контролирует, какие сайты могут встраивать страницу

Небезопасные значения

  • unsafe-inline: Разрешает встроенные скрипты и стили
  • unsafe-eval: Разрешает eval() и подобные функции
  • *: Разрешает любой источник
  • data:: Разрешает URL-адреса data:
  • http:: Разрешает незашифрованные HTTP-соединения
  • https:: Разрешает все HTTPS-соединения

Слабые политики

  • Слишком разрешительная политика: Политика разрешает слишком много источников
  • Отсутствие ограничений: Политика не ограничивает опасные функции
  • Устаревшие директивы: Использование устаревших директив, таких как report-uri

Устранение неполадок

Распространённые проблемы

Проблема: ModuleNotFoundError: No module named 'requests'

Решение: Установите необходимые зависимости:

root@kitploit:~
pip install -r requirements.txt

Проблема: SSL: CERTIFICATE_VERIFY_FAILED

Решение: Используйте флаг -k для отключения проверки SSL или обновите сертификаты:

root@kitploit:~
python3 csp_scanner.py https://example.com -k

Проблема: Тайм-аут при сканировании

Решение: Увеличьте тайм-аут с помощью флага -t:

root@kitploit:~
python3 csp_scanner.py https://example.com -t 30

Проблема: Сканирование слишком медленное

Решение: Увеличьте количество потоков с помощью флага --threads:

root@kitploit:~
python3 csp_scanner.py -f urls.txt --threads 20

Проблема: Ошибки ограничения скорости

Решение: Уменьшите ограничение скорости с помощью флага -r:

root@kitploit:~
python3 csp_scanner.py -f urls.txt -r 2

Режим отладки

Включите режим отладки для получения подробной информации:

root@kitploit:~
python3 csp_scanner.py https://example.com --debug

Это покажет:

  • Полные HTTP-запросы и ответы
  • Подробный анализ политики CSP
  • Информацию об обработке ошибок
  • Данные о времени выполнения

Участие в разработке

Мы приветствуем вклад в развитие проекта! Вот как вы можете помочь:

  1. Форкните репозиторий
  2. Создайте ветку для функции (git checkout -b feature/amazing-feature)
  3. Зафиксируйте изменения (git commit -m 'Add some amazing feature')
  4. Отправьте изменения в ветку (git push origin feature/amazing-feature)
  5. Откройте Pull Request

Руководство по стилю кода

  • Следуйте рекомендациям PEP 8
  • Используйте осмысленные имена переменных
  • Добавляйте строки документации к функциям и классам
  • Включайте тесты для новых функций
  • Обновляйте документацию при необходимости

Запуск тестов

root@kitploit:~
# Запустить все тесты
python3 -m pytest tests/

# Запустить с покрытием
python3 -m pytest tests/ --cov=csp_scanner

# Запустить конкретный тестовый файл
python3 -m pytest tests/test_scanner.py

Лицензия

Этот проект лицензирован под лицензией MIT — подробности см. в файле LICENSE.

Благодарности

  • Спасибо всем участникам, которые помогли улучшить этот инструмент
  • Вдохновлено различными инструментами и ресурсами по безопасности CSP
  • Создано с использованием Python и Requests

Контакты

  • Автор: Security Researcher
  • Email: [email protected]
  • GitHub: https://github.com/example/csp-scanner

Ссылки

  • Спецификация CSP Level 3
  • Документация MDN по CSP
  • Шпаргалка по CSP от OWASP
  • CSP Evaluator
  • Отчёт о безопасности CSP

Отказ от ответственности: Этот инструмент предназначен только для образовательных целей и тестирования безопасности. Всегда получайте надлежащее разрешение перед сканированием веб-сайтов, которые вам не принадлежат. Авторы не несут ответственности за любое неправомерное использование или ущерб, причинённый этим инструментом.```bash sudo ubuntils scan --json --baseline baseline.yaml

root@kitploit:~
Запись базовой линии сопоставляется по `rule_id` плюс `fingerprint`, проверяемому как подстрока `raw_value` находки или точное совпадение с её `artifact_path`. Совпадение полностью удаляет находку из отчёта — однако подавление никогда не бывает безмолвным: количество находок, удалённых базовой линией, всегда видно в `scan_metadata.suppressed_by_baseline`. Подавление через allowlist (`--config`) по-прежнему применяется поверх подавления базовой линией. Работает одинаково в `scan` и `analyze`. Пример находится в [`examples/baseline.yaml`](https://github.com/asmitdesai/ubuntils/blob/main/examples/baseline.yaml).

### Пользовательские правила обнаружения (`--rules`)

`--config` *подавляет* находки; `--rules` *добавляет* их. Это намеренно отдельные файлы, поскольку это противоположные задачи.

Файл правил работает только по сопоставлению с образцом — никаких выражений, никаких условий и никакого выполнения кода, поэтому его загрузка никогда не может запустить логику, предоставленную злоумышленником. Каждое правило указывает `source` артефакта, режим `match` и `pattern`:```yaml
# custom_rules.yaml
rules:
  - id: CUSTOM_KNOWN_MINER
    severity: HIGH                     # HIGH | MEDIUM | LOW
    title: Known cryptominer in process cmdline
    description: A running process command line matches a known miner.
    source: process                    # cron | environment | ssh | process | network
    match: substring                   # regex | substring | glob
    pattern: xmrig

| -s | Silent mode. Only output the final result. | | -v | Verbose mode. Show detailed progress. | | -o <file> | Write output to a file. | | --no-color | Disable colored output. | | --timeout <sec> | Set the request timeout in seconds. | | --proxy <url> | Use the specified proxy. | | --header <h> | Add a custom HTTP header. | | --user-agent <ua> | Set a custom User-Agent string. | | --retry <n> | Retry failed requests up to n times. | | --threads <n> | Number of concurrent threads. | | --rate-limit <n> | Limit requests to n per second. | | --config <file> | Load configuration from a file. | | --debug | Enable debug output. | | --version | Show version information. | | --help | Show the help message. |

Examples

root@kitploit:~
# Basic usage
tool -u https://example.com

# Scan a list of targets
tool -l targets.txt -o results.txt

# Use a proxy with custom headers
tool -u https://example.com --proxy http://127.0.0.1:8080 --header "X-Custom: value"

# Increase threads and set a rate limit
tool -l targets.txt --threads 20 --rate-limit 50

Configuration File

The tool supports a configuration file in YAML format:

root@kitploit:~
timeout: 30
threads: 10
rate_limit: 100
proxy: http://127.0.0.1:8080
headers:
  User-Agent: "CustomAgent/1.0"
  Accept: "*/*"

Output Format

Results are printed to stdout in the following format:

root@kitploit:~
[+] Target: https://example.com
    Status: 200
    Length: 12345
    Title: Example Domain

Exit Codes

CodeMeaning
0Success.
1General error.
2Invalid arguments.
3Network error.
4Timeout.

Troubleshooting

  • Connection refused: Ensure the target is reachable and the port is open.
  • Timeout errors: Increase the --timeout value or check your network connection.
  • SSL errors: Use --insecure to skip certificate verification (not recommended for production).
  • Permission denied: Run with appropriate privileges or check file permissions.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Contributions are welcome! Please read the CONTRIBUTING.md file for guidelines.

Acknowledgements

  • Thanks to all contributors who have helped improve this tool.
  • Special thanks to the open-source community for their support.```bash sudo ubuntils scan --json --rules custom_rules.yaml
root@kitploit:~
| `source` | Сопоставляется с |
|---|---|
| `cron` | Команда cron (path: файл crontab) |
| `environment` | Необработанная строка окружения/инициализации оболочки (path: определяющий файл) |
| `ssh` | Тип ключа, данные ключа и комментарий (path: файл `authorized_keys`) |
| `process` | Командная строка процесса (path: путь к исполняемому файлу) |
| `network` | Описание соединения (path: `remote_addr:remote_port`) |

`regex` и `substring` сопоставляются со столбцом текста; `glob` сопоставляется со столбцом пути — поэтому glob для `network`, такой как `203.0.113.*:*`, нацелен на удалённую конечную точку. Находки пользовательских правил только помечаются флагом (никогда не устраняются автоматически) и по-прежнему подчиняются подавлению через `--config`. Пример находится в [`examples/custom_rules.yaml`](https://github.com/asmitdesai/ubuntils/blob/main/examples/custom_rules.yaml).

### Целостность отчёта

Каждый отчёт `--json` содержит поле `report_sha256` — SHA-256 по каноническому содержимому отчёта. Это делает собранный артефакт триажа защищённым от подмены и позволяет ссылаться на конкретное сканирование по дайджесту в материалах дела. Отчёт также фиксирует `tool_version`, `hostname` и метку времени UTC `generated_at` в разделе `scan_metadata`. Для `scan` поля `hostname`/`ubuntu_version` описывают машину, на которой выполняется `ubuntils`; для `analyze --root` они считываются из собственных `/etc/hostname` и `/etc/os-release` образа. Для `analyze BUNDLE` они, напротив, берутся из собственного манифеста пакета — хоста, который был *собран*, а не хоста, выполняющего `analyze` — вместе с `collection_run_id` и `collected_at_utc_start`/`collected_at_utc_end` сбора, так что запись цепочки сохранности отчёта следует за доказательствами, а не за рабочей станцией аналитика.

**Проверка отчёта.** Отчёт выдаётся в канонической форме (ключи отсортированы, отступ в 2 пробела), и дайджест охватывает всё, кроме самого `report_sha256`:```python
import hashlib, json
doc = json.load(open("report.json"))
claimed = doc.pop("report_sha256")
assert hashlib.sha256(json.dumps(doc, indent=2, sort_keys=True).encode()).hexdigest() == claimed

Офлайн-анализ: сбор и анализ

ubuntils scan выполняет сбор, обнаружение и построение временной шкалы вместе на работающем хосте. collect и analyze разделяют этот конвейер на две части: collect получает защищённый от подмены набор данных с хоста (обнаружение не запускается), а analyze запускает тот же конвейер обнаружения/построения временной шкалы, что и scan, против набора данных или против смонтированного образа через --root, без необходимости прав root и без повторного обращения к исходному хосту. Это предназначено для случаев, когда вы хотите собрать артефакты один раз и анализировать их позже, в другом месте или многократно — или когда вы проводите триаж дискового образа, а не работающей системы.

`ubuntils collect````bash

sudo ubuntils collect --output /path/to/bundle.tar.gz

root@kitploit:~
Требует root, как и `scan`. Читает фиксированный список файлов (`/etc/passwd`, `/etc/group`, `/etc/shadow`, `/etc/sudoers`, `/etc/ld.so.preload`, `/etc/environment`, `/etc/crontab`, `/etc/profile`, `/var/log/syslog`, `/var/log/messages`, `/var/log/audit/audit.log`) и выполняет фиксированный список команд (`ss -tunap`, `netstat -tunap`, `systemctl list-timers` в формах JSON и текстовой, а также `journalctl -o json` за последние 7 дней), хеширует каждый захваченный элемент и записывает всё вместе с `manifest.json` в архив `.tar.gz`. Захваченные файлы журналов и вывод journalctl — это то, что позволяет `analyze BUNDLE` построить реальную временную шкалу в офлайн-режиме. Если `--output` опущен, архив записывается в `./ubuntils-bundle-<UTC timestamp>.tar.gz` в текущем каталоге.

### `ubuntils analyze````bash
ubuntils analyze BUNDLE.tar.gz [--json] [--output FILE] [--config FILE] [--baseline FILE] [--rules FILE] [--since TIME]
ubuntils analyze --root /mnt/forensic-image [--json] [--output FILE] [--config FILE] [--baseline FILE] [--rules FILE] [--since TIME]

Принимает либо путь к bundle в качестве позиционного аргумента, либо --root PATH, указывающий на смонтированный образ / распакованное дерево файловой системы — но не оба одновременно. Запускает тот же самый движок обнаружения, пользовательские правила, allowlist и логику baseline, что и scan. Не требует root. Bundle распаковывается во временный приватный каталог, который удаляется сразу после завершения анализа (он может содержать /etc/shadow).

Покрытие различается между двумя офлайн-режимами, поскольку bundle несёт воспроизведённое захваченное состояние на момент collect, тогда как --root располагает только тем, что находится на смонтированной файловой системе:

  • analyze BUNDLE воспроизводит реальный вывод команд ss/systemctl list-timers/journalctl, захваченный во время collect, поэтому NetworkCollector и SystemdCollector формируют подлинные находки из этого снимка — они не пропускаются. Таймлайн строится из syslog/messages/audit.log/journalctl, захваченных bundle, поэтому он полностью заполнен, а находки получают реальную корреляцию related_events.
  • analyze --root PATH указывает на мёртвый смонтированный образ без живого процесса или состояния ядра для опроса, поэтому выполнение команд полностью отключено: NetworkCollector и SystemdCollector пропускаются, что фиксируется в scan_metadata.command_collectors_skipped. Таймлайн всё равно строится, но из статических лог-файлов, присутствующих на образе (/var/log/syslog, /var/log/messages, /var/log/audit/audit.log) — воспроизведение journald здесь недоступно, поскольку нет живого journalctl для опроса мёртвого образа.

См. Офлайн-анализ: collect и analyze для полного списка пробелов в офлайн-покрытии обнаружения.

Формат bundle

Bundle — это gzip-сжатый tarball, всё содержимое которого находится под префиксом bundle/:``` bundle/ ├── manifest.json ├── files/ │ ├── etc/passwd │ ├── etc/shadow │ ├── var/log/syslog │ └── ... # every captured file, path-flattened under files/ └── commands/ ├── ss.txt ├── netstat.txt ├── systemctl_list_timers_json.txt ├── systemctl_list_timers_text.txt └── journalctl.txt

root@kitploit:~
Схема `manifest.json`:

| Поле | Тип | Описание |
|---|---|---|
| `run_id` | string | UUID, генерируемый заново для каждого запуска `collect` |
| `host_id` | string | Зарезервировано для будущей корреляции между несколькими хостами; сейчас пусто |
| `hostname` | string | `socket.gethostname()` на момент сбора |
| `ubuntu_version` | string | Определённая строка версии Ubuntu |
| `collected_at_utc_start` / `collected_at_utc_end` | string (ISO 8601) | Границы времени настенных часов для запуска сбора |
| `tool_version` | string | Версия ubuntils, создавшая пакет |
| `files[]` | array | Одна запись на каждый захваченный файл: `source_path`, `bundle_path`, `sha256`, `size`, `mtime`, `ctime` (файл, отсутствующий или недоступный для чтения на исходном хосте, записывается с `sha256: ""`, `size: -1`, а не прерывает сбор) |
| `commands[]` | array | Одна запись на каждую захваченную команду: `name`, `argv`, `bundle_path`, `sha256`, `exit_code` |
| `bundle_sha256` | string | SHA-256 по остальной части манифеста (всё вышеперечисленное, канонически сериализованное) — якорь защиты от подмены для всего пакета |

### Целостность пакета в выводе JSON

`scan_metadata.bundle_integrity` в `analyze` сообщает одно из трёх значений:

- `"live"` — это сообщают `scan` и `analyze --root`; пакета для проверки нет.
- `"ok"` — `analyze BUNDLE` проверил `bundle_sha256` по манифесту и SHA-256 каждого захваченного файла по его содержимому в пакете; ничего не было изменено с момента записи `collect`.
- `"mismatch"` — дайджест манифеста, хеш захваченного файла или хеш вывода захваченной команды не совпал. Что-то в пакете было изменено, усечено или повреждено после сбора, и ничто производное от него не должно считаться чистым с точки зрения цепочки сохранности. `analyze` всё равно формирует отчёт, но выводит красное предупреждение в stderr, показывает баннер целостности в верхней части вкладки TUI Summary и **завершается со статусом 3**, чтобы скрипты не могли принять результаты подменённого пакета за достоверные.

### ⚠️ У офлайн-анализа есть реальные пробелы в обнаружении — прочитайте это, прежде чем полагаться на него

**Запуск `analyze` из пакета или с `--root` не имеет паритета обнаружения с живым `scan`.** Это не крайние случаи; это структурные ограничения статического офлайн-сбора, и они дают меньше (или ноль) находок для затронутых правил, а не ошибку. Там, где сборщик *знает*, что не смог заглянуть (неудачная команда, нечитаемый файл), это фиксируется в `scan_metadata.collectors_degraded` и отмечается на вкладке TUI Summary — но файл, который просто не был захвачен, выглядит так же, как файл, которого не существует. (Сама временная шкала больше *не* относится к этим пробелам: `analyze BUNDLE` воспроизводит захваченные syslog/messages/audit.log/journalctl на момент `collect`, а `analyze --root` читает статические лог-файлы, присутствующие на смонтированном образе, поэтому оба дают реальную временную шкалу и реальную корреляцию `related_events` — см. [`ubuntils analyze`](#ubuntils-analyze) выше.)

- **`PROCESS_MASQUERADE` и `PROCESS_SUSPICIOUS_CONNECTION` всегда будут сообщать ноль находок в офлайн-режиме.** Оба правила опираются на поле `exe` процесса, которое заполняется чтением цели симлинка `/proc/<pid>/exe` через источник артефактов (никогда не через собственный `/proc` аналитика). В пакете нет живого `/proc` для чтения, а `--root` указывает на смонтированное дерево файловой системы, где тоже нет `/proc` — в настоящее время нет механизма для захвата или восстановления разрешённой цели exe-симлинка офлайн, поэтому `exe` всегда пуст и оба правила никогда не срабатывают, независимо от того, что на самом деле находится на хосте.
- **Перечисление процессов офлайн вообще не происходит.** У `collect` нет шага захвата по каждому PID (`/proc/*/status`, `/proc/*/cmdline`), поэтому в пакете изначально нет процессов для анализа — это та же первопричина, что и в пункте выше, но со стороны сбора.
- **`CRON_TMP_PATH`, `SUDOERS_NOPASSWD` и `SSH_UNAUTHORIZED_KEY` ограничены или отсутствуют при анализе из пакета.** Список файлов `collect` статичен и не может раскрыть через glob `/etc/cron.d/*`, `/etc/sudoers.d/*`, `/etc/profile.d/*` или пользовательские `~/.ssh/authorized_keys` — захватываются только `/etc/crontab`, `/etc/sudoers` и `/etc/environment`/`/etc/profile`. (У `--root` против полного смонтированного дерева файловой системы этого пробела нет, поскольку реальные каталоги присутствуют на диске.) Когда `SSH_UNAUTHORIZED_KEY` или `SHELL_RC_MODIFICATION` *всё же* срабатывают (живой scan или `--root` при наличии реальных пользовательских каталогов), они теперь также оценивают уверенность по ctime и содержимому файла, а не только по mtime — см. [Оценка уверенности](#json-output) ниже. Это улучшает то, насколько следует доверять сработавшей находке; это не меняет того, срабатывает ли правило офлайн в принципе.
- **Обнаружение `SUSPICIOUS_SYSTEMD_TIMER` ослаблено для пакетов.** Юниты служб читаются напрямую из каталогов юнитов (`/etc/systemd/system`, `/usr/lib/systemd/system`, пользовательские `~/.config/systemd/user`, …), поэтому `--root` получает полное покрытие служб. Пакет же не захватывает эти каталоги: таймеры появляются из захваченного вывода `systemctl list-timers`, но `ExecStart` каждого таймера берётся из вызова `systemctl show` для каждого юнита, который `collect` не выполняет, поэтому правило не может оценить, что запускает таймер в пакете.

**Когда это важно:** если вы разбираете живой, доступный хост, используйте `sudo ubuntils scan` — у него полное покрытие обнаружения. Используйте `collect`/`analyze`, когда вам нужно собрать один раз и анализировать в другом месте, нужно анализировать без root или вы работаете с образом диска, где `scan` вообще не вариант — и относитесь к чистому результату `analyze` для правил выше как к «не проверено», а не «проверено и чисто».

---

## TUI

Запуск `sudo ubuntils scan` (без `--json`) открывает полноэкранный интерактивный TUI.

### Экран сканирования

Пока сборщики работают, ubuntils показывает живой контрольный список — по одной строке на сборщик. Каждая строка обновляется в реальном времени по мере завершения сборщика:```
Scanning system…

  ✓  Process
  ✓  Network
  ✓  Users
  ⠹  Cron
     Systemd
     SSH
     Sudoers
     Environment

✓ обозначает успех, ✗ — ошибку, спиннер обозначает активный сборщик, а пустые строки — ожидающие. После завершения всех сборщиков и завершения обнаружения и построения временной шкалы TUI автоматически переключается на экран результатов.

Экран результатов

Экран результатов имеет четыре вкладки, навигация по которым осуществляется цифровыми клавишами:

КлавишаВкладкаСодержимое
1СводкаСтатистика сканирования + основные находки с первого взгляда
2НаходкиПолный список находок с встроенными деталями и рекомендациями по устранению
3Временная шкалаХронологические коррелированные события журнала
4СтатистикаВерсия Ubuntu, архитектура, длительность, количество сборщиков

Нажмите q или Ctrl+C для выхода.

Вкладка «Сводка» (клавиша 1)

Отображает метаданные сканирования и основные находки на одном экране:``` Collectors: 8 run · 0 failed Findings: 2 HIGH · 1 MEDIUM · 0 LOW Timeline: 47 events Duration: 2.8s

● HIGH CRON_TMP_PATH /etc/cron.d/cleanup ● HIGH LD_PRELOAD_INJECT /home/alice/.bashrc ○ MED SSH_UNAUTHORIZED_KEY /home/bob/.ssh/authorized_keys

root@kitploit:~
В чистой системе эта вкладка отображает `System appears clean.`

### Вкладка Findings (клавиша `2`)

Прокручиваемый список всех находок, отсортированных HIGH → MEDIUM → LOW. При выборе находки (Enter или клавиши со стрелками) внизу раскрывается панель с подробностями, показывающая полное описание, путь к артефакту, исходное вызвавшее срабатывание значение и информацию об устранении.```
HIGH  CRON_TMP_PATH           /etc/cron.d/cleanup
HIGH  LD_PRELOAD_INJECT       /home/alice/.bashrc
MED   SSH_UNAUTHORIZED_KEY    /home/bob/.ssh/authorized_keys
───────────────────────────────────────────────────────
A cron job was found referencing /tmp, /var/tmp, or /dev/shm.
These directories are world-writable and commonly used as
attacker staging grounds.

Artifact:  /etc/cron.d/cleanup
Raw:       0 * * * * root /tmp/.update
Fix:       Will remove the offending cron entry from
           /etc/cron.d/cleanup after creating a timestamped backup.

R: remediate

Исправление в TUI

Для находок, для которых доступно автоматическое исправление, нажмите R, когда находка выбрана. Появляется модальное окно подтверждения:``` ┌─────────────────────────────────────────────────┐ │ Remediate CRON_TMP_PATH? │ │ │ │ Will remove the offending cron entry from │ │ /etc/cron.d/cleanup after creating a backup. │ │ Backup will be created at /var/backups/ubuntils/…│ │ │ │ Y: confirm Esc: cancel │ └─────────────────────────────────────────────────┘

root@kitploit:~
Нажмите `Y` для подтверждения. Модуль исправления запускается в фоновом потоке. По завершении строка находки в списке обновляется до `[fixed]`, а панель сведений отображает результат:```
✓ Remediated
Backup:    /var/backups/ubuntils/20260115_142201/etc_cron.d_cleanup
Rollback:  cp /var/backups/ubuntils/20260115_142201/etc_cron.d_cleanup /etc/cron.d/cleanup

При сбое панель сведений показывает ошибку. Резервная копия всегда создаётся до попытки внесения любых изменений.

Нажмите Esc, чтобы свернуть панель сведений.

Вкладка Timeline (клавиша 3)

Прокручиваемый хронологический список коррелированных событий журнала. Каждая строка показывает метку времени, источник и описание. События собираются из syslog, journald и auditd и дедуплицируются.

Вкладка Stats (клавиша 4)

Сводное представление сканирования: обнаруженная версия Ubuntu, архитектура, длительность сканирования, количество сборщиков и сбоев, а также количество находок по уровням серьёзности вместе с общим числом событий временной шкалы.


Что он обнаруживает

Rule IDSeverityRemediableWhat it checks
CRON_ROOT_EXECHIGHYesNon-root user crontabs running commands in root-owned paths or inlining sudo
CRON_TMP_PATHHIGHYes*Any cron job (including @reboot/@daily entries and scripts in /etc/cron.{hourly,daily,weekly,monthly}) referencing /tmp, /var/tmp, or /dev/shm. *Script lines are flag-only
LD_PRELOAD_INJECTHIGHYesAny entry in /etc/ld.so.preload (empty on stock Ubuntu), or LD_PRELOAD in any shell init file with any listed library outside /lib, /usr/lib, /lib64, /usr/lib64
SUSPICIOUS_SYSTEMD_TIMERHIGHNoSystemd timers and service units whose ExecStart references a world-writable directory or runs a binary not owned by root
SSH_UNAUTHORIZED_KEYMEDIUMYesauthorized_keys files modified within the last 7 days
USER_UID_ZEROHIGHNoAny account other than root with UID 0 (a hidden second superuser)
USER_EMPTY_PASSWORDHIGHNoA login-shell account whose /etc/shadow password field is empty (Ubuntu's default PAM nullok lets it log in with no password)
SUDOERS_NOPASSWDMEDIUMYes*NOPASSWD sudoers grants for users with UID ≥ 1000 and a login shell, directly or via a %group rule; included files are followed. *Group rules are flag-only (removing %sudo could remove all sudo access)
PROCESS_MASQUERADEMEDIUMNoProcesses whose name matches a known system binary but whose executable is outside the standard system directories (/usr/bin, /usr/sbin, /bin, /sbin, /usr/local/{bin,sbin}, /usr/lib, /usr/libexec, /lib, /snap)
PROCESS_SUSPICIOUS_CONNECTIONHIGH / MEDIUMNoProcesses holding an outbound connection whose executable is in a world-writable temp dir or deleted from disk (HIGH), or is outside the standard system directories or talks to a non-standard remote port (MEDIUM)
SHELL_RC_MODIFICATIONLOWNoShell init files (bashrc, profile, zshrc, etc.) modified within the last 48 hours for any user with a login shell
PACKAGE_TAMPEREDHIGH

Почему существует каждое правило

CRON_ROOT_EXEC — Пользовательские crontab-задания выполняются от имени владельца crontab. Запись, вызывающая sudo или интерпретатор, принадлежащий root, означает, что пользователь организовал выполнение кода с привилегиями root по расписанию, не нуждаясь в постоянном доступе к sudo. Это переживает смену пароля.

Пример находки:``` [HIGH] CRON_ROOT_EXEC Title: User crontab executing with sudo Artifact: /var/spool/cron/crontabs/alice Raw value: */5 * * * * sudo /usr/bin/python3 /tmp/beacon.py Remediation: available

root@kitploit:~
**CRON_TMP_PATH** — Каталоги, доступные для записи всем пользователям, такие как /tmp и /dev/shm, являются стандартными площадками для подготовки атак. Задание cron, указывающее туда, означает, что полезная нагрузка может быть подменена между запусками без изменения какого-либо постоянного пути. Это охватывает записи в стиле `@reboot`/`@daily` и скрипты в `/etc/cron.{hourly,daily,weekly,monthly}`; обнаружения в этих скриптах только помечаются флагом, поскольку удаление одной строки из shell-скрипта не является безопасным автоматическим исправлением.

*Пример обнаружения:*```
[HIGH] CRON_TMP_PATH
Title:         Cron job references writable temp directory
Artifact:      /etc/cron.d/cleanup
Raw value:     0 * * * * root /tmp/.update
Remediation:   available

LD_PRELOAD_INJECT — LD_PRELOAD заставляет динамический компоновщик загружать указанную разделяемую библиотеку раньше всех остальных, что позволяет перехватывать произвольные функции в любом динамически скомпонованном бинарном файле. Значение, указывающее за пределы стандартных путей к библиотекам, является почти несомненным индикатором руткита в пространстве пользователя; проверяется каждая библиотека в списке, разделённом пробелами или двоеточиями. /etc/ld.so.preload внедряется в каждый процесс и пуст в стандартной Ubuntu, поэтому любая запись там будет обнаружена — даже та, что подложена внутрь /lib, распространённый трюк руткитов. Исправление удаляет записи из /etc/ld.so.preload, а не закомментирует их, поскольку загрузчик не имеет синтаксиса комментариев в этом файле.

Пример обнаружения:``` [HIGH] LD_PRELOAD_INJECT Title: LD_PRELOAD set to non-standard library path Artifact: /home/alice/.bashrc Raw value: export LD_PRELOAD=/tmp/.libssl.so Remediation: available

root@kitploit:~
**SUSPICIOUS_SYSTEMD_TIMER** — Таймеры systemd более устойчивы и менее заметны для большинства специалистов по реагированию, чем задания cron. Таймер — или обычный юнит `.service`, который является более распространённым способом закрепления и вообще не требует таймера — чей ExecStart ссылается на временный каталог или запускает бинарный файл, не принадлежащий root, является признаком созданного злоумышленником закрепления. Юниты служб читаются напрямую из каталогов юнитов, включая пользовательские `~/.config/systemd/user`. Только пометка — удаление юнитов systemd требует человеческого суждения.

*Пример находки:*```
[HIGH] SUSPICIOUS_SYSTEMD_TIMER
Title:         Systemd timer ExecStart points to suspicious path
Artifact:      /etc/systemd/system/update-check.timer
Raw value:     ExecStart=/tmp/.sys/update
Remediation:   not available

SSH_UNAUTHORIZED_KEY — Недавно добавленный SSH-ключ предоставляет постоянный удалённый доступ независимо от паролей. Семидневное окно позволяет выявить недавние добавления, избегая шума от первоначальной настройки на старых системах. Примечание: правило использует mtime файла, который отражает время последней записи в файл authorized_keys, а не время вставки каждого отдельного ключа.

Пример обнаружения:``` [MEDIUM] SSH_UNAUTHORIZED_KEY Title: SSH authorized key added in last 7 days Artifact: /home/bob/.ssh/authorized_keys Raw value: ssh-rsa AAAAB3NzaC1... attacker@evil Remediation: available

root@kitploit:~
**SUDOERS_NOPASSWD** — беспарольный sudo для учётной записи обычного пользователя (UID ≥ 1000 с login shell) является вектором повышения привилегий, который сохраняется после удаления других механизмов персистентности. Легитимные разрешения NOPASSWD почти всегда предназначены для сервисных учётных записей без login shell. Групповые правила (`%sudo ALL=(ALL) NOPASSWD:ALL`) разрешаются в их участников, а файлы `#include`/`@includedir` обрабатываются. Находки по группам имеют только флаг: удаление правила вроде `%sudo` может лишить систему всех разрешений sudo.

*Пример находки:*```
[MEDIUM] SUDOERS_NOPASSWD
Title:         NOPASSWD sudo grant for regular user
Artifact:      /etc/sudoers.d/alice
Raw value:     alice ALL=(ALL) NOPASSWD: ALL
Remediation:   available

PROCESS_MASQUERADE — присвоение вредоносному бинарному файлу имени известного системного процесса (sshd, python3, bash) — это базовая техника уклонения от обнаружения в выводе ps. Это правило сопоставляет имя процесса из /proc/<pid>/status с разрешённым путём к исполняемому файлу из /proc/<pid>/exe. Стандартные расположения включают /usr/local/{bin,sbin}, /usr/lib, /usr/libexec и /snap, поэтому systemd (/usr/lib/systemd/systemd) и snap-пакеты не вызывают срабатывания. Только пометка — для завершения процесса требуется решение человека.

Пример обнаружения:``` [MEDIUM] PROCESS_MASQUERADE Title: Process masquerading as system binary Artifact: /proc/1337/exe Raw value: name=sshd, exe=/tmp/.sshd Remediation: not available

root@kitploit:~
**USER_UID_ZERO** — Только `root` должен иметь UID 0. Вторая учётная запись, сопоставленная с UID 0 (CIS Ubuntu Benchmark 6.2.x), является бэкдором с высокой степенью достоверности: она предоставляет полные права суперпользователя без изменения собственных учётных данных root и сохраняется после сброса пароля root. Практически нулевой уровень ложных срабатываний. Только пометка — удаление учётной записи с UID 0 требует решения человека.

*Пример обнаружения:*```
[HIGH] USER_UID_ZERO
Title:         Non-root account with UID 0
Artifact:      /etc/passwd
Raw value:     toor:x:0:0:...:/bin/bash
Remediation:   not available

USER_EMPTY_PASSWORD — Учётная запись, у которой поле пароля в /etc/shadow пустое, вообще не имеет пароля, и стандартный стек PAM в Ubuntu (pam_unix ... nullok) позволяет ей войти без пароля. Для учётной записи с login shell это открытая дверь. Только флаг — заблокируйте её с помощью passwd -l, пока ведёте расследование.

Пример находки:``` [HIGH] USER_EMPTY_PASSWORD Title: Login account with no password Artifact: /etc/shadow Raw value: eve:: Remediation: not available

root@kitploit:~
**PROCESS_SUSPICIOUS_CONNECTION** — Персистентность — это лишь половина картины; точка опоры, которая ни с чем не взаимодействует, редко представляет интерес. Это правило объединяет сборщики процессов и сетевых соединений по PID, так что помеченный процесс поступает вместе со своими текущими соединениями. Исполняемый файл, размещённый в `/tmp` и удерживающий установленный исходящий сокет, — это HIGH; легитимный бинарник, обращающийся к нестандартному удалённому порту, — это MEDIUM и заслуживает внимания. Это снимок текущего состояния, а не непрерывный мониторинг — маяк, который спит во время сканирования, не появится. Только флаг.

*Пример находки:*```
[HIGH] PROCESS_SUSPICIOUS_CONNECTION
Title:         Process with suspicious outbound connection
Artifact:      /proc/1337/exe
Raw value:     203.0.113.9:4444
Remediation:   not available

SHELL_RC_MODIFICATION — Файлы инициализации оболочки являются надёжным вектором персистентности, поскольку они выполняются при каждом входе пользователя в систему. Это правило выявляет недавние изменения для проверки человеком. Только пометка — содержимое shell RC требует прочтения перед принятием мер.

Пример обнаружения:``` [LOW] SHELL_RC_MODIFICATION Title: Shell init file recently modified Artifact: /root/.bashrc Raw value: mtime=2024-01-15 14:22:01 (6 hours ago) Remediation: not available

root@kitploit:~
**PACKAGE_TAMPERED** — Системные бинарные файлы и конфигурационные файлы являются основой доверия. Это правило обнаруживает случаи, когда файлы, принадлежащие пакетам, были изменены, удалены или имеют несоответствия содержимого/режима/размера, используя `dpkg --verify`. Правки только в conffile (ожидаемые локальные изменения конфигурации) исключаются из отчёта во избежание шума. Только флаг — вмешательство может быть законным (пользовательские локальные правки) или вредоносным (подмена файла); для решения требуется человеческое суждение.

*Пример обнаружения:*```
[HIGH] PACKAGE_TAMPERED
Title:         Package-owned file modified since installation
Artifact:      /usr/bin/sshd
Raw value:     ....5..T. (content and mtime differ)
Remediation:   not available

IMMUTABLE_FLAG_SET — Злоумышленники часто устанавливают флаг immutable (i) или флаг append-only (a) на файлы, чтобы предотвратить их изменение или удаление даже root-пользователем, в том числе чтобы скрыть следы вмешательства от дальнейших правок и ротации логов. Установка этих флагов на чувствительные системные файлы, такие как /etc/passwd, /etc/sudoers, /etc/pam.d/*, или на лог-файлы auth/syslog/wtmp/btmp, является сильным индикатором «закрепления» злоумышленника. Это правило обнаруживает флаги immutable и append-only через lsattr по указанному фиксированному списку чувствительных путей. Только флаг — изменения флагов требуют проверки человеком.

Пример находки:``` [MEDIUM] IMMUTABLE_FLAG_SET Title: Sensitive file has an unexpected chattr flag Artifact: /etc/ld.so.preload Raw value: ----i--------e--- Remediation: not available

root@kitploit:~
**PAM_BACKDOOR** — PAM (Pluggable Authentication Modules) и NSS (Name Service Switch) — это основные системы аутентификации и идентификации в Linux. Это правило НЕ выполняет обнаружение на основе mtime «был ли этот файл изменён» — оно сопоставляет шаблоны с *содержимым* файла: (1) буквальная строка `pam_permit.so` в любом файле /etc/pam.d/* (этот модуль всегда завершается успешно и является классическим бэкдором обхода аутентификации), или (2) модуль NSS, указанный в /etc/nsswitch.conf, которого нет во встроенном списке разрешённых ubuntils. **Примечание:** проверка NSS будет давать ложные срабатывания на хостах, присоединённых к домену/SSSD/LDAP/Winbind, использующих модуль вне встроенного списка разрешённых — по этой причине она намеренно оценивается с более низкой достоверностью, чем совпадение с pam_permit.so; используйте `--config`, чтобы добавить нераспознанные имена модулей в список разрешённых для вашей среды. Только флаг — изменения конфигурации аутентификации требуют тщательной проверки.

*Примеры находок:*```
[HIGH] PAM_BACKDOOR
Title:         PAM config unconditionally permits authentication
Artifact:      /etc/pam.d/sshd
Raw value:     auth required pam_permit.so
Remediation:   not available
root@kitploit:~
[HIGH] PAM_BACKDOOR
Title:         Unexpected NSS module in nsswitch.conf
Artifact:      /etc/nsswitch.conf
Raw value:     passwd: files evilmod
Remediation:   not available

KERNEL_MODULE_SUSPICIOUS — Модули ядра выполняются в ring 0 с неограниченным доступом. Злоумышленники часто загружают пользовательские модули ядра для руткитов, перехвата пакетов или сокрытия процессов. Это правило сравнивает текущие загруженные модули с небольшим списком разрешённых ожидаемых встроенных модулей (общих для большинства систем). Уровень серьёзности — LOW, поскольку этот список разрешённых намеренно узок. Примечание: хосты с большим количеством аппаратного обеспечения, драйверами GPU, Wi-Fi-картами или проприетарными драйверами, будут генерировать ложные срабатывания. Специалистам по реагированию следует добавить ожидаемые модули своего хоста через --config, добавив в список разрешённых по имени модуля (используется как artifact_path). Только флаг — исследование модулей ядра требует криминалистических инструментов и человеческой экспертизы.

Пример обнаружения:``` [LOW] KERNEL_MODULE_SUSPICIOUS Title: Loaded kernel module not in the expected set Artifact: implant_rootkit Raw value: {'name': 'implant_rootkit', 'size': '12288', 'used_by': []} Remediation: not available

root@kitploit:~
**SETUID_INVENTORY** — Бинарные файлы с битами setuid и setgid автоматически повышают привилегии при выполнении. Злоумышленники создают собственные setuid/setgid-бинарники для закрепления повышения привилегий, чаще всего вне стандартных системных каталогов бинарников (типичный путь установки, такой как /opt, собственный /home пользователя, /srv или временный каталог с правами на запись для всех). Это правило инвентаризирует setuid/setgid-бинарники с помощью `find -perm -4000 -o -perm -2000` по каталогам `/usr /bin /sbin /opt /home /srv /tmp /var/tmp /dev/shm` и отмечает любые за пределами известного базового набора легитимных системных утилит. Только пометка — неожиданные setuid/setgid-бинарники требуют расследования, но могут быть легитимными бинарниками, установленными приложением.

*Пример обнаружения:*```
[LOW] SETUID_INVENTORY
Title:         Unexpected setuid binary
Artifact:      /tmp/.hidden/backdoor
Raw value:     setuid
Remediation:   not available

Вывод JSON

--json записывает один объект JSON в stdout. Больше ничего не выводится.```json { "scan_metadata": { "tool_version": "2.1.0", "hostname": "web-01", "generated_at": "2026-06-10T08:22:03.114523+00:00", "ubuntu_version": "Ubuntu 22.04.3 LTS", "architecture": "x86_64", "duration_s": 2.84, "collector_failures": 0, "bundle_integrity": "live", "command_collectors_skipped": [], "collectors_degraded": {}, "rules_failed": [], "timeline_error": null, "suppressed_by_baseline": 1 }, "artifact_counts": { "ProcessCollector": 142, "NetworkCollector": 23, "UserCollector": 4, "CronCollector": 7, "SystemdCollector": 12, "SSHCollector": 3, "SudoersCollector": 5, "EnvironmentCollector": 18 }, "findings": [ { "rule_id": "CRON_TMP_PATH", "severity": "HIGH", "title": "Cron job references writable temp directory", "description": "A cron job was found referencing /tmp, /var/tmp, or /dev/shm. These directories are world-writable and commonly used as attacker staging grounds.", "artifact_path": "/etc/cron.d/cleanup", "raw_value": "0 * * * * root /tmp/.update", "remediation_available": true, "remediation_description": "Will remove the offending cron entry from /etc/cron.d/cleanup after creating a timestamped backup.", "related_events": [ { "timestamp": "2024-01-15T08:20:00+00:00", "source": "syslog", "description": "CRON[2841]: (root) CMD (/tmp/.update)" } ], "confidence": 75, "confidence_band": "HIGH", "signals": [ {"name": "timeline_corroboration", "weight": 25, "detail": "1 nearby timeline event(s)"} ] }, { "rule_id": "PROCESS_MASQUERADE", "severity": "MEDIUM", "title": "Process masquerading as system binary", "description": "Process 'sshd' (pid=1337) has exe path outside standard binary directories: /tmp/.sshd", "artifact_path": "/proc/1337/exe", "raw_value": "/tmp/.sshd", "remediation_available": false, "guided_remediation": "Confirm pid 1337 is malicious (ls -l /proc/1337/exe, cat /proc/1337/cmdline), then terminate it: kill -9 1337.", "confidence": 50, "confidence_band": "MEDIUM", "signals": [] } ], "timeline": [ { "timestamp": "2024-01-15T08:22:01+00:00", "source": "syslog", "description": "sshd: Accepted publickey for alice from 10.0.0.42 port 52341" } ], "report_sha256": "a3f1c9…(64 hex chars)" }

root@kitploit:~
`remediation_results` появляется как дополнительный ключ верхнего уровня только при передаче `--remediate`. `report_sha256` присутствует всегда и вычисляется по остальной части документа. `scan_metadata.bundle_integrity` имеет значение `"live"` для `scan` и `analyze --root`, `"ok"` для проверенного бандла, переданного в `analyze`, и `"mismatch"`, если содержимое бандла не соответствует его манифесту — см. [Bundle integrity in JSON output](#bundle-integrity-in-json-output). `scan_metadata.command_collectors_skipped` перечисляет любые коллекторы на основе команд (`NetworkCollector`, `SystemdCollector`, `PackageCollector`, `KernelCollector`), пропущенные при запуске с `--root` — всегда пусто для `scan` и `analyze BUNDLE`. `scan_metadata.suppressed_by_baseline` — это количество находок, удалённых из этого отчёта файлом `--baseline` — см. [Known-good baselining](#known-good-baselining---baseline). `scan_metadata.collectors_degraded` сопоставляет имя коллектора с причинами неполноты его данных (команда, завершившаяся ошибкой или по таймауту, нечитаемый файл, пропущенная некорректная строка), `rules_failed` перечисляет любое правило обнаружения, которое аварийно завершилось, а `timeline_error` устанавливается, если временную шкалу не удалось построить. Все три пусты при нормальном запуске. Проверяйте их, прежде чем считать пустой список находок признаком «чисто».

`related_events` и `guided_remediation` появляются у находки только при наличии содержимого. `related_events` содержит до пяти событий временной шкалы, сопоставленных находке по пути артефакта и ключевым словам правила, в порядке от самых свежих — это вспомогательное средство для выявления, а не утверждение о причинно-следственной связи. `guided_remediation` — это проверенная последовательность команд для ручного выполнения; ubuntils никогда её не выполняет.

### Оценка уверенности

Каждая находка несёт оценку `confidence` (0–100, по умолчанию 50) и `confidence_band` (`HIGH` ≥ 75, `MEDIUM` ≥ 40, `LOW` ниже этого), а также список `signals`, показывающий, как именно была получена эта оценка — каждая запись имеет вид `{"name", "weight", "detail"}`, так что оценка всегда объяснима, никогда не является чёрным ящиком. Сигналы складываются поверх базовой уверенности 50 и применяются тем правилом или этапом конвейера, который их породил:

- Правила обнаружения применяют свои сигналы в момент обнаружения — например, `SSH_UNAUTHORIZED_KEY` и `SHELL_RC_MODIFICATION` добавляют `content_match` (+30), когда содержимое артефакта соответствует известному опасному шаблону (опасная опция SSH-ключа; строка curl/wget-to-shell или base64-decode в RC-файле оболочки), `ctime_corroborates_mtime` (+20), когда ctime файла также попадает в окно обнаружения (сложнее подделать, чем один mtime), или `mtime_only` (−20), когда свежесть — *единственный* сигнал и ctime его не подтверждает — намёк на то, что mtime мог быть изменён на более ранний.
- Конвейер применяет `timeline_corroboration` (+25) после корреляции находка↔временная шкала, когда у находки есть одно или несколько `related_events`.

Находка с диапазоном `LOW` не отбрасывается и не скрывается — она по-прежнему появляется в списке находок и в JSON-выводе точно так же, как любая другая — но диапазон говорит вам, сколько веса ей придавать перед дальнейшим расследованием. Это заменяет старую эвристику только по mtime для `SSH_UNAUTHORIZED_KEY`/`SHELL_RC_MODIFICATION`, где устаревший, но законно изменённый файл (например, инструмент управления конфигурацией, перезаписывающий `.bashrc` при каждом запуске) выглядел идентично настоящему новому бэкдору.

**Известное ограничение:** сегодня активны только сигналы на основе шаблонов содержимого и ctime. Сигналы на основе владельца/отпечатка — неизвестный отпечаток SSH-ключа, опция ограничения `from=` у ключа или несоответствие владельца/режима RC-файла (сигнал `ownership_anomaly`) — пока не реализованы. Это отложенный пробел в покрытии, отслеживаемый для будущего релиза, а не то, что учитывает текущая оценка уверенности.

---

## Исправление

Пять из шестнадцати правил обнаружения имеют автоматическое исправление: `CRON_ROOT_EXEC`, `CRON_TMP_PATH`, `LD_PRELOAD_INJECT`, `SSH_UNAUTHORIZED_KEY` и `SUDOERS_NOPASSWD`. Остальные только помечают и никогда не будут исправляться автоматически, потому что для безопасных действий с ними сначала нужен взгляд человека.

### Управляемое исправление

`SUSPICIOUS_SYSTEMD_TIMER`, `PROCESS_MASQUERADE` и `SHELL_RC_MODIFICATION` несут строку `guided_remediation`: точные команды для выполнения после подтверждения находки — `systemctl disable --now <unit>`, `kill -9 <pid>` или просмотр и откат RC-файла. Она отображается в панели деталей TUI и в JSON. ubuntils никогда не выполняет её за вас; эти правила по замыслу остаются вне охвата `--remediate --confirm`.

### В TUI

Выберите любую находку с исправлением на вкладке Findings, затем нажмите `R`. Модальное окно подтверждения показывает планируемое действие. Нажмите `Y`, чтобы применить его — модуль исправления работает в фоновом потоке, поэтому TUI остаётся отзывчивым. Строка находки обновляется до `[fixed]` по завершении, с путём резервной копии и точной командой отката, показанными прямо в строке.

### Из CLI

`--remediate` без `--confirm` — это безопасный пробный запуск: резервные копии создаются и валидация выполняется, но изменения не применяются. Передайте оба флага, чтобы действительно внести изменения. В этом режиме конвейер запускается до старта TUI, а вкладка Summary перечисляет каждый результат исправления с его путём резервной копии и командой отката.

`--remediate --confirm` действует только на находки с оценкой уверенности не ниже 40 (диапазон MEDIUM) — `SSH_UNAUTHORIZED_KEY` с низкой уверенностью и только по mtime помечается как `SKIPPED`, а не удаляется его ключ. Настройте порог с помощью `--min-confidence N`.```bash
sudo ubuntils scan --remediate          # dry run
sudo ubuntils scan --remediate --confirm # apply changes, then open TUI
sudo ubuntils scan --remediate --confirm --min-confidence 75  # only HIGH-confidence findings

Меры защиты

Каждое исправление следует одному и тому же шаблону независимо от того, как оно запущено:

  1. Проверить, является ли путь артефакта символической ссылкой — если да, отказаться (предотвращает запись root через символические ссылки, контролируемые злоумышленником)
  2. Создать резервную копию с отметкой времени в /var/backups/ubuntils/YYYYMMDD_HHMMSS/ с правами 0700
  3. Проверить текущее состояние (точная строка всё ещё должна присутствовать)
  4. Применить минимально возможное изменение — записи cron и ключи удаляются построчно; строки LD_PRELOAD в файлах инициализации оболочки закомментируются; записи в /etc/ld.so.preload удаляются (у загрузчика там нет синтаксиса комментариев, поэтому закомментированная запись всё равно загрузилась бы). Для sudoers отредактированное содержимое проверяется с помощью visudo -cf на временной копии до того, как будет затронут реальный файл
  5. Записать атомарно — новое содержимое записывается во временный файл рядом с оригиналом (с теми же правами и владельцем), выполняется fsync, затем переименование поверх оригинала, так что сбой в середине записи не может оставить усечённый /etc/sudoers
  6. Проверить, что точная строка исчезла

Если какой-либо шаг завершается неудачей, исправление немедленно останавливается, система остаётся без изменений, и полная ошибка сообщается вместе с путём резервной копии и командой отката. Доступ sudo защищён двумя способами: правила NOPASSWD для %group (например, %sudo) только помечаются флагом и никогда не удаляются автоматически, а модуль исправления sudoers отказывается удалять последнее правило из основного файла sudoers.


Интеграция с Wazuh

ubuntils создан для точечной диагностики на одном хосте — вы запускаете его, когда уже подозреваете, что что-то не так, и он никогда не отправляет данные наружу и не продолжает наблюдение после завершения сканирования. Это сделано намеренно, но это также означает, что находка от ubuntils живёт только в том одном отчёте, если что-то не передаст её дальше. Большинство команд, использующих Ubuntu в любом масштабе, уже имеют SIEM, выполняющий непрерывную часть обнаружения, поэтому вместо того, чтобы превращать ubuntils в собственный долгоработающий агент мониторинга, он передаёт свои находки тому, который вы, вероятно, уже используете: Wazuh.

Если на хосте присутствует агент Wazuh (/var/ossec/bin/wazuh-agentd или /var/ossec/etc/ossec.conf существует), ubuntils scan (если не запущен с --no-wazuh) добавляет каждую находку одной строкой JSON в /var/log/ubuntils/wazuh-alerts.json, чтобы агент её подхватил — это чистый форвардер, а не модуль Wazuh: никаких сетевых вызовов, никаких API-ключей, ничего кроме тех же локальных записей артефактов, которые ubuntils уже делает — хотя агент, конечно, отправит эти строки с хоста на свой менеджер; в этом и смысл. Он обнаруживается автоматически без необходимости флага (используйте --no-wazuh, чтобы исключить запуск), поэтому скриптовый или запланированный ubuntils scan на парке хостов, зарегистрированных в агенте, начинает питать SIEM немедленно без дополнительной настройки. Это никогда не происходит во время офлайн-ubuntils analyze (bundle или --root), поскольку эти находки описывают другой хост, отличный от того, на котором работает локальный агент Wazuh — пересылка находок из bundle собственному агенту аналитика приписала бы их не той машине.

Цель — встроить ubuntils в существующий конвейер оповещений/эскалации вместо того, чтобы просить реагирующего нянчиться со вторым инструментом: как только приведённые ниже примеры правил загружены, находка ubuntils с уровнем HIGH (новая учётная запись с UID 0, руткит LD_PRELOAD, бэкдор PAM) появляется как обычное оповещение Wazuh, наследует любую маршрутизацию уведомлений, уже настроенную в менеджере, и находится рядом со всеми другими сигналами в одной временной шкале вместо отдельного JSON-файла, который кто-то должен не забыть проверить.

Чтобы Wazuh разбирал и оповещал об этих находках, скопируйте примеры правил из examples/wazuh/ на ваш менеджер Wazuh и добавьте блок <localfile> из examples/wazuh/ossec_localfile_snippet.xml в /var/ossec/etc/ossec.conf агента. Установка пользовательского декодера не требуется: localfile настроен с log_format json, поэтому встроенный JSON-декодер Wazuh разбирает каждую строку и сопоставляет каждый ключ верхнего уровня JSON k с data.k, с чем local_rules.xml сопоставляется напрямую.

  1. examples/wazuh/local_rules.xml → /var/ossec/etc/rules/ менеджера
  2. Блок <localfile> из examples/wazuh/ossec_localfile_snippet.xml → /var/ossec/etc/ossec.conf агента
  3. Перезапустите оба: systemctl restart wazuh-manager (менеджер), systemctl restart wazuh-agent (хост агента)

Это только примеры шаблонов, предоставленные как отправная точка — они не тестировались на работающем менеджере Wazuh и должны быть проверены в непроизводственной среде, прежде чем полагаться на них.

Схема JSON для каждой строки:

ПолеТипОписание
timestampstring (ISO 8601)Когда находка была переслана
hostnamestringПросканированный хост
rule_idstringСоответствует ID правила обнаружения ubuntils (см. таблицу правил обнаружения выше)
severitystringHIGH | MEDIUM | LOW
titlestringКраткое понятное название
descriptionstringПолное описание находки
artifact_pathstringПуть к файлу/ресурсу, где была найдена проблема
raw_valuestringНеобработанная строка/значение, вызвавшее срабатывание правила
remediation_availableboolЕсть ли у ubuntils модуль исправления для этого правила
related_eventsarray (опционально)Связанные события временной шкалы, если есть

Коллекторы

КоллекторСобираемые артефакты
ProcessCollectorЗапущенные процессы из /proc и вывода ps
NetworkCollectorОткрытые соединения и слушатели из ss/netstat
UserCollector/etc/passwd, /etc/shadow, /etc/group
CronCollectorКаталоги /etc/cron* и /var/spool/cron/crontabs/*
SystemdCollectorВывод systemctl list-timers и list-units
SSHCollector~/.ssh/authorized_keys для всех пользователей
SudoersCollector/etc/sudoers и все файлы в /etc/sudoers.d/
EnvironmentCollector/etc/environment, /etc/profile.d/*, файлы инициализации оболочки пользователя
PackageCollectorЦелостность системных пакетов через dpkg --verify, атрибуты неизменяемого флага через lsattr и бинарные файлы setuid/setgid через find
PamCollectorФайлы /etc/pam.d/* и /etc/nsswitch.conf
KernelCollectorЗагруженные модули ядра через lsmod

Зависимости коллекторов

PackageCollector требует три стандартных инструмента Ubuntu на живом хосте (dpkg, lsattr, find — все присутствуют в стандартных установках Ubuntu). Если какая-либо команда недоступна, PackageCollector корректно выдаёт пустые данные для этой части вместо аварийного завершения. Офлайн-анализ (analyze BUNDLE) воспроизводит захваченный вывод команд со времени collect, поэтому доступность команд на хосте анализатора не требуется.

Сканирование setuid/setgid через find передаёт -xdev, чтобы оставаться ограниченным — оно не спускается в отдельно смонтированные файловые системы (отдельное монтирование под /opt, смонтированный по NFS /home и т. д.). Это намеренный компромисс между временем выполнения и покрытием: без -xdev сканирование могло бы зависнуть, сканируя сетевые монтирования или виртуальные файловые системы. Если в вашей среде эти пути смонтированы на отдельных файловых системах, учтите, что они не будут просканированы.

dpkg --verify и сканирование setuid/setgid через find используют щедрые нестандартные тайм-ауты (10 минут и 5 минут соответственно, см. ubuntils/collectors/packages.py), поскольку оба могут законно работать значительно дольше стандартного для библиотеки значения в 30 секунд на реальном хосте с большой базой пакетов или деревом файловой системы; ubuntils collect использует те же тайм-ауты при захвате этих команд в bundle.


Совместимость

Поддерживается
Ubuntu20.04, 22.04, 24.04
Архитектураamd64, arm64
Python3.9+
ПривилегииТребуется root для полного доступа к артефактам

Запуск без root даёт частичное сканирование с предупреждениями. Критические пути, такие как /etc/shadow, защищённые каталоги crontab и некоторые записи /proc, будут пропущены.


План развития

v1.0.0

  • Все 8 коллекторов
  • Все 8 правил обнаружения
  • Построитель временной шкалы (syslog, journald, auditd)
  • Экран прогресса живого сканирования с ✓/✗ по каждому коллектору
  • Интерактивный четырёхвкладочный TUI (Summary / Findings / Timeline / Stats)
  • Исправление внутри TUI с модальным окном подтверждения и фоновым воркером
  • Режим вывода JSON
  • Исправление через CLI для 5 правил с резервным копированием, откатом и защитой от символических ссылок
  • Поддержка Ubuntu 20.04/22.04/24.04
  • 240 тестов при 90% покрытии

v1.1.0

  • Список разрешённых ложных срабатываний по id правила или пути (--config)
  • --output FILE для прямой записи отчётов
  • Оконное ограничение временной шкалы через --since
  • Отчёты с защитой от подделки (report_sha256, hostname, timestamp)
  • Правило обнаружения USER_UID_ZERO

v1.5.0

  • Пользовательские правила обнаружения по сопоставлению с шаблоном через YAML (--rules)
  • PROCESS_SUSPICIOUS_CONNECTION — корреляция процесс↔сеть по PID
  • Автоматическая корреляция находок↔временной шкалы (related_events)
  • Управляемое исправление для трёх правил, требующих суждения
  • 282 теста при 92% покрытии

Поиск хешей в VirusTotal и экспорт IOC в MISP были исключены из этого релиза. VirusTotal отвечает только для известных хешей — случай, который уже покрывает rkhunter, и противоположность пробелу в новых техниках, на который нацелен ubuntils — и обе функции поместили бы сетевой вызов внутрь инструмента, ценность которого основана на их отсутствии. Сам ubuntils по-прежнему не делает сетевых вызовов (см. интеграцию с Wazuh для единственного отключаемого способа, которым находки могут покинуть хост через локальный агент).

v2.0.0 — офлайн-разделение collect/analyze

  • ubuntils collect — получает защищённый от подделки bundle (manifest.json + хешированные файлы/команды) с живого хоста, без обнаружения
  • ubuntils analyze (BUNDLE | --root PATH) — запускает тот же конвейер обнаружения/временной шкалы, что и scan, против bundle или смонтированного образа, root не требуется
  • bundle_integrity (live/ok/mismatch) отображается в scan_metadata
  • Документированные пробелы в покрытии обнаружения в офлайн-режиме (PROCESS_MASQUERADE, PROCESS_SUSPICIOUS_CONNECTION и сниженное покрытие для glob-путей cron/sudoers/SSH и ExecStart таймеров systemd)
  • Достоверное обнаружение: оценка уверенности (confidence/confidence_band/signals), подавление через --baseline, замена эвристик только по mtime в SSH_UNAUTHORIZED_KEY/SHELL_RC_MODIFICATION на сигналы ctime + содержимого, и реальная офлайн-временная шкала как для analyze BUNDLE, так и для analyze --root
  • Пакет покрытия: PACKAGE_TAMPERED, IMMUTABLE_FLAG_SET, PAM_BACKDOOR, KERNEL_MODULE_SUSPICIOUS, SETUID_INVENTORY (через PackageCollector, PamCollector, KernelCollector; все по дизайну только помечаются флагом)
  • 400 тестов при 93.79% покрытии

v2.1.0 — пересылка в SIEM

  • Находки живого ubuntils scan пересылаются локальному агенту Wazuh в виде JSONL, обнаруживается автоматически (флаг не требуется)
  • Пример декодера/правил Wazuh и фрагмент <localfile> для ossec.conf (examples/wazuh/)
  • Пересылка намеренно ограничена только живым scan — никогда не срабатывает во время офлайн-analyze, поскольку bundle или образ описывает другой хост, отличный от того, на котором работает агент
  • --no-wazuh для исключения сканирования из пересылки

v2.1.0 — усиление защиты (аудит всей кодовой базы)

  • Безопасность: повторный запуск sudo больше не передаёт PATH вызывающего, и команды разрешаются по фиксированному безопасному пути; правки sudoers проверяются через visudo до изменения файла; атомарные записи исправлений; безопасный для символических ссылок вывод отчётов/bundle; извлечённые bundle удаляются после analyze
  • Покрытие обнаружения: разбирается /etc/ld.so.preload, записи cron @reboot/@daily и скрипты /etc/cron.{hourly,daily,weekly,monthly}, юниты systemd .service и бинарные файлы ExecStart, не принадлежащие root, правила sudoers %group и #include/@includedir, каждый элемент списка LD_PRELOAD
  • Новое правило USER_EMPTY_PASSWORD (учётная запись для входа без пароля)
  • Меньше ложных срабатываний: проверки путей с ограничением по разделителям, различение setuid и setgid, демоны snap//usr/lib считаются стандартными, KERNEL_MODULE_SUSPICIOUS понижен до LOW, одна находка NSS на модуль
  • Честные отчёты: неудавшиеся правила и деградировавшие коллекторы записываются в scan_metadata и TUI; сбой временной шкалы больше не отбрасывает находки; подделанные bundle предупреждают и завершаются с кодом 3; год/часовой пояс syslog обрабатываются корректно
  • Более безопасное исправление: порог --min-confidence (по умолчанию 40), результаты показываются в TUI после scan --remediate
  • 444 теста при 94.29% покрытии

v3.0.0 / v4.0.0 (исследовательские)

  • Веб-панель для диагностики нескольких хостов
  • Поддержка macOS

Участие в разработке

Наиболее полезными вкладами прямо сейчас являются новые правила обнаружения (добавляются как отдельные функции в detectors/rules.py с соответствующим тестом), дополнительные коллекторы для ещё не охваченных типов артефактов, модули исправления для SUSPICIOUS_SYSTEMD_TIMER и SHELL_RC_MODIFICATION (оба сейчас по дизайну только помечаются флагом, но могут существовать безопасные пути автоисправления), тестовые случаи для граничных случаев на конкретных конфигурациях Ubuntu и улучшения документации.

Откройте issue перед началом крупного вклада, чтобы избежать дублирования работы.


Лицензия

MIT


Автор

Создан Asmit — BTech Computer Science, PES University, Бенгалуру. Инструмент появился из разочарования тем, сколько времени занимает ручная диагностика Ubuntu по сравнению с тем, что может автоматизировать хорошо проработанный скрипт.

Скачать инструмент
No
System-owned package files modified, missing, or whose content/mode/size mismatches the package manifest (via dpkg --verify)
IMMUTABLE_FLAG_SETMEDIUMNoImmutable (i) or append-only (a) flags set on sensitive files like /etc/passwd, /etc/sudoers, or /etc/pam.d/* (detected via lsattr)
PAM_BACKDOORHIGHNoA literal pam_permit.so line in any /etc/pam.d/* file, or an NSS module in /etc/nsswitch.conf outside an allowlist (files/sss/ldap/winbind/...)
KERNEL_MODULE_SUSPICIOUSLOWNoLoaded kernel modules outside an allowlist of common built-in modules — note: hardware-heavy hosts (GPUs, Wi-Fi cards, proprietary drivers) will see false positives; add expected modules via --config
SETUID_INVENTORYLOWNoUnexpected setuid or setgid binaries outside a known baseline set (the two bits are checked and reported separately)