CVE-2021-44228 · CVSS 10.0 CRITICAL · опубликована 10.12.2021

10 декабря 2021 года в сообществе разработчиков разразился один из самых громких кризисов последнего десятилетия: была обнародована уязвимость в Apache Log4j2, получившая имя Log4Shell, с максимально возможной оценкой — CVSS 10.0, CRITICAL. По сложившейся традиции, описание подобных катастроф часто подменяет преувеличением («взломаны все серверы мира»), но в случае с Log4Shell преувеличением было бы сказать, что уязвимость не так уж опасна. Библиотека Log4j2 — один из самых распространённых журналирующих фреймворков в экосистеме Java: её подключают буквально к любому приложению, от корпоративных бэкендов до «умных» кофеварок. Уязвимость затронула версии 2.0-beta9 по 2.15.0, то есть практически всё, что было выпущено за годы.

Как это работает

Архитектурно Log4Shell — это вопрос доверия к данным, которые приложение считало «безобидным текстом». Когда приложение пишет строку в журнал через Log4j2, библиотека проходит по этой строке в поисках специальных шаблонов — подстановок вида ${...}. Такие подстановки могут означать всё что угодно: текущую дату, имя пользователя, значение переменной окружения. Среди прочего Log4j2 умеет выполнять JNDI-запросы — обращения к Java Naming and Directory Interface, службе имён, которая по строковому имени возвращает Java-объекты. Это легитимная механика для корпоративных систем, ведь объекты могут подгружаться с центральных серверов каталогов.

Проблема в том, что строкой с ${...} может управлять злоумышленник. Достаточно, чтобы вредоносное значение попало хотя бы в одно поле, которое затем логируется: имя пользователя при регистрации, заголовок HTTP-запроса, содержимое письма в CRM. Журналирующая библиотека, предназначенная просто писать текст, начинала ходить по сети, скачивать и исполнять код. Атакующий оставляет подставной сервер, ждёт запроса — и получает исполнение кода внутри жертвы. Уязвимость получилась из того, что логирование, сетевое именование и загрузка кода оказались в одной цепочке доверия без прослоек изоляции. Исправить это оказалось сложнее, чем кажется: в первой «заплатке» (2.15.0) остались обходные векторы, потребовавшие немедленных вторичных исправлений.

Реальные последствия

Хронология уязвимости была драматичной: эксплойт обсуждался в закрытых кругах ещё до публичного раскрытия 10 декабря 2021 года, и в первые дни после обнародования сенсоры по всему миру фиксировали волны автоматизированных атак. Уязвимость находили повсюду, где быстро обнаруживали, что под капотом бизнес-приложения сидит Java: в игровых сервисах, в облачных платформах, в сетевом оборудовании, в системах управления умным домом. Требовались не просто патчи приложений — патчи самих библиотек, которые включены в продукты на глубине нескольких уровней зависимостей, то есть появился третий субъект: вендоры продуктов, которые сами использовали Log4j2. Масштаб уязвимости был таков, что поиск уязвимых экземпляров стал отдельной индустрией.

Что делать

Митигация Log4Shell в первые часы сводилась к скорости. Первый шаг — обновление Log4j2 до версии, где JNDI-подстановки в недоверенных строках были отключены по умолчанию. Где патчить нельзя, вендоры рекомендовали конфигурационные меры: удаление класса, отвечающего за JNDI-загрузку, или настройку, полностью запрещающую удалённую загрузку кода. На уровне инфраструктуры полезно фильтровать исходящие JNDI-обращения (LDAP/RMI и сопутствующие протоколы) к недоверенным адресам и мониторить журналы на подозрительные последовательности ${. Долгосрочная же мораль: зависимости проекта должны быть видимы (SBOM), версии библиотек — регулярно обновляться, а логирующие компоненты не должны иметь возможности исполнять код.

Источники

Карточка CVE-2021-44228 в NVD

Exploit-DB: EDB-50592

Каталог CISA KEV