Rat5ak/CVE-2026-41285-OpenBSD-v6daemons-go-brrr

GitHub: Rat5ak/CVE-2026-41285-OpenBSD-v6daemons-go-brrr

针对 OpenBSD slaacd/rad 守护进程的 CVE-2026-41285 PoC,通过发送一个 ND 选项长度为零的 ICMPv6 数据包触发整数下溢无限循环,实现永久性 IPv6 SLAAC 服务拒绝。

Stars: 0 | Forks: 0

# CVE-2026-41285:一个数据包导致 OpenBSD 上的 IPv6 瘫痪 来自本地网络的一个特制 ICMPv6 数据包会永久挂起 `slaacd` 和/或 `rad`。IPv6 SLAAC 地址自动配置会失效,直到有人手动 重启该守护进程。无需认证,无需权限,仅需 18 字节的 ICMPv6 负载。 | | | |------------|--------------------------------------------------------------------| | CVE | CVE-2026-41285 | | 漏洞类别 | 整数下溢导致的无限循环 | | 根本原因 | ND 选项解析器执行 `nd_opt_len * 8 - 2` 时未检查 len==0 | | 组件 | `sbin/slaacd/engine.c`, `usr.sbin/rad/engine.c` | | 影响 | 导致 IPv6 SLAAC (slaacd) 或 RA 服务 (rad) 遭受永久性 DoS | | 前提条件 | 同一 L2 网络段上的任何设备 | | 测试环境 | OpenBSD 7.8 GENERIC amd64 | ## 漏洞详情 RFC 4861 §4.6 规定长度为零的 ND 选项是无效的,必须被 静默丢弃。内核自身在 `sys/netinet6/nd6.c` 中的 `nd6_options()` 正确地执行了这一点。但是,在该检查起作用之前,原始的 ICMPv6 数据包 已经被传送到用户空间 socket。 `slaacd` 和 `rad` 都会自行解析 ND 选项。其循环代码如下所示: ``` while (len > 0) { // ... optlen = nd_opt->nd_opt_len * 8 - 2; // nd_opt_len is uint8_t if (optlen > len) break; len += 2; // advance pointer by optlen... which is (uint32_t)-2 promoted from int } ``` 当 `nd_opt_len == 0` 时:表达式 `0 * 8 - 2` 会被提升为 `int` → `-2`。 判断条件 `(-2 > len)` 始终为假(有符号比较,len 为正值)。 随后 `len += 2` 并且指针后退 2 个字节。循环永远不会向前推进。 CPU 占用率会一直保持在 100%。永久死循环。 内核验证了它自己的副本。而用户空间的守护进程获取的则是原始数据。 没有人通知 slaacd。 ## 影响 - 一个数据包 → slaacd 引擎卡在无限循环中,CPU 占用率达 100% - 所有后续的 RA 均被忽略 → 无法配置新的 SLAAC 地址 - 现有地址最终过期(生命周期耗尽,无法续期) - 所有由 slaacd 管理的接口上的 IPv6 连通性会逐渐完全中断 - 针对 rad 的相同攻击:一个特制的 RS 即可使该链路的 RA 服务瘫痪 - 恢复需要手动执行 `rcctl restart slaacd` 或重启系统 ## PoC ``` python3 poc/kill_slaacd.py ``` 需要使用 scapy。发送一个带有一个 `nd_opt_len = 0` 的 ND 选项的 路由通告(Router Advertisement)。就是这样。选项类型并不重要(PoC 使用了类型 200 / 未知)。 完整的端到端证明(展示 SLAAC 正常工作 -> 发起攻击 -> SLAAC 瘫痪): ``` python3 poc/prove_dos.py ``` ## 证据 ``` ── Before exploit ── SLAAC addresses: 2001:db8:1:0:df6f:edeb:6e3a:2640, ... Engine CPU: 0.0% ── After one packet ── Engine CPU: 23.1% → 43.3% (climbing) New RA with 2001:db8:2::/64 sent → no address configured slaacd is dead. IPv6 autoconf: DEAD. ``` ## 先前案例 与 CVE-2022-27881 和 CVE-2022-27882 的攻击面相同(早期的 slaacd 在 engine.c 中的无限循环,同样发生在 ND 选项解析时)。这是同一类 漏洞的一个新实例 —— 之前的修复并没有覆盖所有的解析循环。 ## 修复方案 在对 `nd_opt_len` 进行算术运算之前检查 `nd_opt_len == 0`。并跳出循环。 这正是内核在 `nd6_options()` 中已经执行的操作: ``` if (nd_opt->nd_opt_len == 0) break; // or: goto bad; ``` 针对 slaacd 的 `parse_ra()`、`debug_log_ra()` 以及 rad 的 RS 解析器的建议补丁 —— 这三个循环都需要加上相同的一行代码防护。 ## 时间线 - 2026-04-12:附带 PoC 和补丁报告至 security@openbsd.org - 2026-04-20:由 MITRE 分配了 CVE-2026-41285 ## 免责声明 这是一个本地网络的 DoS 攻击。如果你与运行着 slaacd 的 OpenBSD 设备处于同一个 L2 网段,一个数据包就能冻结其 IPv6。请不要将其发送至 你不拥有的网络。如果你正在运行 OpenBSD,请检查是否有补丁或自行添加 len==0 的防护。 Daniel Wade - [GitHub](https://github.com/Rat5ak) · [Twitter/X](https://x.com/Nadsec11) · [Bluesky](https://bsky.app/profile/nadsec.online) · [nadsec.online](https://nadsec.online/)
标签:0day挖掘, C/C++, CVE-2026-41285, DoS, ICMPv6, IPv6, L2网络攻击, NDP, OpenBSD, PowerShell, SLAAC, 事务性I/O, 内核安全, 内核驱动, 安全漏洞, 拒绝服务, 整数下溢, 无限循环, 漏洞分析, 网络协议, 路径探测, 路由发现协议, 逆向工具