
Исследовательский репозиторий для CVE-2026-68121 — use-after-free в PPPoE ядра Linux в pppoe_sendmsg(), позволяющей локальное повышение привилегий, с PoC, анализом первопричины и настройкой лабораторной среды.
PPPoEject
Уязвимость повреждения памяти в ядре Linux в пути передачи PPPoE,
вызванная устаревшим указателем на заголовок sk_buff после того, как
callback заголовка устройства перераспределяет head skb.
Этот репозиторий предназначен только для авторизованных исследований в области безопасности, анализа уязвимостей ядра, сред CTF и защитного тестирования.
Не запускайте код proof-of-concept против систем без явного разрешения.
Запись CVE определяет уязвимость как устаревший указатель на заголовок PPPoE,
который может стать недействительным, когда dev_hard_header() перераспределяет head skb.
Уязвимость существует в:
drivers/net/ppp/pppoe.c
внутри:
pppoe_sendmsg()
Уязвимая последовательность концептуально выглядит так:
pppoe_sendmsg()
│
▼
Сохранение указателя на заголовок PPPoE
│
▼
dev_hard_header()
│
▼
head skb может быть перераспределён
│
▼
Старый указатель становится устаревшим
│
▼
PPPoE выполняет запись через устаревший указатель
│
▼
Use-After-Free
│
▼
Повреждение памяти ядра
Сетевой код Linux допускает, что callback заголовка устройства может
перераспределить head sk_buff. Поэтому указатель на старый head не может
безопасно использоваться после возврата из dev_hard_header().
Основная проблема — нарушение времени жизни.
pppoe_sendmsg() получает указатель на заголовок PPPoE перед вызовом:
dev_hard_header()
Однако этот callback может привести к перемещению head skb.
Концептуально:
До callback:
skb
┌──────────────────────────────┐
│ Ethernet │ PPPoE │ Payload │
└──────────┴───────┴───────────┘
▲
│
устаревший указатель
После расширения skb:
старый head skb ──X──► освобождён
новый head skb
┌────────────────────────────────────┐
│ Ethernet │ PPPoE │ Payload │
└──────────┴───────┴─────────────────┘
▲
│
корректное расположение
Старый указатель по-прежнему ссылается на освобождённую область памяти.
Когда PPPoE впоследствии записывает заголовок через этот указатель, ядро выполняет запись use-after-free.
Документированный триггер включает гонку вокруг copy_from_user() и
изменения операций заголовка team-устройства.
Одна из описанных последовательностей:
PPPoE sendmsg()
│
▼
copy_from_user() блокируется
│
│
├───────────────┐
│ │
▼ ▼
Team-устройство Добавляется первый
меняет операции не-Ethernet порт
заголовка │
▼
Делегированный GRE callback
│
▼
Расширение head skb
│ │
└───────────────┘
│
▼
устаревший указатель PPPoE
│
▼
запись use-after-free
Запись CVE отмечает, что это может произойти, когда первый не-Ethernet порт добавляется к пустому team-устройству и делегированный GRE callback заголовка расширяет head skb.
Уязвимость может привести к:
Опубликованный вектор CVSS для CVE:
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
с базовой оценкой 7.8 High.
Соответствующие компоненты:
PF_PPPOX / PPPoE socket
│
▼
pppoe_sendmsg()
│
▼
sk_buff (skb)
│
▼
dev_hard_header()
│
▼
Callback заголовка сетевого устройства
│
▼
Потенциальное расширение head skb
│
▼
Устаревший указатель на заголовок PPPoE
│
▼
UAF-запись
Таким образом, уязвимый код — это не просто универсальный парсер пакетов PPPoE; критическое условие заключается во взаимодействии между передачей через PPPoE-сокет и динамическим перераспределением head skb.
Исправление в upstream называется:
pppoe: reload header pointer after dev_hard_header()
Исправление перезагружает заголовок PPPoE через смещение сетевого заголовка skb после создания заголовка устройства.
Важное свойство:
До:
указатель на заголовок
│
▼
dev_hard_header()
│
▼
skb перемещается
│
▼
указатель = устаревший ❌
После:
dev_hard_header()
│
▼
skb может переместиться
│
▼
перезагрузка заголовка с использованием смещения skb
│
▼
указатель = корректный ✅
pskb_expand_head() обновляет соответствующее смещение skb при
перемещении head skb, что делает поиск по смещению безопасным после
перераспределения.
Контролируемую лабораторию можно организовать так:
┌───────────────────────────────────────────────┐
│ Linux VM │
│ │
│ ┌───────────────┐ │
│ │ PPPoE Socket │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ pppoe_sendmsg │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Team │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ GRE │ │
│ └───────────────┘ │
│ │
└───────────────────────────────────────────────┘
Полезные инструменты отладки ядра:
gdb
pwndbg
gef
crash
objdump
readelf
pahole
Мониторинг сообщений ядра:
sudo dmesg -w
Проверка поддержки PPPoE:
lsmod | grep pppoe
Проверка доступных модулей PPP:
find /lib/modules/$(uname -r) -iname '*pppoe*'
Проверка текущего работающего ядра:
uname -r
Проверка конфигурации, связанной с PPPoE:
grep -E 'CONFIG_PPP|CONFIG_PPPOE' \
/boot/config-$(uname -r)
Типичные соответствующие опции включают:
CONFIG_PPP
CONFIG_PPP_ASYNC
CONFIG_PPP_SYNC_TTY
CONFIG_PPPOE
Для контролируемого исследования ядра:
01. Собрать уязвимое ядро
↓
02. Загрузить изолированную VM
↓
03. Включить поддержку PPPoE
↓
04. Создать контролируемую сетевую топологию
↓
05. Настроить взаимодействие team/GRE
↓
06. Задействовать PPPoE sendmsg()
↓
07. Отслеживать время жизни skb
↓
08. Собрать диагностику ядра
↓
09. Применить upstream-исправление
↓
10. Повторить и сравнить
Цель — безопасно воспроизвести нарушение времени жизни памяти и сравнить поведение уязвимой и исправленной версий.
CVE-2026-68121-PPPoEject/
│
├── README.md
│
├── exploit/
│ ├── poc.c
│ └── Makefile
│
├── analysis/
│ ├── root-cause.md
│ ├── pppoe-sendmsg.md
│ ├── skb-lifetime.md
│ └── patch-analysis.md
│
├── kernel/
│ ├── vulnerable/
│ └── patched/
│
├── lab/
│ ├── setup.sh
│ ├── cleanup.sh
│ └── topology.md
│
├── screenshots/
│
├── docs/
│ └── research-notes.md
│
└── LICENSE
Рекомендуемая мера — обновление до ядра Linux, содержащего upstream-исправление или соответствующий backport дистрибутива.
Для Debian/Kali:
sudo apt update
sudo apt full-upgrade
Затем перезагрузка:
sudo reboot
Проверка работающего ядра:
uname -r
Backports дистрибутивов могут использовать другие номера версий, поэтому администраторам следует сверять установленный пакет с рекомендациями по безопасности дистрибутива. В настоящее время Debian указывает исправленные версии, включая 6.1.187-1 для Bookworm и 6.12.101-1 для Trixie.
Стабильные ветки Linux содержат исправление в нескольких поддерживаемых ветках. Запись CVE перечисляет соответствующие стабильные коммиты и указывает затронутый исходный файл:
drivers/net/ppp/pppoe.c
Уязвимая история начинается с реализации PPPoE в ядре Linux, а серия
исправляющих коммитов завершается upstream-исправлением, представленным
7a56e7c9b08e08fd55a1bcada24cf4fe3782b722 в данных CVE.
Нельзя считать указатель на skb действительным после callback, способного перераспределить head skb.
Сетевые callback могут изменять лежащую в основе структуру памяти.
Исправление демонстрирует, почему смещение относительно skb безопаснее, чем сохранение сырого указателя через потенциально перемещающую операцию.
Уязвимое состояние зависит от параллельной активности вокруг передачи пакетов и конфигурации сетевого устройства.
Устаревший указатель в сетевом коде ядра может стать примитивом повреждения памяти с последствиями для конфиденциальности, целостности и доступности.
drivers/net/ppp/pppoe.cpppoe_sendmsg()pppoe: reload header pointer after dev_hard_header()Linux Kernel · PPPoE · Use-After-Free · Kernel Security · LPE
Research • Analyze • Reproduce • Harden
| Поле | Детали |
|---|
| CVE | CVE-2026-68121 |
| Кодовое имя | PPPoEject |
| Компонент | Linux Kernel |
| Подсистема | PPPoE / Networking |
| Затронутый файл | drivers/net/ppp/pppoe.c |
| Основная функция | pppoe_sendmsg() |
| Класс ошибки | Use-After-Free |
| Воздействие | Повреждение памяти ядра |
| Потенциальное воздействие | Локальное повышение привилегий |
| CVSS v3.1 | 7.8 — High |
| Вектор атаки | Локальный |
| Сложность атаки | Низкая |
| Требуемые привилегии | Низкие |
| Взаимодействие с пользователем | Отсутствует |
| Статус | Исправлено |
| Свойство безопасности | Уязвимая | Исправленная |
|---|
| Указатель на заголовок сохранён до callback | ✅ | — |
| head skb может перемещаться | ✅ | ✅ |
| Указатель обновляется после callback | ❌ | ✅ |
| Разыменование устаревшего указателя | Возможно | Предотвращено |
| Запись use-after-free | Возможно | Устранено |
| Повреждение памяти ядра | Возможно | Устранено |