Двенадцать следов взлома Zimbra, которые видно в логах

В юрфирме в Химках, 44 рабочих места, меня позвали к «тормозящей» почте. Веб-клиент открывался долго, письма подвисали — обычная заявка на обслуживание. Через десять минут грепа по логам я смотрел на чужой процесс с аптаймом в три недели. Это был май 2025-го. С тех пор я собрал в один список двенадцать признаков, по которым компрометация Zimbra видна в стандартных логах — и рядом честно отметил, какие из них дают ложные срабатывания, чтобы вы не подняли тревогу на пустом месте.

Как одна заявка на «тормоза» превратилась в форензику

Юрист жаловался на скорость: письмо открывается пять-семь секунд, поиск по ящику думает минуту. В такой ситуации я обычно смотрю IOwait и буфер InnoDB — и в девяти случаях это они. Здесь IOwait действительно был высокий. Но источник оказался не там, где я ждал.

Первое, что я всегда делаю на незнакомом сервере, — смотрю, кто ест CPU, и сверяю процессы со списком служб Zimbra. Тут и вылез чужой:

ps -eo pid,etime,pcpu,user,comm --sort=-pcpu | head
#   PID   ELAPSED %CPU USER    COMMAND
# 21883  21-04:12 690  zimbra  kdevtmpfsi   <- аптайм 21 день, 690% CPU

Аптайм 21 день. Процесс, которого нет в Zimbra. Дальше я уже не чинил тормоза — я разбирал взлом, а тормоза оказались его побочкой: майнер забивал CPU, оттого и IOwait, оттого и «медленная почта». Ложная версия про InnoDB отпала за минуту.

Ниже — двенадцать признаков, которые я с тех пор проверяю на каждом сервере, взятом на обслуживание. Все ищутся грепом по стандартным логам. Ни один не требует спецсофта.

Признаки 1–4: нагрузка, файлы, соединения, автозапуск

1. Аномальная загрузка CPU в нерабочие часы. Не «странный трафик», как принято думать, а именно ровное плато CPU ночью и в выходные. Это самый частый первый симптом. Майнеру не нужен трафик — ему нужны ваши ядра.

2. Свежие файлы в /opt/zimbra и /tmp позже даты последнего апгрейда. Логика простая: после апгрейда легитимные файлы Zimbra не меняются сами. Всё, что новее, — подозрительно.

# файлы, изменённые позже установки последнего патча
find /opt/zimbra /tmp /dev/shm -type f -newermt '2025-04-01' \
  -not -path '*/log/*' -printf '%TY-%Tm-%Td %p\n' 2>/dev/null | sort

3. Исходящие соединения от процессов не из списка служб Zimbra. ss -tnp покажет установленные сессии; если сокет держит процесс, которого нет среди служб Zimbra, — это разговор с C2 или пулом майнинга.

4. Свежие systemd-юниты и cron-задачи от root, не совпадающие с датой установки системы. Персистентность живёт здесь. Юнит с общим именем вроде «System Logger» и бинарём в /lib/udev/ — классическая маскировка.

ss -tnp | grep ESTAB | grep -v -E 'zimbra|mysqld|slapd'
systemctl list-unit-files --state=enabled | grep -vi zimbra
crontab -l -u root; ls -la /etc/cron.d

Признаки 5–8: почта как оружие — релей, base64, чужие адреса

5. Исходящая очередь с адресами, которых нет в вашем домене. Если mailq полон писем от отправителей, которых у вас не существует, ваш сервер используют как открытый релей для спама. Это бьёт по репутации домена сильнее простоя.

mailq | head -40
qshape deferred | head          # для каких доменов копится
grep 'reject' /var/log/maillog | tail

6. base64-строки в полях заголовков писем в maillog. Это след эксплуатации postjournal: атакующие прятали команды в закодированных полях письма. Длинные base64-блоки там, где должен быть обычный заголовок, — красный флаг. Ищутся так:

# длинные base64-куски в адресных полях транспортного лога
grep -oE 'to=<[^>]*[A-Za-z0-9+/]{40,}={0,2}[^>]*>' /var/log/maillog | head

# что вообще ходило через сам postjournal
grep -E 'postjournal|:10027' /var/log/maillog | tail -20

Оговорюсь сразу, потому что на этом обжигаются: base64 в письмах встречается и совершенно законно. Тема письма на кириллице приезжает как =?UTF-8?B?...?=, и это тоже base64. Смотреть надо не на кодировку саму по себе, а на её место: закодированный кусок в адресном поле, в to= или from=, — вот это ненормально. В теме — обычный вторник.

7. Подставные Gmail-адреса в подозрительных письмах. В известных кампаниях против ZCS команды доставлялись письмами с фальшивых Gmail-адресов. Само по себе письмо с gmail — норма; в связке с base64-полями и следующим пунктом — уже нет.

8. Всплеск REJECT/relay-попыток в maillog. Резкий рост отказов на relay или попыток отправки на внешние домены с самого сервера — сигнал, что кто-то тестирует ваш MTA как релей или уже гонит через него. Важна не абсолютная цифра, а форма графика: пара сотен reject в сутки — это фон, который есть у всех, а вот скачок в десять раз за один день по сравнению с прошлой неделей значит, что вами кто-то предметно занялся. Поэтому считать надо по дням, а не одним числом за весь файл:

grep 'reject' /var/log/maillog | awk '{print $1" "$2}' | uniq -c | tail -14

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

Признаки 9–12: вебшелл, DOS-фильтр, странные логины, аптайм

9. Обращения к незнакомым .jsp в access-логах. Вебшелл в Zimbra — это .jsp-файл с параметром-командой. Запросы вида w.jsp?k=...&c= к файлам, которых нет в штатной поставке, — прямое попадание.

grep -E '\.jsp\?.*(cmd|c=|exec|k=)' /opt/zimbra/log/access_log* | tail
grep -rE 'Runtime|ProcessBuilder' /opt/zimbra/jetty*/webapps 2>/dev/null | head

10. Срабатывания DOS-фильтра по IP в mailbox.log. Строка Access to IP suspended, for repeated failed login — встроенная защита Zimbra заблокировала IP после серии неудачных входов. Одна-две — норма, шквал с одного адреса — брутфорс.

11. Успешные логины в неурочное время и из чужой географии. Вход администратора в 03:40 с адреса, которого раньше не было, — повод проверить. Ищется по mailbox.log грепом на oip= и статус аутентификации.

12. Процесс с аптаймом больше, чем время с последнего рестарта Zimbra. Тот самый признак из Химок. Если чужой процесс живёт дольше, чем сами службы почты, — он не часть Zimbra, он поверх неё.

grep -E 'AuthRequest|oip=' /opt/zimbra/log/mailbox.log | grep -i success | tail
grep 'suspended' /opt/zimbra/log/mailbox.log | awk '{print $NF}' | sort | uniq -c

Проверьте у себя за 2 минуты

Не надо гонять все двенадцать проверок сразу. Вот минимальный набор, который за пару минут отделит «чисто» от «надо копать глубже». От root, только чтение.

# кто ест CPU и не из Zimbra ли это
ps -eo pid,etime,pcpu,user,comm --sort=-pcpu | head

# исходящие соединения от нештатных процессов
ss -tnp | grep ESTAB | grep -v -E 'zimbra|mysqld|slapd|nginx'

# чужие письма в очереди (сервер как релей)
mailq | grep -c '@' ; qshape deferred | head
Что увиделиТрактовкаЛожное срабатывание?
Процесс не из Zimbra, аптайм больше, чем у mailboxdПочти наверняка компрометацияКрайне редко
Исходящие соединения от нештатного процессаРазговор с C2 или пуломИногда — агент мониторинга; сверьте, что за процесс
Очередь полна писем от несуществующих отправителейОткрытый релейПроверьте бэкскаттер: bounce-письма выглядят похоже
Шквал DOS-suspended с одного IPБрутфорсЧасто ложь: забытый клиент со старым паролем даёт то же

Обратите внимание на последний столбец. Половина работы — не найти совпадение, а отсеять ложное. Об этом отдельный раздел, потому что именно здесь новичок либо паникует зря, либо, наоборот, списывает реальный след на «наверное, ерунда».

Где эти признаки врут — и как не поднять тревогу зря

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

DOS-фильтр по IP (признак 10). Самый частый ложняк. Забытый на телефоне почтовый клиент со сменённым паролем долбится каждые пять минут и исправно ловит suspended. Выглядит как брутфорс, а это ваш же уволившийся сотрудник. Отличие: у брутфорса адреса меняются и меняются логины-цели; у забытого клиента — один IP и один логин.

Чужие адреса в очереди (признак 5). Бэкскаттер — обратные отбойники на подделанного вас — заполняет очередь письмами, которые выглядят как чужие. Это не всегда релей. Смотреть надо, кто отправитель по факту (ваш сервер или внешний) и куда идёт письмо.

Письма с Gmail (признак 7). Сам по себе ноль информации: вам пишут с gmail постоянно. Признак работает только в связке — gmail-адрес плюс base64 в заголовках плюс временная близость к появлению чужого процесса.

Свежие файлы в /opt/zimbra (признак 2). Логи и индексы меняются постоянно — их надо исключать из поиска, иначе утонете в шуме. Именно поэтому в команде выше стоит -not -path '*/log/*'.

Ночное плато CPU (признак 1). Тот самый признак, с которого я начал список, — и он же умеет врать чаще прочих. У Zimbra ночью своя жизнь: обучение антиспама zmtrainsa, обновление баз ClamAV, ротация и сжатие логов, а если у клиента настроен бэкап или переиндексация — тем более. Всё это честно грузит процессор в три часа ночи. Отличать просто: штатные ночные задачи отрабатывают и заканчиваются, а майнер держит ровное плато и в три ночи, и в шесть утра, и в воскресенье. Посмотрите sar -u за неделю, если установлен sysstat, — форма кривой скажет больше, чем любая единичная цифра.

Моё правило: один признак — повод посмотреть внимательнее, не повод для выводов. Тревога обоснована, когда сходятся два-три независимых. В Химках сошлись сразу четыре: аптайм, исходящее соединение, свежий бинарь и cron от root.

Чем закончилось в Химках и сколько это стоило

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

Но денежный ущерб от тормозов — мелочь на фоне главного риска. Три недели чужого доступа к почтовому серверу юрфирмы означают, что атакующий мог читать переписку по делам клиентов. Доказать, что не читал, невозможно. Именно эта неопределённость и есть настоящая цена — её не выразить в часах простоя.

Часы я всё же посчитал, потому что «несколько минут» звучит несерьёзно, пока не умножишь. Замеряли на трёх машинах: в среднем 12 минут в день на человека уходило на ожидание — открытие письма, поиск, вложения. Сорок четыре человека — это 8,8 часа в день, за пятнадцать рабочих дней компрометации 132 часа. Час сотрудника юрфирмы со всеми налогами и взносами обходится работодателю примерно в 1 000 рублей: 132 000 рублей просто выброшены, и это ещё без единого сорванного срока. Разбор, чистка и вывод почты на новый контур встали клиенту в 94 000 — то есть дешевле, чем один месяц жизни с майнером.

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

Что из этого следует вам

Взлом Zimbra редко приходит с табличкой «вас взломали». Он приходит как «почта тормозит», «письма подвисают», «сервер греется». За бытовой жалобой пользователя может стоять чужой процесс с трёхнедельным аптаймом, и увидеть его — вопрос десяти минут грепа, а не дорогого аудита.

Прогоните у себя минимальный набор из блока «проверьте за 2 минуты». Если хоть один признак сработал и вы не уверены, ложный он или нет, — пришлите мне вывод трёх команд: ps с аптаймом процессов, ss -tnp по установленным соединениям и mailq с началом очереди. За день отвечу, что из этого шум, а что — реальный след, и если след — с чего начинать, чтобы не спугнуть и не затереть улики.

Частые вопросы

Мой сервер просто тормозит. Это точно взлом?

Не точно — тормоза бывают и от честных причин: высокий IOwait, маленький буфер InnoDB, забитый индексный том, нехватка памяти под Java heap. Но проверить на взлом стоит первым делом, потому что это быстро и потому что майнер даёт ровно такую же картину: забивает CPU, поднимает IOwait, и почта еле шевелится. В Химках заявка была именно «тормозит», а под ней сидел майнер с аптаймом 21 день. Начните с ps на аптайм процессов и сверки со списком служб Zimbra — если чужого процесса нет, тогда уже копайте InnoDB и память.

Что важнее искать — необычный трафик или что-то ещё?

Вопреки расхожему мнению, не трафик. Самый частый первый симптом компрометации — аномальная загрузка CPU в нерабочие часы, а не всплеск трафика. Майнеру трафик почти не нужен, ему нужны ваши ядра, поэтому он и виден как ровное плато CPU ночью и в выходные, когда в офисе никого. Трафик вырастает позже — когда сервер начинают использовать как релей для спама. Так что смотрите в первую очередь на CPU по времени суток и на список процессов, а сетевые аномалии — вторым шагом.

Я нашёл в очереди кучу писем от адресов, которых у нас нет. Это релей?

Возможно, но не обязательно. Есть похожий по виду, но безобидный случай — бэкскаттер: когда спамеры подделывают ваш домен как отправителя, к вам возвращаются отбойники (bounce), и очередь заполняется письмами, которые выглядят чужими. Настоящий открытый релей отличается тем, что письма реально отправляются с вашего сервера на внешние домены, а не приходят как отказы. Посмотрите qshape deferred и логи maillog: если ваш сервер сам инициирует отправку на чужие домены и в reject нет отбоя — это релей, надо срочно закрывать mynetworks.

Насколько можно доверять срабатыванию DOS-фильтра по IP?

С осторожностью — это признак с самым высоким процентом ложных тревог. Строка про suspended в mailbox.log означает, что Zimbra заблокировала IP после серии неудачных логинов, и чаще всего виноват не хакер, а забытый почтовый клиент со старым паролем: телефон уволившегося сотрудника, неотключённый скрипт, устройство с просроченными кредами. Отличить брутфорс просто: у атаки адреса и логины-цели меняются, у забытого клиента — один IP долбится в один и тот же логин. Считать это взломом можно только в связке с другими признаками.

Сколько признаков должно совпасть, чтобы бить тревогу?

Моё рабочее правило — два-три независимых. Один признак почти всегда имеет невинное объяснение, и делать по нему выводы — путь к ложной тревоге либо к панике на ровном месте. А вот когда сходятся, например, чужой процесс с большим аптаймом, его исходящее соединение наружу и свежий cron от root — это уже не совпадение, это картина. В Химках сошлись сразу четыре признака, и сомнений не осталось. Если у вас совпало два и больше и вы не уверены — не гадайте, пришлите вывод команд, разберём вместе.

Нужна помощь с проектом?

Специалисты АйТи Фреш помогут с архитектурой, DevOps, безопасностью и разработкой — 15+ лет опыта

📞 Связаться с нами
#Zimbra#безопасность#логи#форензика#диагностика
Комментарии 0

Оставить комментарий

загрузка...

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.