PPPoEject
Linux 内核 PPPoE 发送路径中的内存破坏漏洞,
由设备头回调重新分配 skb 头后遗留的 sk_buff 头指针悬空所导致。
本仓库仅用于授权安全研究、内核漏洞分析、CTF 环境以及防御性测试。
请勿在未获得明确授权的情况下对系统执行概念验证代码。
CVE 记录将该漏洞描述为陈旧的 PPPoE 头指针,当 dev_hard_header() 重新分配 skb 头时该指针可能失效。
该漏洞存在于:
drivers/net/ppp/pppoe.c
中的:
pppoe_sendmsg()
易受攻击的序列概念上为:
pppoe_sendmsg()
│
▼
保存 PPPoE 头指针
│
▼
dev_hard_header()
│
▼
skb 头可能被重新分配
│
▼
旧指针变为悬空
│
▼
PPPoE 通过悬空指针写入
│
▼
释放后使用
│
▼
内核内存破坏
Linux 网络代码允许设备头回调重新分配 sk_buff 头。因此,在 dev_hard_header() 返回后,指向旧头的指针无法安全地重用。
核心问题是生命周期违规。
pppoe_sendmsg() 在调用以下函数之前获取指向 PPPoE 头的指针:
dev_hard_header()
然而,该回调可能导致 skb 头移动。
概念上:
回调前:
skb
┌──────────────────────────────┐
│ Ethernet │ PPPoE │ Payload │
└──────────┴───────┴───────────┘
▲
│
悬空指针
skb 扩展后:
旧 skb 头 ──X──► 已释放
新 skb 头
┌────────────────────────────────────┐
│ Ethernet │ PPPoE │ Payload │
└──────────┴───────┴─────────────────┘
▲
│
有效位置
旧指针仍然引用已释放的分配。
当 PPPoE 随后通过该指针写入头时,内核执行了一次释放后使用写入。
文档记录的触发条件涉及围绕 copy_from_user() 的竞态以及 team 设备头操作的变更。
一种描述的序列为:
PPPoE sendmsg()
│
▼
copy_from_user() 阻塞
│
│
├───────────────┐
│ │
▼ ▼
Team 设备变更 第一个非以太网
头操作 端口被添加
│
▼
委托的 GRE 回调
│
▼
skb 头扩展
│ │
└───────────────┘
│
▼
悬空的 PPPoE 指针
│
▼
释放后使用写入
CVE 记录指出,当第一个非以太网端口被添加到空的 team 设备,且委托的 GRE 头回调扩展 skb 头时,可能发生此情况。
该漏洞可能导致:
CVE 公布的 CVSS 向量为:
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
基础评分为 7.8 高。
相关组件为:
PF_PPPOX / PPPoE socket
│
▼
pppoe_sendmsg()
│
▼
sk_buff (skb)
│
▼
dev_hard_header()
│
▼
网络设备头回调
│
▼
潜在的 skb 头扩展
│
▼
PPPoE 悬空头指针
│
▼
UAF 写入
因此,易受攻击的代码并非简单的通用 PPPoE 数据包解析器;关键条件是 PPPoE 套接字传输与动态 skb 头重新分配之间的交互。
上游修复的标题为:
pppoe: reload header pointer after dev_hard_header()
该修复在设备头创建后,通过 skb 的网络头偏移重新加载 PPPoE 头。
重要特性是:
修复前:
头指针
│
▼
dev_hard_header()
│
▼
skb 移动
│
▼
指针 = 悬空 ❌
修复后:
dev_hard_header()
│
▼
skb 可能移动
│
▼
使用 skb 偏移重新加载头
│
▼
指针 = 有效 ✅
当 skb 头被重新定位时,pskb_expand_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. 应用上游补丁
↓
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 内核。
对于 Debian/Kali:
sudo apt update
sudo apt full-upgrade
然后重启:
sudo reboot
验证正在运行的内核:
uname -r
发行版回溯移植可能使用不同的版本号,因此管理员应根据发行版的安全公告验证其安装的软件包。Debian 目前列出的修复版本包括 Bookworm 的 6.1.187-1 和 Trixie 的 6.12.101-1。
Linux 稳定树在多个维护分支中包含该修复。CVE 记录列出了相应的稳定提交,并将受影响的源文件标识为:
drivers/net/ppp/pppoe.c
易受攻击的历史始于 Linux 内核 PPPoE 实现,修复提交系列终止于 CVE 数据中由 7a56e7c9b08e08fd55a1bcada24cf4fe3782b722 表示的上游修复。
在可能重新分配 skb 头的回调之后,不能假定指向 skb 的指针仍然有效。
网络回调可能改变底层内存布局。
该补丁展示了为什么在可能重新定位的操作中,skb 相对偏移比保留原始指针更安全。
易受攻击的状态依赖于数据包传输和网络设备配置周围的并发活动。
内核网络代码中的悬空指针可能成为具有机密性、完整性和可用性后果的内存破坏原语。
drivers/net/ppp/pppoe.cpppoe_sendmsg()pppoe: reload header pointer after dev_hard_header()Linux Kernel · PPPoE · Use-After-Free · Kernel Security · LPE
研究 • 分析 • 复现 • 加固
| 字段 | 详情 |
|---|
| CVE | CVE-2026-68121 |
| 代号 | PPPoEject |
| 组件 | Linux 内核 |
| 子系统 | PPPoE / 网络 |
| 受影响文件 | drivers/net/ppp/pppoe.c |
| 主要函数 | pppoe_sendmsg() |
| 漏洞类别 | 释放后使用 |
| 影响 | 内核内存破坏 |
| 潜在影响 | 本地权限提升 |
| CVSS v3.1 | 7.8 — 高 |
| 攻击向量 | 本地 |
| 攻击复杂度 | 低 |
| 所需权限 | 低 |
| 用户交互 | 无 |
| 状态 | 已修补 |
| 安全属性 | 易受攻击 | 已修补 |
|---|
| 回调前保存头指针 | ✅ | — |
| skb 头可以移动 | ✅ | ✅ |
| 回调后刷新指针 | ❌ | ✅ |
| 悬空指针解引用 | 可能 | 已阻止 |
| 释放后使用写入 | 可能 | 已缓解 |
| 内核内存破坏 | 可能 | 已缓解 |