У клиента-юрфирмы в Хамовниках почтовый сервер работал шесть лет и ни разу не подводил. Админ был уверен, что стоит девятка и всё обновлено. Одна команда показала патч-уровень на восемь ступеней ниже того, в котором закрыт RCE через postjournal. Разбираю, как проверить это у себя и что делать с результатом.
Какая у вас Zimbra на самом деле: версия, патч-уровень, риск
«У нас девятка и всё обновлено» — самая дорогая фраза в почте
Почтовый сервер стоит в углу серверной и не просит есть. Он работает. Письма ходят, календари синхронизируются, жалоб нет. Раз в год кто-нибудь вспоминает, что его неплохо бы обновить, и тут же забывает — потому что трогать работающее страшнее, чем не трогать.
Если у вас Zimbra, расклад обычно такой. Сервер поставил подрядчик несколько лет назад, потом его вёл штатный админ, потом админ ушёл в другую компанию, а сервер остался. На вопрос «какая у нас версия» звучит уверенное «девятка, последняя». Никто это не перепроверял. Я перепроверял — за последние годы примерно у сорока клиентов. Ответ админа совпал с тем, что выдал сервер, в одном случае из пяти.
Дело не в том, что админы врут. Дело в том, что у Zimbra две цифры версии, и обе называются «версия». Есть релиз — например, 9.0.0. И есть патч-уровень поверх релиза — P26, P33, P41. Релиз меняется раз в несколько лет, патч — раз в пару месяцев. Уязвимости закрываются вторым, а помнят все первое.
Ниже — как я снимаю обе цифры, где мне соврал файл истории установок и почему в ноябре 2024-го я уехал от клиента в третьем часу ночи.
Ноябрь 2024, Хамовники: 35 юристов и сервер, к которому боялись подходить
Позвали меня совсем не за этим. Формулировка была бытовая: «поиск по почте стал тупить, ищет минуту, иногда не находит вчерашнее письмо». Юридическая фирма, 35 рабочих мест, свой офис в переулке за Остоженкой, вся переписка по делам живёт в почте с 2019 года.
Сервер — виртуалка на локальном ESXi, 8 vCPU, 24 ГБ RAM, диск 750 ГБ. Внутри Zimbra. Какая — никто не знал, паролей от админ-консоли не нашли, но root по SSH был. Первая команда, которую я набираю на любой незнакомой Zimbra, всегда одна:
su - zimbra
zmcontrol -v
Ответ:
Release 9.0.0_GA_3924.RHEL7_64_20220514035628 RHEL7_64 FOSS edition, Patch 9.0.0_P33.
В этой строке четыре факта, и три из них плохие.
- 9.0.0_GA_3924 — релиз девятки. Тут админ не соврал.
- Patch 9.0.0_P33 — а вот это и есть настоящая версия. Уязвимость через postjournal закрыта в 9.0.0 Patch 41. Восемь уровней разрыва.
- FOSS edition — Open Source, а значит, никакого встроенного бэкапа. Клиент был уверен, что «бэкап делает сама Zimbra».
- RHEL7_64 — ОС под сервером семейства RHEL 7. На дворе ноябрь 2024-го, поддержка CentOS 7 закончилась 30 июня того же года. Обновлений безопасности для самой операционки уже не приходило пять месяцев.
Я показал строку директору. Он сказал: «Мы платим подрядчику за поддержку, у нас всё обновляется». Я попросил показать акты. В актах было «профилактическое обслуживание почтового сервера» — двенадцать штук за два года.
Проверьте у себя за две минуты
Три команды. Заходите по SSH под root, переключаетесь на пользователя zimbra и выполняете подряд:
su - zimbra
zmcontrol -v
tail -n 20 /opt/zimbra/.install_history
zmprov gs $(zmhostname) zimbraServiceEnabled | tr ' ' '\n' | grep -v '^$'
Первая даёт релиз и патч. Вторая — историю: когда сервер поставили, чем обновляли, чем пытались обновить. Третья — какие роли на нём реально подняты, потому что от этого зависит, что у него открыто наружу.
Как читать результат:
| Что увидели | Что это значит | Насколько срочно |
|---|---|---|
| 8.8.15 в любом виде | Ветка снята с поддержки 31 декабря 2023 года. Патчей безопасности после этой даты не выходило вовсе | Планировать переезд, а не патч |
| 9.0.0 с патчем ниже P41 | Открыт RCE через postjournal (CVE-2024-45519), эксплуатируется без аутентификации | На этой неделе |
| 9.0.0 с патчем ниже P43 | Не закрыт SSRF в парсере RSS (CVE-2025-25065) | В ближайший месяц |
| 10.0.x ниже 10.0.12 или 10.1.x ниже 10.1.4 | SQL-инъекция в SOAP-эндпоинте ZimbraSync (CVE-2025-25064, CVSS 9.8) плюс тот же SSRF | На этой неделе |
| 10.0.x ниже 10.0.18 или 10.1.x ниже 10.1.13 | Stored XSS через CSS-директиву @import (CVE-2025-66376), срабатывает в панели предпросмотра | На этой неделе |
В строке RHEL7_64 или CentOS7 | Операционная система под сервером мертва с 30 июня 2024 года | Отдельная задача, дороже патча |
Слово NETWORK вместо FOSS | Коммерческая редакция. Есть штатный бэкап, но есть и лицензия, которую надо проверить на срок | Проверить дату лицензии |
Если zmcontrol -v вообще не отработал и завис — это тоже результат. У Zimbra внутри статусной обвязки зашит таймаут в 60 секунд, и если сервер отвечает медленнее, команда честно врёт или молчит. Значит, сервер уже нездоров, и версия — не главная ваша проблема.
Где я ошибся: .install_history врёт реже, чем админ, но всё-таки врёт
Дальше я полез в историю установок. Файл /opt/zimbra/.install_history — это построчный журнал инсталлятора: что и когда ставили, что апгрейдили, чем патчили. Его нельзя отредактировать из админ-консоли, и он переживает апгрейды. Поэтому я ему доверяю больше, чем словам.
Вот что там было, в сокращении:
2019-04-11 22:40:12: INSTALL SESSION START
2019-04-11 23:07:51: INSTALLED 8.8.15_GA_3869
2019-04-11 23:07:51: INSTALL SESSION COMPLETE
2022-05-30 21:58:03: UPGRADE SESSION START
2022-05-30 22:41:19: UPGRADED 9.0.0_GA_3924
2022-05-30 22:41:19: UPGRADE SESSION COMPLETE
2024-03-07 01:18:55: INSTALL SESSION START
2024-03-07 01:19:02: INSTALLED zimbra-patch-9.0.0_P33
2024-03-07 01:22:10: INSTALL SESSION COMPLETE
2024-10-19 02:04:31: INSTALL SESSION START
2024-10-19 02:05:44: INSTALLED zimbra-patch-9.0.0_P36
Я обрадовался. Последняя строка — P36, значит, подрядчик всё-таки что-то ставил месяц назад — пусть и по своему устаревшему регламенту, в котором актуальным патчем до сих пор числился P36, и до нужного P41 остаётся пять шагов, а не восемь. Написал это в черновик отчёта.
Через час перечитал и увидел, чего в файле нет. У последней сессии нет строки INSTALL SESSION COMPLETE. Сессия открылась 19 октября в 02:04, поставила пакет патча в 02:05 и оборвалась. Пакет лёг на диск, а постинсталляционная часть — та, что дёргает zmfixperms, применяет схему и перезапускает службы — не отработала.
Поэтому zmcontrol -v и показывал P33: сервер работал на старом коде, хотя на диске лежали файлы нового. В /var/log/messages в 02:06 того же дня нашлось сообщение ядра о нехватке места на /opt. Патч не встал, потому что диск был забит на 97%, и никто этого не заметил — обновление ставили ночью по расписанию, отчёт никто не читал.
Урок, который я теперь применяю везде: сверять две вещи и не верить ни одной по отдельности. zmcontrol -v говорит, что реально запущено. .install_history говорит, что пытались поставить. Расхождение между ними — это и есть самая интересная строчка вашего аудита.
Как сверять патч-уровень со списком дыр
Патч-уровень сам по себе — просто число. Смысл появляется, когда вы кладёте его рядом с тем, что в каком патче закрыто. Держу такую табличку под рукой и обновляю по мере выхода бюллетеней:
| Уязвимость | Суть | Закрыта в |
|---|---|---|
| CVE-2024-45519 | Выполнение произвольных команд через службу postjournal: команда передаётся в SMTP-сессии на порт 10027 и попадает в шелл без экранирования (в живых атаках payload прятали в адресах поля CC) | 8.8.15 P46, 9.0.0 P41, 10.0.9, 10.1.1 |
| CVE-2025-25064 | SQL-инъекция в SOAP-эндпоинте ZimbraSync, CVSS 9.8, раскрытие метаданных писем | 10.0.12, 10.1.4 |
| CVE-2025-25065 | SSRF в парсере RSS-фида, запросы уходят на внутренние адреса сети | 9.0.0 P43, 10.0.12, 10.1.4 |
| CVE-2025-66376 | Хранимый XSS через CSS-директиву @import в теле письма, срабатывает при предпросмотре | 10.0.18, 10.1.13 |
Обратите внимание на первую строку. Для 8.8.15 патч 46 существует, но ветка снята с общей поддержки 31 декабря 2023 года. То есть формально дыра закрыта, а всё, что нашли после — уже нет и не будет. Сидеть на 8.8.15 в 2026 году — это не «старая, но рабочая версия». Это версия, для которой список незакрытых дыр растёт каждый квартал, и вы его не видите.
Отдельная история для тех, кто работает с аттестованными системами. Эти же уязвимости лежат в банке данных угроз ФСТЭК — там есть записи по postjournal-RCE, по SSRF из-за недостаточной валидации запросов и по XSS в веб-интерфейсе. Для ГИС и ИСПДн БДУ — официальный источник при оценке угроз, и проверяющий смотрит именно туда, а не в ваш акт профилактического обслуживания.
Цена бездействия: 4 сентября, 27 сентября, 28 сентября
Хронология по postjournal-RCE выглядит так. Патч вендора вышел 4 сентября 2024 года. Публичный эксплойт появился 27 сентября. Первые массовые атаки зафиксированы 28 сентября — на следующий день после публикации кода. К 1 октября массовую эксплуатацию подтвердили независимые исследователи, а по данным Proofpoint кто-то пользовался этой дырой ещё за несколько недель до огласки.
Двадцать четыре дня. Столько было у администратора, который следит за бюллетенями, чтобы спокойно поставить патч в плановое окно. У моего клиента в Хамовниках этих дней не было, потому что бюллетени никто не читал.
Теперь деньги. Считаю на этом же случае, все цифры — из нашей сметы, а не из головы.
- Плановое обновление до P41 с проверкой: 6 часов работ, из них 2 в окно простоя. Ночная смена, один инженер. По нашей ставке 3 500 ₽ за час — 21 000 ₽, и это весь бюджет вопроса, если успеть в те самые двадцать четыре дня.
- Разбор уже случившейся компрометации почтового сервера, который мы делали у другого клиента: три недели — от первого подозрения до момента, когда я согласился считать сервер чистым. Там был криптомайнер, root через sudo, повторное заражение через юнит systemd уже после первой чистки. Сервер в итоге вывели и мигрировали, потому что доверия к нему не осталось. По часам это вышло 147 часов работ — 514 500 ₽ по той же ставке, не считая нового сервера и лицензий.
- Простой почты в юрфирме на 35 человек. Один рабочий день без переписки по делам — это 35 человек по 8 часов; даже если считать час работы сотрудника по себестоимости фонда оплаты, 1 500 ₽ в час, получается 420 000 ₽ за сутки. Плюс сорванные сроки в двух процессах и разговор с доверителем, которого никто не хочет.
Разница между шестью часами и тремя неделями, между двадцатью одной тысячей и полумиллионом, — это и есть весь смысл проверки патч-уровня. Она стоит две минуты.
Что мы сделали за одну ночь и во что это встало
Работали в ночь с пятницы на субботу — юристы в выходные почту читают, но письма пишут редко, окно нашлось.
Порядок был такой:
- Освободили
/opt. Причина провалившегося патча никуда не делась. Вычистили ротированные логи и два старых архива в/opt/zimbra/backup, которые кто-то положил руками в 2021 году. Освободилось 113 ГБ, занятость упала с 97% до 82% — на томе в 750 ГБ это ровно те пятнадцать процентных пунктов. - Сняли холодный слепок. Остановили сервер и сделали снапшот виртуалки плюс отдельный
tarкаталога/opt/zimbraна сетевой том. Это заняло 1 час 40 минут — 573 ГБ данных. Без этого шага я к патчам не приступаю. - Разгребли незавершённую установку P36. Пакет на диске был, а состояние — нет. Довели её до конца штатным путём, проверили статус служб.
- Поставили патчи до P41 и убедились, что каждая сессия дописала
INSTALL SESSION COMPLETE. - Выключили postjournal, потому что клиент им не пользовался, и проверили, кому сервер разрешает релей.
# проверка после каждого шага
zmcontrol -v
zmcontrol status
grep -c 'INSTALL SESSION COMPLETE' /opt/zimbra/.install_history
# кому разрешён релей — тут не должно быть лишних сетей
zmprov gcf zimbraMtaMyNetworks
# что реально слушает наружу
ss -lntp | grep -E ':(25|110|143|443|587|993|995|7071|7072|10027|11211)\b'
Где я чуть не наступил на грабли. После патча zmcontrol status показал mailbox в состоянии Stopped, и я почти начал откатывать снапшот. Подождал ещё четыре минуты — поднялся. Mailboxd после обновления схемы стартует долго, особенно когда индексный том большой, а heap выставлен по остаточному принципу. Если бы откатился — потерял бы всю ночную работу и вернул бы сервер в дырявое состояние.
Итог: 9 часов работ, из них 3 часа 20 минут полного простоя. Счёт — 31 500 ₽ вместо разговора про три недели и полмиллиона. Ни одного потерянного письма. Тормозивший поиск, из-за которого меня и позвали, оказался следствием того же забитого диска — индексу некуда было писать.
Что из этого следует, если у вас похожая картина
Проверка версии — это не про любопытство. Это про то, чтобы отличить «сервер старый, но управляемый» от «сервер уже год как открыт наружу, и мы об этом не знаем».
Три вещи, которые я бы сделал в вашем случае прямо сегодня, если вы ещё не знаете свой патч-уровень:
- Снять
zmcontrol -vи записать строку целиком, а не по памяти. - Посмотреть хвост
.install_historyи убедиться, что у последней сессии естьCOMPLETE. - Проверить занятость
/opt. Забитый диск тихо ломает и патчи, и индекс, и очередь.
Дальше начинается развилка, которую по одной команде не решить. Если у вас 8.8.15 — патчить некуда, разговор пойдёт про переезд, а он упирается в календари, общие папки и то, чем пользуются с телефонов. Если девятка с большим разрывом по патчам — надо смотреть, что успело произойти за время разрыва: следы в логах, лишние учётки, чужие задания в cron. Если под сервером живёт CentOS 7 — обновлять придётся не только Zimbra, и это уже другой бюджет и другой график.
Мне не нужен доступ к вашему серверу, чтобы сказать первое приближение. Достаточно трёх строк: вывод zmcontrol -v, последние двадцать строк .install_history и вывод df -h /opt. Пришлите их — за день отвечу, что у вас на самом деле стоит, какие дыры открыты и сколько примерно стоит привести это в порядок. Если окажется, что всё в норме — так и напишу, это тоже нормальный ответ.
Частые вопросы
Чем патч-уровень отличается от версии и почему все путают?
Релиз — это 8.8.15, 9.0.0, 10.1. Он меняется раз в несколько лет, и именно его называют «версией». Патч-уровень — это P33, P41, P46 поверх релиза, и меняется он каждые пару месяцев. Уязвимости закрывают патчами, а помнят люди релиз. Отсюда и берётся классическое «у нас девятка, всё обновлено» при патче двухлетней давности. Команда zmcontrol -v выводит обе цифры одной строкой — там же видно редакцию (FOSS или NETWORK) и семейство ОС, под которое собран пакет.
Админ-консоль показывает версию. Почему нельзя смотреть там?
Смотреть можно, но я на неё не полагаюсь. Во-первых, у вас может не быть пароля от неё — в моей практике это каждый третий случай приёма чужого сервера. Во-вторых, админ-консоль показывает данные из своего кэша, и на форуме Zimbra есть отдельные обсуждения расхождений между статусом в консоли и выводом CLI. В-третьих, консоль не покажет вам оборванную сессию установки патча — а это ровно то место, где в моём ноябрьском случае и пряталась правда.
У нас 8.8.15 и всё работает. Обязательно ли что-то делать?
Работает — это про функциональность, а не про безопасность. Общая поддержка 8.8.15 Open Source закончилась 31 декабря 2023 года: обновлений безопасности после этой даты не выходило и не выйдет. Всё, что нашли в 2024-м, 2025-м и позже, для вас не закрыто. Патч 46 для восьмёрки существует и закрывает postjournal-RCE, поставить его стоит прямо сейчас, но это разовая мера. Дальше разговор идёт про апгрейд или переезд, и в лоб он получается не у всех — на официальном форуме есть целая ветка людей, у которых обновление до десятки в их конфигурации не прошло.
Мы платим подрядчику за поддержку. Разве он не следит за патчами?
Иногда следит. Проверяется это за две минуты и без конфликта: попросите прислать вывод zmcontrol -v с вашего сервера и сравните патч-уровень с датой последнего акта. У моего клиента в Хамовниках в актах было двенадцать «профилактических обслуживаний» за два года, а на сервере — патч, который поставили в марте и который не встал. Никто не обманывал: обновление запускалось по расписанию ночью, падало из-за забитого диска, и отчёт о падении не читал ни клиент, ни подрядчик.
Что делать, если разрыв большой — сразу прыгать на последнюю версию?
Не сразу. Сначала я привожу сервер в состояние, в котором он вообще способен пережить обновление: свободное место, целостность базы, живой LDAP, снятый и проверенный слепок. Потом ставлю патчи внутри текущего релиза — это дёшево и почти всегда безопасно. И только после этого обсуждается смена релиза, потому что там начинаются промежуточные версии, схема базы и риск остаться с мёртвым каталогом посреди ночи. Прыжок «из 8.8.15 сразу в десятку» на живом проде без репетиции на копии я не делаю.
Оставить комментарий