Свежий main, старый fileman: как проверить реальный patch level Битрикс
В админке зелёный статус, обновление прошло, заявку закрыли. А на втором веб-сервере осталась старая копия партнёрского модуля. Я, Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш», считаю обновление принятым только после проверки конкретных модулей и исполняемого кода. Покажу, как собрать такую проверку: от main и fileman до решений Маркетплейса, локальных копий компонентов и PHP-процессов.
1. Что на самом деле означает версия продукта
Начну с важного уточнения: номер продукта внизу административной панели Битрикс означает версию главного модуля main. Это не отдельный счётчик, который подтверждает состояние всей установки. Поэтому нормальный сценарий нашей задачи выглядит так: main обновлён, а fileman или партнёрский модуль отстаёт. Если свежий номер в админке противоречит версии main на диске, сначала проверяйте узел, DOCUMENT_ROOT и источник показанного номера. Пояснение разработчика.
Система обновлений работает с версиями отдельных модулей и учитывает зависимости. В ней можно выбирать обновления, а в экспертном режиме — ограничивать установку определённой версией. Поэтому фраза «мы обновляли Битрикс в пятницу» для меня почти бесполезна. Нужен перечень: какие модули, до каких версий, на каких серверах и с каким результатом. Журнал установки помогает восстановить эту картину. Документация SiteUpdate.
С Маркетплейсом добавляется отдельная цепочка: разработчик решения, его выпуск, доступность обновления для вашей установки и фактическая доставка файлов. Я отдельно открываю обновления решений и проверяю условия получения новых версий. Статус «обновлений нет» имеет смысл только после успешного обращения к серверу обновлений. Ошибка соединения, ограничение доступности или давно не запускавшаяся проверка не превращают установленный код в исправленный.
Мой рабочий patch level — это запись из четырёх частей: обнаруженная версия, применимый бюллетень, подтверждение установки исправления и проверка работающего экземпляра. У каждой записи есть дата и конкретный узел. Единственного числа «сайт безопасен на версии X» я в отчёт не ставлю. Оно слишком легко скрывает старую библиотеку, забытый обработчик или второй сервер, на который обновление вообще не попало.
2. Собираю два списка: зарегистрированные модули и файлы
Первый список беру в разделе «Настройки → Настройки продукта → Модули»: идентификатор, версия, установлен ли модуль. Для автоматизации в доверенном окружении есть ModuleManager::getInstalledModules(), getVersion() и getModulesFromDisk(). Но реестр установленных модулей не отвечает на вопрос, какие файлы физически остались на сервере. Неустановленный модуль тоже может лежать на диске; его доступность и возможность выполнения нужно разбирать отдельно. Страница модулей, API ModuleManager.
Второй список собираю непосредственно из /bitrix/modules и /local/modules. Оба дерева обязательны: при поиске соответствующих файлов Битрикс отдаёт приоритет /local. Две директории с одинаковым ID нельзя молча объединять в одну строку отчёта. Сохраняйте логический и физический путь, особенно при симлинках и переключении релизов. Сначала установите, какой каталог обслуживает нужный виртуальный хост, затем запускайте инвентаризацию. Структура директорий.
Для первого прохода я выбираю чтение файлов без запуска PHP. Следующий скрипт сохраняйте вне DOCUMENT_ROOT как inventory.py. Он требует Python 3, читает стандартную декларацию VERSION и выводит отдельную JSON-строку для каждого каталога модуля. Пример запуска: python3 /srv/audit/inventory.py /srv/www/shop. При сохранении вывода файл отчёта тоже размещайте вне веб-корня.
import json, re, sys
from pathlib import Path
if len(sys.argv) != 2:
sys.exit("Usage: inventory.py DOCUMENT_ROOT")
root = Path(sys.argv[1]).resolve(strict=True)
if not (root / "bitrix/modules").is_dir():
sys.exit("DOCUMENT_ROOT/bitrix/modules is not a directory")
pattern = re.compile(rb'''['"]VERSION['"]\s*=>\s*['"](\d+\.\d+\.\d+)['"]''')
for relative in ("bitrix/modules", "local/modules"):
base = root / relative
if not base.is_dir():
continue
for module in sorted(base.iterdir()):
if not module.is_dir():
continue
file = module / "install/version.php"
row = {"module": module.name, "path": str(file),
"physical_path": str(file.resolve()), "version": None,
"status": "review"}
try:
matches = pattern.findall(file.read_bytes())
if len(matches) == 1:
row.update(version=matches[0].decode("ascii"), status="literal_found")
else:
row["reason"] = "missing_or_multiple_VERSION"
except OSError as error:
row["reason"] = type(error).__name__
print(json.dumps(row, ensure_ascii=False))Это намеренно ограниченный инструмент. Он не интерпретирует PHP и может найти VERSION внутри комментария; вычисляемую версию он не распознает. Статус literal_found означает только найденную декларацию. Строки review разбирайте вручную. Скрипт не определяет регистрацию модуля, выбранный загрузчиком код или завершение миграций. Запускайте его на каждом отдельном дереве приложения, включая узлы фоновых заданий. При подозрении на взлом предпочтительна проверка сохранённой копии файлов из доверенного окружения.
3. Сопоставляю версии с конкретными бюллетенями
После инвентаризации открываю два источника: центр обновлений безопасности самого Битрикс и реестр уязвимых сторонних решений. Затем перехожу в карточки разработчиков и исследователей. Приведённые ниже сведения проверены на 5 сентября 2026 года. Таблица показывает несколько важных контрольных точек; полный перечень применимых уязвимостей нужно собирать по составу вашего сайта. Бюллетени платформы, реестр сторонних решений.
В рабочей таблице я обязательно связываю номер исправления с идентификатором ошибки. Иначе через год старый порог начинают использовать как универсальное разрешение ничего больше не обновлять. | Компонент | Конкретная проблема | Версия исправления | | --- | --- | --- | | main | BDU:2025-08663, превышение привилегий при работе с почтовыми шаблонами | 25.100.400 | | fileman | BDU:2025-08662, превышение привилегий при копировании файлов | 24.500.100 | | iblock | BDU:2025-08665, чтение файлов при XML-импорте | 24.300.100 | | main | BDU:2026-04276, раскрытие настроек почтовых отправлений | 26.150.100 | | landing | BDU:2026-05965, включение локальных файлов при редактировании лендинга | 25.1100.100 | | esol.importexportexcel | Исправления безопасности из бюллетеня 27.12.2025 | 3.2.6 |
Здесь легко преувеличить риск. Исследователи Positive Technologies указывают, что рассматриваемые ошибки 2025 года в main, fileman и iblock требовали авторизованного доступа; для iblock — прав управления инфоблоками. Это существенное условие, которое нельзя выбрасывать из отчёта. Чтение файла, включение локального файла и RCE тоже не синонимы: возможность исполнения кода зависит от конкретной ошибки и условий. Однако украденная учётка редактора делает такие ограничения вполне практической проблемой. Разбор исследователей.
Показательный пример — esol.importexportexcel. Порог 2.9.0 относится к старой проблеме; декабрьский бюллетень 2025 года уже указывает исправление 3.2.6. Проверка только старой известной RCE оставит новые вопросы без ответа. Разработчик отдельно уточняет, что для описанных декабрьских ошибок нужны доступ в административную часть и права работы с модулем. Я фиксирую и версию, и условия, и дату бюллетеня. Если поставщик не опубликовал полный диапазон затронутых версий, не придумываю его самостоятельно. Бюллетень разработчика.
Почему версия модуля — не абстрактная формальность
Исторический пример с понятным ущербом — CVE-2022-27228 в модуле vote: производитель платформы указывает исправление 21.0.100 и оценку опасности 9.8 из 10. Произвольная запись файла при подходящей конфигурации могла обернуться выполнением PHP-кода. Но переносить этот ярлык на любую похожую уязвимость нельзя: иногда для эксплуатации нужны права редактора или администратора, иногда опасный маршрут доступен вообще без авторизации — это выясняется по конкретному бюллетеню, а не по аналогии.
То же самое касается решений Маркетплейса: официальный реестр уязвимых сторонних решений на момент проверки содержал несколько десятков записей. Например, один из модулей импорта был отмечен уязвимым до версии 1.79.0 — разработчик пояснял, что это обновление добавляет проверку прав и токена, защищает HTTP-воркеры и убирает выполнение пользовательской PHP-формулы. Партнёрские решения нужно сверять с реестром так же внимательно, как и платформенные модули, а не только main и fileman.
4. Учебный разбор: два узла условной компании «Кройка и шитьё»
Для воспроизводимого разбора беру файловую модель ООО «Кройка и шитьё»: условная производственная компания на 49 рабочих мест, B2B-каталог, два веб-узла. Это учебный сценарий с синтетическими файлами версий; реальная CMS здесь не разворачивалась. Архитектурная вводная — отдельные деревья кода web01 и web02 за балансировщиком. Именно такая схема требует проверки каждого узла: общая база данных сама по себе не синхронизирует содержимое дисков.
В обоих деревьях задаю main 26.150.100, fileman 24.500.0 и esol.importexportexcel 3.2.0. На web02 дополнительно оставляю копию партнёрского модуля версии 2.9.0 в /local/modules. Первый запуск приведённого скрипта действительно дал три записи для web01 и четыре для web02. Дубликат сохранился отдельной строкой, как и требовалось. | Путь относительно корня сайта | web01 | web02 | | --- | --- | --- | | bitrix/modules/main | 26.150.100 | 26.150.100 | | bitrix/modules/fileman | 24.500.0 | 24.500.0 | | bitrix/modules/esol.importexportexcel | 3.2.0 | 3.2.0 | | local/modules/esol.importexportexcel | отсутствует | 2.9.0 |
Получились три задачи: проверить отставание fileman от нужного исправления, обновление партнёрского решения и происхождение его локальной копии. Для второго файлового прогона меняю декларации fileman на 26.0.0, партнёрского модуля — на 3.2.6, а дубликат переношу за корень модели. Результат: по три записи, ноль дублирующих ID и ноль расхождений версий между узлами. Версия fileman 26.0.0 действительно опубликована в истории модуля, но здесь использована только как значение учебной проверки. История fileman.
На настоящем проекте простое изменение VERSION ничего не исправляет. Перед переносом локального модуля нужно выяснить, какие доработки и зависимости он содержит; затем установить официальные обновления и проверить фактические файлы. Итог эксперимента скромный, но полезный: инвентаризация обнаруживает копию, которую потерял бы отчёт с одной строкой на ID. Дополнительно проверены отсутствующий version.php, несколько деклараций VERSION и симлинки. Работоспособность магазина и закрытие уязвимостей этим тестом не подтверждались — для них нужна следующая часть приёмки.
5. Как доказать, что исправление действительно работает
Сначала разбираю завершение установки: ошибки копирования, права на каталоги, свободное место, выполнение обновляющих скриптов. Битрикс допускает updater.php, который меняет не только файлы внутри модуля, но и внешние файлы или базу данных. Поэтому свежий install/version.php не доказывает успешное прохождение всей процедуры. Особенно внимательно проверяйте установки, где обновление прерывали, повторяли вручную или восстанавливали только часть файлов из резервной копии. Механизм обновления модулей.
Дальше проверяю именно файлы, затронутые исправлением, и рабочие копии компонентов. Источником сравнения служит доверенный пакет соответствующей версии, официальный патч или чистая контрольная установка, обновлённая тем же способом. Проверяю /local/components, /bitrix/components, PHP в шаблонах и самостоятельные обработчики, связанные с решением. Совпадение хешей двух серверов доказывает одинаковость файлов, но оба сервера могут содержать одинаковую старую копию. Для подтверждения исправления нужен доверенный эталон.
Третий слой — работающие PHP-процессы. Например, конфигурация ниже требует явного применения изменений к OPcache; сама замена файлов недостаточна. Я включаю в процедуру управляемый перезапуск обслуживающего сайт PHP-FPM на каждом узле, с выводом узла из балансировки и проверкой после возврата. Это пример настройки, а не рекомендация включать её на любом сайте. При использовании дискового кеша OPcache его состояние тоже нужно учитывать. Настройки OPcache.
opcache.enable=1
opcache.validate_timestamps=0
opcache.file_cache=""Последний слой — проверка поведения. На изолированной копии использую безопасный контрольный сценарий для конкретного исправления: тестовую учётку с нужными ограничениями и специально подготовленные несекретные данные. Параллельно проверяю обычные операции: редактор, импорт, обмен, оформление заказа. Один ответ 403 через WAF ничего не доказывает о коде на backend. Если обнаружены признаки прежнего взлома, обновление сопровождается расследованием: сохранением артефактов, проверкой постороннего кода и учёток, а при подтверждённой утечке — заменой секретов.
Ещё два пункта, которые не выражаются версией модуля
Отдельно стоит проверить корень сайта на файл bitrixsetup.php: официальный бюллетень по этому риску требует именно его удаления, а не обновления какого-либо модуля — версией эта угроза вообще не выражается, и инвентаризация модулей её не поймает.
Для сайтов на main версии 24.400.0 и новее при настроенном Composer доступна официальная CLI-команда обновления модулей из каталога /bitrix: php bitrix.php update:modules. Это не замена ручной сверки с бюллетенями, но удобный способ стандартизировать сам процесс применения обновлений на нескольких узлах одинаково, а не полагаться на клики в разных админках.
6. Что делать первым и как не повторять проверку с нуля
Я начинаю с доступных извне компонентов и известных применимых ошибок с тяжёлыми последствиями. Если исправление пока невозможно установить, временно ограничиваю доступ к затронутой функции и назначаю срок устранения. Ограничение админки через VPN полезно, но сначала нужно проверить, действительно ли опасный маршрут находится только там. У модулей бывают отдельные обработчики и другие точки входа. Отключение пункта меню не означает отключение серверного кода.
Обычные обновления сначала прогоняю на копии с проверяемым восстановлением файлов и базы. Состав тестов определяется бизнесом: для каталога с импортом важнее корректный обмен и обработка ошибок, чем идеальная проверка каждой административной кнопки. На копии отключаю реальные платежи, рассылки и внешние задания. Если обновляющий скрипт меняет схему данных, возврат старого каталога приложения сам по себе может оказаться неполным откатом.
После приёмки сохраняю реестр: узел, DOCUMENT_ROOT, ID и путь модуля, версия, бюллетень, подтверждение исправления, дата проверки и ответственный. Для перенесённого исправления без изменения версии дополнительно нужны происхождение патча и проверенные файлы. Такой случай допустим, но сопровождать его дороже: следующий администратор должен понимать, почему установлен старый номер и на каком основании конкретная ошибка считается закрытой.
Ежедневно можно сравнивать текущую инвентаризацию с принятой и сообщать о новых модулях, дублях, откатах версий и необъяснимых изменениях кода. Бюллетени проверяйте отдельно: отсутствие изменений на сервере не означает отсутствия новых сведений об уязвимостях. Я спокойно откладываю косметические обновления интерфейса и охоту за красивым номером. Откладывать разбор старого исполняемого модуля, который доступен пользователям и никем не сопровождается, значительно дороже.
- Сначала: применимые критичные уязвимости, доступные точки входа и признаки уже произошедшего взлома.
- Затем: официальное исправление, проверка файлов и миграций, обновление PHP-процессов, функциональная приёмка.
- Следом: забытые решения, локальные копии, неподдерживаемые доработки и расхождения между узлами.
- Постоянно: контроль состава приложения и новых бюллетеней с назначенным ответственным.
Частые вопросы
Можно проверить patch level только из браузера?
В админке можно собрать исходный список версий. Для подтверждения состояния файлов на каждом узле, локальных копий и PHP-процессов нужен доступ к инфраструктуре либо соответствующие проверяемые отчёты.
Старый номер версии всегда означает незакрытую уязвимость?
Нет. Возможно отдельное официальное исправление без смены номера. Но его наличие нужно подтвердить происхождением патча и состоянием затронутых файлов; устного заявления недостаточно.
Свежая версия модуля исключает старый уязвимый код?
Нет. Могли остаться копии компонентов, незавершённое обновление, другое дерево на соседнем узле или старый код в OPcache. Версия — отправная точка проверки.
Можно удалить неиспользуемый модуль?
После проверки зависимостей, обработчиков, агентов, заданий и нужных данных. Затем нужно убедиться, что не остались доступные исполняемые файлы. Простое удаление каталога может нарушить работу сайта.
Я помогу проверить patch level вашего Битрикс: собрать модули и локальные копии, сопоставить их с бюллетенями и подготовить проверяемый план обновления. Обратитесь в [«АйТи-Фреш»](https://itfresh.ru/) — разберём оставшиеся риски и организуем приёмку исправлений.
Бесплатная консультация →
Источники
- 1С-Битрикс: определение версии продукта — Учебный курс, урок 23444: версия продукта соответствует версии главного модуля. [Документ](https://dev.1c-bitrix.ru/learning/course/?COURSE_ID=57&LESSON_ID=23444&LESSON_PATH=5442.23446.23444).
- 1С-Битрикс: модули и их версии — Официальные описания [ModuleManager](https://docs.1c-bitrix.ru/api/classes/Bitrix-Main-ModuleManager.html) и [архитектуры модулей](https://docs.1c-bitrix.ru/pages/modules/architecture.html), включая install/version.php.
- 1С-Битрикс: установка обновлений — [Система обновлений](https://dev.1c-bitrix.ru/user_help/marketplace/sysupdate.php); курс 101, [урок 3218](https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=101&LESSON_ID=3218): version.php, updater.php и зависимости.
- 1С-Битрикс: исправления main и fileman 2025 года — BDU:2025-08663 — [main 25.100.400, 21.04.2025](https://www.1c-bitrix.ru/vul/25346794/); BDU:2025-08662 — [fileman 24.500.100, 18.04.2025](https://www.1c-bitrix.ru/vul/25346784/).
- 1С-Битрикс: чтение файлов при XML-импорте — BDU:2025-08665, iblock, исправление 24.300.100 от 23.04.2025. [Карточка](https://www.1c-bitrix.ru/vul/25346820/).
- 1С-Битрикс: исправления main и landing 2026 года — BDU:2026-04276 — [main 26.150.100, 08.04.2026](https://www.1c-bitrix.ru/vul/28287820/); BDU:2026-05965 — [landing 25.1100.100, 13.01.2026](https://www.1c-bitrix.ru/vul/27618322/).
- Positive Technologies: условия эксплуатации ошибок Битрикс — Публикация исследователей от 12.08.2025 об ошибках main, fileman и iblock, необходимых правах и последствиях. [Разбор](https://ptsecurity.com/about/news/pt-experts-helped-to-strengthen-security-in-1c-bitrix-systems/).
- 1С-Битрикс: реестр уязвимых сторонних решений — Решения, версии и рекомендации разработчиков; проверено 05.09.2026. [Реестр](https://www.1c-bitrix.ru/vul_dev/).
- esolutions: исправления безопасности модулей импорта — Бюллетень от 27.12.2025: версии 3.2.6 для двух модулей импорта и 0.6.4 для многофункционального решения. [Бюллетень](https://esolutions.su/bezopastnost-saytov/dorabotki-bezopasnosti-moduley-importa/).
- PHP: применение изменений к OPcache — Директивы opcache.validate_timestamps, opcache.file_cache и поведение сброса кеша. [Конфигурация](https://www.php.net/manual/en/opcache.configuration.php), [opcache_reset](https://www.php.net/manual/en/function.opcache-reset.php).
