
Исследовательский репозиторий для CVE-2026-68121 — use-after-free в PPPoE ядра Linux в pppoe_sendmsg(), позволяющей локальное повышение привилегий, с PoC, анализом первопричины и настройкой лабораторной среды.
PPPoEject
Уязвимость повреждения памяти ядра Linux в пути передачи PPPoE,
вызванная устаревшим указателем на заголовок sk_buff после того, как
callback заголовка устройства перераспределяет голову skb.
Этот репозиторий предназначен только для авторизованных исследований в области безопасности, анализа уязвимостей ядра, сред CTF и защитного тестирования.
Не запускайте код proof-of-concept против систем без явного разрешения.
| Поле | Детали |
|---|---|
| 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 |
| Вектор атаки | Локальный |
| Сложность атаки | Низкая |
| Требуемые привилегии | Низкие |
| Взаимодействие с пользователем | Отсутствует |
| Статус | Исправлено |
Запись CVE определяет уязвимость как устаревший указатель заголовка PPPoE,
который может стать недействительным, когда dev_hard_header() перераспределяет
голову skb.
Уязвимость существует в:
drivers/net/ppp/pppoe.c
в пределах:
pppoe_sendmsg()
Уязвимая последовательность концептуально выглядит так:
pppoe_sendmsg()
│
▼
Save PPPoE header pointer
│
▼
dev_hard_header()
│
▼
skb head may be reallocated
│
▼
Old pointer becomes stale
│
▼
PPPoE writes through stale pointer
│
▼
Use-After-Free
│
▼
Kernel memory corruption
Сетевой код Linux позволяет колбэкам заголовков устройств перераспределять
голову sk_buff. Поэтому указатель на старую голову нельзя безопасно использовать повторно
после возврата из dev_hard_header().
Основная проблема — нарушение времени жизни.
pppoe_sendmsg() получает указатель на заголовок PPPoE перед вызовом:
dev_hard_header()
Однако этот callback может привести к смещению начала skb.
Концептуально:
Before callback:
skb
┌──────────────────────────────┐
│ Ethernet │ PPPoE │ Payload │
└──────────┴───────┴───────────┘
▲
│
stale pointer
After skb expansion:
old skb head ──X──► freed
new skb head
┌────────────────────────────────────┐
│ Ethernet │ PPPoE │ Payload │
└──────────┴───────┴─────────────────┘
▲
│
valid location
Старый указатель по-прежнему ссылается на освобождённый участок памяти.
Когда PPPoE впоследствии записывает заголовок через этот указатель, ядро выполняет запись после освобождения (use-after-free write).
Описанное срабатывание связано с гонкой вокруг copy_from_user() и изменениями
операций заголовка team-устройства.
Одна из описанных последовательностей:
PPPoE sendmsg()
│
▼
copy_from_user() blocks
│
│
├───────────────┐
│ │
▼ ▼
Team device changes First non-Ethernet
header operations port is added
│
▼
Delegated GRE callback
│
▼
skb head expansion
│ │
└───────────────┘
│
▼
stale PPPoE pointer
│
▼
use-after-free write
В записи CVE отмечается, что это может произойти, когда первый не-Ethernet порт добавляется в пустое team-устройство и делегированный callback заголовка GRE расширяет head у skb.
Уязвимость может привести к:
Опубликованный в CVE вектор CVSS:
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()
│
▼
Network device header callback
│
▼
Potential skb head expansion
│
▼
PPPoE stale header pointer
│
▼
UAF write
Уязвимый код, таким образом, не является просто универсальным парсером PPPoE-пакетов; критическое условие заключается во взаимодействии между передачей через PPPoE-сокет и динамическим перераспределением головы skb.
Исправление в upstream озаглавлено:
pppoe: reload header pointer after dev_hard_header()
Исправление перезагружает заголовок PPPoE через смещение сетевого заголовка skb после создания заголовка устройства.
Важное свойство заключается в следующем:
Before:
header pointer
│
▼
dev_hard_header()
│
▼
skb moves
│
▼
pointer = stale ❌
After:
dev_hard_header()
│
▼
skb may move
│
▼
reload header using skb offset
│
▼
pointer = valid ✅
pskb_expand_head() обновляет соответствующие смещения skb при перемещении заголовка skb, что делает поиск по смещению безопасным после перераспределения памяти.
| Свойство безопасности | Уязвимая | Исправленная |
|---|---|---|
| Указатель на заголовок сохраняется до callback | ✅ | — |
| Заголовок skb может перемещаться | ✅ | ✅ |
| Указатель обновляется после callback | ❌ | ✅ |
| Разыменование устаревшего указателя | Возможно | Предотвращено |
| Запись use-after-free | Возможно | Смягчено |
| Повреждение памяти ядра | Возможно | Смягчено |
Контролируемую лабораторию можно организовать следующим образом: