Если ваше приложение использует Log4j с версии 2.0-alpha1 до 2.14.1, вам следует как можно скорее выполнить обновление до последней версии (2.16.0 на момент написания этой статьи - 20 декабря).

Примечание переводчика. Ситуация с Log4j быстро меняется, поэтому рекомендуется, по возможности, обновить до версии2.17.0 или более поздней. Эта версия содержит исправления безопасности для двух уязвимостей удаленного выполнения кода, исправленных в2.15.0 (CVE-2021-44228) и2.16.0 (CVE-2021-45046), и последнюю DoS уязвимость, исправленную в версии 2.17.0 (CVE-2021-45105). 

Уязвимость Log4j, известная как Log4Shell и отслеживаемая как CVE-2021-44228, позволяет злоумышленнику выполнить произвольный код в системе. 

Правительство Швейцарии опубликовало отличную диаграмму, объясняющую уязвимость:

Теперь давайте погрузимся в стратегии смягчения последствий ...

Использование Maven Dependency Plugin

В проекте Maven вы можете найти зависимость log4j-core в дереве зависимостей и проверить, используете ли вы затронутую зависимость. Легкий способ сделать это - выполнить следующую команду:

mvn dependency:tree -Dincludes=org.apache.logging.log4j:log4j-core

Эта команда использует подключаемый модуль Maven Dependency для отображения дерева зависимостей (включая транзитивные зависимости) для проекта. Параметр includes фильтрует вывод, чтобы показать только зависимость log4-core. 

Если ваш проект зависит от уязвимой версии Log4j, вы увидите что-то вроде следующего:

В этом примере выходные данные показывают, что проект напрямую использует версию 2.14.1 (уязвимую) Log4j. В этом проекте необходимо обновить зависимость:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.14.1</version> <!-- update this! -->
</dependency>

на следующую:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.16.0</version> <!-- or newer version -->
</dependency>

Я попробовал это с проектом JDBC connector для базы данных MariaDB и получил следующее:

Хорошие новости - проект не использует Log4j и, следовательно, не уязвим для Log4Shell (см. эту статью с дополнительной информацией о конкретном случае MariaDB).

Использование Maven Help Plugin

Если вы хотите продолжить расследование, вы можете проверить эффективный POM и найти фреймворк ведения журнала, используемую в вашем проекте. 

Продолжая исследовать проект JDBC-коннектора MariaDB, я использовал Maven Help Plugin для создания эффективного POM и, поскольку я использовал Unix-подобную операционную систему (macOS), я отфильтровал вывод с помощью grep (вы можете использовать findstr в Windows) следующим образом:

mvn help:effective-pom | grep log

Я получил следующий результат:

Это показывает, что драйвер JDBC MariaDB использует Logback в качестве фреймворка ведения журнала. 

Хотя Log4Shell не влияет на Logback, у него есть связанная уязвимость (гораздо меньшей серьезности, не нужно паниковать), исправленная в версии1.2.8 и 1.3.0-alpha11. Я проверил версию, используемую коннектором, и обнаружил, что она использует 1.3.0-alpha10. 

Несмотря на то, что Logback включен в качестве тестовой зависимости в драйвер MariaDB, я отправил pull request на GitHub, чтобы обновить его. 

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

Использование Syft и Grype

В более сложных проектах с большим количеством файлов JAR вы можете использовать такие инструменты, как Syft и Grype. Syft - это инструмент командной строки и библиотека Go для создания спецификации программного обеспечения (SBOM) из образов контейнеров и файловых систем. Его можно использовать с Grype, который сканирует образы контейнеров и файловые системы на наличие уязвимостей на нескольких уровнях вложенности.

Использование инструмента LunaSec

Люди из LunaSec (платформа безопасности данных с открытым исходным кодом) разработали инструмент с открытым исходным кодом для сканирования каталогов и поиска файлов, имеющих соответствующий хэш для уязвимых зависимостей Log4j. Инструмент доступен для систем Windows, Linux и MacOS. Все, что вам нужно сделать, это запустить инструмент, передав каталог для сканирования. Например:

log4shell scan your-project-dir

В уязвимом проекте вы получите что-то вроде следующего:

10:04AM INF identified vulnerable path fileName=org/apache/logging/log4j/core/net/JndiManager$1.class path=test/struts-2.5.28-all/struts-2.5.28/apps/struts2-rest-showcase.war::WEB-INF/lib/log4j-core-2.12.1.jar versionInfo="log4j 2.8.2-2.12.0"

Использование log4j-scan

Команда FullHunt предоставила инструмент с открытым исходным кодом под названием log4j-scan, автоматизированный комплексный сканер для поиска уязвимых хостов Log4j. Это позволяет командам разработки сканировать свою инфраструктуру, а также проверять обходы WAF (брандмауэра веб-приложений), которые могут привести к выполнению кода. Инструмент имеет несколько опций, но вкратце вы передаете инструменту URL-адрес для сканирования и получаете отчет об обнаруженных уязвимостях. Например:

python3 log4j-scan.py -u https://log4j.lab.secbot.local

Вот скриншот вывода:

Использование тестера уязвимостей Huntress Log4Shell

Тестер уязвимости Huntress Log4Shell является инструментом с открытым исходным кодом доступен в Интернете, которая позволяет проверить, если приложение использует уязвимую версию Log4j. 

Инструмент генерирует строку, используемую в качестве входных данных в приложении, которое вы хотите проверить, например, используя ее в текстовом поле. 

Эта строка включает поиск JNDI на сервере LDAP. Сервер регистрирует запросы от вашего приложения и показывает IP-адрес, с которого был отправлен запрос. Я записал видео, демонстрирующее этот инструмент:

Вывод

Появляется больше инструментов, и я рекомендую следить за тем, что публикуют эксперты по безопасности. 

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

Комментарии (8)


  1. aleksandy
    20.12.2021 15:39
    +1

    Гуглопереводчик?


  1. dir2000
    20.12.2021 16:35

    У нас проект на Spring Boot. По умолчанию используется logback, но среди транзитивных зависимостей есть "org.apache.logging.log4j:log4j-api:2.10.0" (core не нашел). Нужно ли беспокоиться и что-то делать?


    1. val6852 Автор
      20.12.2021 16:41

      Все зависит от версии logback.

      В http://mailman.qos.ch/pipermail/logback-user/2021-December/005168.html написано:

      We urge you to upgrade to logback 1.2.8 as soon as possible.


    1. wAngel
      20.12.2021 16:42
      +1

      Модуль log4j-api не содержит уязвимости:

      Note that only the log4j-core JAR file is impacted by this vulnerability. Applications using only the log4j-api JAR file without the log4j-core JAR file are not impacted by this vulnerability.


  1. wAngel
    20.12.2021 16:37
    +2

    На 20 декабря 2021 правильнее обновляться сразу на 2.17 в которой исправлены ещё и CVE-2021-45105.


    1. val6852 Автор
      20.12.2021 16:48

      Об этом написано в примечании в начале заметки.


  1. amarao
    20.12.2021 16:44
    +1

    Да, я планирую себе на футболку QR-код с автопроверкой сделать и по логам сервера оценить количество <s>дырявых</s> систем слежения с поддержкой QR-кодов в окружающем мире.


  1. mmMike
    20.12.2021 17:12

    Да просто все проверяется.

    либо простейшая программа консольная из 10 строк на java|python|что нравится, которая слушает сокет и выдает на экран факт TCP/IP коннекта либо nginx (если импотентен написать эти 10 строк, а потентен настроить nginx)

    public static void main(String[] args) throws Throwable {
    ServerSocket ss = new ServerSocket(6666);
    while (true) {
    Socket s = ss.accept();
    System.out.println("-------------- Client accepted --------------");

    ну и сделать так, что бы логе всех программ прошла нужная строка типа  ${jndi:ldap://localhost:6666}

    К слову, даже если в лог не выводится строка с ${jndi.. (не тот уровень логирования, например), то SpringBoot все равно ломится на ldap при получении чего ни будь типа

    curl -H "qqqqqq: ${jndi:ldap://localhost:6666}" --url http://localhost:8080/version

    Так же себя ведут и не SpringBoot web сервис c jetty и grizzly (что сам проверял).

    Ну или если не web приложенее, то по принципу "в лог должно попасть ..".

    Это самый надежный способ проверки наличия уязвимости и что она еще не купирована удалением ли класса или другим методом.

    Правда отличить от какой программы (когда сервисов в цепочке обработки мого) пошел запрос не просто, но зато сразу видно что не все купировано.

    А по прикладным логам программ и не поймешь. Разве что времени ответа (log4j2 притормаживает с выводом строчки где то на 3-5 сек если нет ответа от ldap сервера). Но если логирование ассинхронное и в лог по уровню логирования ничего не попадает, то вообще не поймешь ломится куда или нет.