diff --git a/honeypots/__init__.py b/honeypots/__init__.py index c9bcb8d..450a1ee 100644 --- a/honeypots/__init__.py +++ b/honeypots/__init__.py @@ -4,6 +4,20 @@ from .dns_server import QDNSServer from .elastic_server import QElasticServer from .ftp_server import QFTPServer +from .helper import ( + check_privileges, + clean_all, + close_port_wrapper, + disable_logger, + get_free_port, + get_running_servers, + kill_server_wrapper, + kill_servers, + postgres_class, + server_arguments, + set_local_vars, + setup_logger, +) from .http_proxy_server import QHTTPProxyServer from .http_server import QHTTPServer from .https_server import QHTTPSServer @@ -30,4 +44,49 @@ from .ssh_server import QSSHServer from .telnet_server import QTelnetServer from .vnc_server import QVNCServer -from .helper import server_arguments, clean_all, kill_servers, get_free_port, close_port_wrapper, kill_server_wrapper, setup_logger, disable_logger, postgres_class, get_running_servers, set_local_vars, check_privileges + +__all__ = [ + "QBSniffer", + "QDHCPServer", + "QDNSServer", + "QElasticServer", + "QFTPServer", + "QHTTPProxyServer", + "QHTTPSServer", + "QHTTPServer", + "QIMAPServer", + "QIPPServer", + "QIRCServer", + "QLDAPServer", + "QMSSQLServer", + "QMemcacheServer", + "QMysqlServer", + "QNTPServer", + "QOracleServer", + "QPJLServer", + "QPOP3Server", + "QPostgresServer", + "QRDPServer", + "QRedisServer", + "QSIPServer", + "QSMBServer", + "QSMTPServer", + "QSNMPServer", + "QSOCKS5Server", + "QSSHServer", + "QTelnetServer", + "QVNCServer", + "check_privileges", + "clean_all", + "close_port_wrapper", + "disable_logger", + "get_free_port", + "get_running_servers", + "kill_server_wrapper", + "kill_servers", + "main_logic", + "postgres_class", + "server_arguments", + "set_local_vars", + "setup_logger", +] diff --git a/honeypots/__main__.py b/honeypots/__main__.py index 096dfaa..886c875 100644 --- a/honeypots/__main__.py +++ b/honeypots/__main__.py @@ -1,13 +1,44 @@ #!/usr/bin/env python from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') -filterwarnings('ignore', category=RuntimeWarning, module='runpy') -all_servers = ['QDNSServer', 'QFTPServer', 'QHTTPProxyServer', 'QHTTPServer', 'QHTTPSServer', 'QIMAPServer', 'QMysqlServer', 'QPOP3Server', 'QPostgresServer', 'QRedisServer', 'QSMBServer', 'QSMTPServer', 'QSOCKS5Server', 'QSSHServer', 'QTelnetServer', 'QVNCServer', 'QElasticServer', 'QMSSQLServer', 'QLDAPServer', 'QNTPServer', 'QMemcacheServer', 'QOracleServer', 'QSNMPServer', 'QSIPServer', 'QIRCServer', 'QRDPServer', 'QDHCPServer', 'QPJLServer', 'QIPPServer'] +filterwarnings(action="ignore", module=".*OpenSSL.*") +filterwarnings("ignore", category=RuntimeWarning, module="runpy") + +all_servers = [ + "QDNSServer", + "QFTPServer", + "QHTTPProxyServer", + "QHTTPServer", + "QHTTPSServer", + "QIMAPServer", + "QMysqlServer", + "QPOP3Server", + "QPostgresServer", + "QRedisServer", + "QSMBServer", + "QSMTPServer", + "QSOCKS5Server", + "QSSHServer", + "QTelnetServer", + "QVNCServer", + "QElasticServer", + "QMSSQLServer", + "QLDAPServer", + "QNTPServer", + "QMemcacheServer", + "QOracleServer", + "QSNMPServer", + "QSIPServer", + "QIRCServer", + "QRDPServer", + "QDHCPServer", + "QPJLServer", + "QIPPServer", +] temp_honeypots = [] -from signal import signal, alarm, SIGALRM, SIG_IGN, SIGTERM, SIGINT, SIGTSTP +from signal import signal, alarm, SIGALRM, SIGTERM, SIGINT, SIGTSTP from time import sleep from functools import wraps @@ -33,12 +64,12 @@ def __init__(self, strategy): self.strategy = strategy def await_termination(self): - if self.strategy == 'input': - input('') - elif self.strategy == 'signal': + if self.strategy == "input": + input("") + elif self.strategy == "signal": SignalFence([SIGTERM, SIGINT, SIGTSTP]).wait_on_fence() else: - raise Exception('Unknown termination strategy: ' + strategy) + raise Exception("Unknown termination strategy: " + strategy) def timeout(seconds=10): @@ -47,6 +78,7 @@ def decorator(func): def wrapper(*args, **kwargs): def handle_timeout(signum, frame): raise Exception() + signal(SIGALRM, handle_timeout) alarm(seconds) result = None @@ -55,28 +87,33 @@ def handle_timeout(signum, frame): finally: alarm(0) return result + return wrapper + return decorator def list_all_honeypots(): for honeypot in all_servers: - print(honeypot[1:].replace('Server', '').lower()) + print(honeypot[1:].replace("Server", "").lower()) @timeout(5) def server_timeout(object, name): try: - print('[x] Start testing {}'.format(name)) + print(f"[x] Start testing {name}") object.test_server() except BaseException: - print('[x] Timeout {}'.format(name)) - print('[x] Done testing {}'.format(name)) + print(f"[x] Timeout {name}") + print(f"[x] Done testing {name}") def main_logic(): - - from honeypots import QDNSServer, QFTPServer, QHTTPProxyServer, QHTTPServer, QHTTPSServer, QIMAPServer, QMysqlServer, QPOP3Server, QPostgresServer, QRedisServer, QSMBServer, QSMTPServer, QSOCKS5Server, QSSHServer, QTelnetServer, QVNCServer, QMSSQLServer, QElasticServer, QLDAPServer, QNTPServer, QMemcacheServer, QOracleServer, QSNMPServer, QSIPServer, QIRCServer, QRDPServer, QDHCPServer, QPJLServer, QIPPServer, server_arguments, clean_all, postgres_class, setup_logger, QBSniffer, get_running_servers, check_privileges + from honeypots import ( + clean_all, + setup_logger, + check_privileges, + ) from atexit import register from argparse import ArgumentParser, SUPPRESS from sys import stdout @@ -84,105 +121,161 @@ def main_logic(): from netifaces import ifaddresses, AF_INET, AF_LINK, interfaces from psutil import Process, net_io_counters from uuid import uuid4 - from json import JSONEncoder, dumps, load + from json import load from os import geteuid def exit_handler(): - print('[x] Cleaning') + print("[x] Cleaning") clean_all() sleep(1) class _ArgumentParser(ArgumentParser): def error(self, message): - self.exit(2, 'Error: %s\n' % (message)) + self.exit(2, "Error: %s\n" % (message)) - ARG_PARSER = _ArgumentParser(description='Qeeqbox/honeypots customizable honeypots for monitoring network traffic, bots activities, and username\\password credentials', usage=SUPPRESS) + ARG_PARSER = _ArgumentParser( + description="Qeeqbox/honeypots customizable honeypots for monitoring network traffic, bots activities, and username\\password credentials", + usage=SUPPRESS, + ) ARG_PARSER._action_groups.pop() - ARG_PARSER_SETUP = ARG_PARSER.add_argument_group('Arguments') - ARG_PARSER_SETUP.add_argument('--setup', help='target honeypot E.g. ssh or you can have multiple E.g ssh,http,https', metavar='', default='') - ARG_PARSER_SETUP.add_argument('--list', action='store_true', help='list all available honeypots') - ARG_PARSER_SETUP.add_argument('--kill', action='store_true', help='kill all honeypots') - ARG_PARSER_SETUP.add_argument('--verbose', action='store_true', help='Print error msgs') - ARG_PARSER_OPTIONAL = ARG_PARSER.add_argument_group('Honeypots options') - ARG_PARSER_OPTIONAL.add_argument('--ip', help='Override the IP', metavar='', default='') - ARG_PARSER_OPTIONAL.add_argument('--port', help='Override the Port (Do not use on multiple!)', metavar='', default='') - ARG_PARSER_OPTIONAL.add_argument('--username', help='Override the username', metavar='', default='') - ARG_PARSER_OPTIONAL.add_argument('--password', help='Override the password', metavar='', default='') - ARG_PARSER_OPTIONAL.add_argument('--config', help='Use a config file for honeypots settings', metavar='', default='') - ARG_PARSER_OPTIONAL.add_argument('--options', type=str, help='Extra options', metavar='', default='') - ARG_PARSER_OPTIONAL_2 = ARG_PARSER.add_argument_group('General options') - ARG_PARSER_OPTIONAL_2.add_argument('--termination-strategy', help='Determines the strategy to terminate by', default='input', choices=['input', 'signal']) - ARG_PARSER_OPTIONAL_2.add_argument('--test', default='', metavar='', help='Test a honeypot') - ARG_PARSER_OPTIONAL_2.add_argument('--auto', help='Setup the honeypot with random port', action='store_true') - ARG_PARSER_CHAMELEON = ARG_PARSER.add_argument_group('Chameleon') - ARG_PARSER_CHAMELEON.add_argument('--chameleon', action='store_true', help='reserved for chameleon project') - ARG_PARSER_CHAMELEON.add_argument('--sniffer', action='store_true', help='sniffer - reserved for chameleon project') - ARG_PARSER_CHAMELEON.add_argument('--iptables', action='store_true', help='iptables - reserved for chameleon project') + ARG_PARSER_SETUP = ARG_PARSER.add_argument_group("Arguments") + ARG_PARSER_SETUP.add_argument( + "--setup", + help="target honeypot E.g. ssh or you can have multiple E.g ssh,http,https", + metavar="", + default="", + ) + ARG_PARSER_SETUP.add_argument( + "--list", action="store_true", help="list all available honeypots" + ) + ARG_PARSER_SETUP.add_argument("--kill", action="store_true", help="kill all honeypots") + ARG_PARSER_SETUP.add_argument("--verbose", action="store_true", help="Print error msgs") + ARG_PARSER_OPTIONAL = ARG_PARSER.add_argument_group("Honeypots options") + ARG_PARSER_OPTIONAL.add_argument("--ip", help="Override the IP", metavar="", default="") + ARG_PARSER_OPTIONAL.add_argument( + "--port", help="Override the Port (Do not use on multiple!)", metavar="", default="" + ) + ARG_PARSER_OPTIONAL.add_argument( + "--username", help="Override the username", metavar="", default="" + ) + ARG_PARSER_OPTIONAL.add_argument( + "--password", help="Override the password", metavar="", default="" + ) + ARG_PARSER_OPTIONAL.add_argument( + "--config", help="Use a config file for honeypots settings", metavar="", default="" + ) + ARG_PARSER_OPTIONAL.add_argument( + "--options", type=str, help="Extra options", metavar="", default="" + ) + ARG_PARSER_OPTIONAL_2 = ARG_PARSER.add_argument_group("General options") + ARG_PARSER_OPTIONAL_2.add_argument( + "--termination-strategy", + help="Determines the strategy to terminate by", + default="input", + choices=["input", "signal"], + ) + ARG_PARSER_OPTIONAL_2.add_argument("--test", default="", metavar="", help="Test a honeypot") + ARG_PARSER_OPTIONAL_2.add_argument( + "--auto", help="Setup the honeypot with random port", action="store_true" + ) + ARG_PARSER_CHAMELEON = ARG_PARSER.add_argument_group("Chameleon") + ARG_PARSER_CHAMELEON.add_argument( + "--chameleon", action="store_true", help="reserved for chameleon project" + ) + ARG_PARSER_CHAMELEON.add_argument( + "--sniffer", action="store_true", help="sniffer - reserved for chameleon project" + ) + ARG_PARSER_CHAMELEON.add_argument( + "--iptables", action="store_true", help="iptables - reserved for chameleon project" + ) ARGV = ARG_PARSER.parse_args() - PARSED_ARG_PARSER_OPTIONAL = {action.dest: getattr(ARGV, action.dest, '') for action in ARG_PARSER_OPTIONAL._group_actions} + PARSED_ARG_PARSER_OPTIONAL = { + action.dest: getattr(ARGV, action.dest, "") + for action in ARG_PARSER_OPTIONAL._group_actions + } config_data = None print("[!] For updates, check https://github.com/qeeqbox/honeypots") if check_privileges() == False: print("[!] Using system or well-known ports requires higher privileges (E.g. sudo -E)") - if ARGV.config != '': + if ARGV.config != "": with open(ARGV.config) as f: try: config_data = load(f) except Exception as e: - print('[!] Unable to load or parse config.json file', e) + print("[!] Unable to load or parse config.json file", e) exit() - if 'db_sqlite' in config_data['logs'] or 'db_postgres' in config_data['logs']: - uuid = 'honeypotslogger' + '_' + 'main' + '_' + str(uuid4())[:8] - if 'db_options' in config_data: - if 'drop' in config_data['db_options']: - print('[x] Setup Logger {} with a db, drop is on'.format(uuid)) - logs = setup_logger('main', uuid, ARGV.config, True) + if "db_sqlite" in config_data["logs"] or "db_postgres" in config_data["logs"]: + uuid = "honeypotslogger" + "_" + "main" + "_" + str(uuid4())[:8] + if "db_options" in config_data: + if "drop" in config_data["db_options"]: + print(f"[x] Setup Logger {uuid} with a db, drop is on") + logs = setup_logger("main", uuid, ARGV.config, True) else: - print('[x] Setup Logger {} with a db, drop is off'.format(uuid)) - logs = setup_logger('main', uuid, ARGV.config, False) + print(f"[x] Setup Logger {uuid} with a db, drop is off") + logs = setup_logger("main", uuid, ARGV.config, False) else: - logs = setup_logger('main', uuid, ARGV.config, True) + logs = setup_logger("main", uuid, ARGV.config, True) if ARGV.list: list_all_honeypots() elif ARGV.kill: clean_all() elif ARGV.chameleon and config_data is not None: - print('[x] Chameleon mode') - if config_data['sniffer_filter'] and config_data['sniffer_interface']: + print("[x] Chameleon mode") + if config_data["sniffer_filter"] and config_data["sniffer_interface"]: if not ARGV.test: if ARGV.sniffer: - current_interfaces = 'unknown' + current_interfaces = "unknown" try: - current_interfaces = ' '.join(interfaces()) - if config_data['sniffer_interface'] in current_interfaces: - print('[x] Your IP: {}'.format(ifaddresses(config_data['sniffer_interface'])[AF_INET][0]['addr'])) - print('[x] Your MAC: {}'.format(ifaddresses(config_data['sniffer_interface'])[AF_LINK][0]['addr'])) + current_interfaces = " ".join(interfaces()) + if config_data["sniffer_interface"] in current_interfaces: + print( + "[x] Your IP: {}".format( + ifaddresses(config_data["sniffer_interface"])[AF_INET][0][ + "addr" + ] + ) + ) + print( + "[x] Your MAC: {}".format( + ifaddresses(config_data["sniffer_interface"])[AF_LINK][0][ + "addr" + ] + ) + ) else: exit() except Exception as e: - print('[!] Unable to detect IP or MAC for [{}] interface, current interfaces are [{}]'.format(config_data['sniffer_interface'], current_interfaces), e) + print( + "[!] Unable to detect IP or MAC for [{}] interface, current interfaces are [{}]".format( + config_data["sniffer_interface"], current_interfaces + ), + e, + ) exit() if ARGV.iptables: try: - print('[x] Fixing iptables') - Popen('iptables -A OUTPUT -p tcp -m tcp --tcp-flags RST RST -j DROP', shell=True) + print("[x] Fixing iptables") + Popen( + "iptables -A OUTPUT -p tcp -m tcp --tcp-flags RST RST -j DROP", + shell=True, + ) except Exception as e: print(e) - print('[x] Wait for 10 seconds..') + print("[x] Wait for 10 seconds..") stdout.flush() sleep(2) - if ARGV.config != '': - print('[x] Config.json file overrides --ip, --port, --username and --password') + if ARGV.config != "": + print("[x] Config.json file overrides --ip, --port, --username and --password") - if isinstance(config_data['honeypots'], dict): - print('[x] Parsing honeypot [hard]') - for honeypot in config_data['honeypots']: + if isinstance(config_data["honeypots"], dict): + print("[x] Parsing honeypot [hard]") + for honeypot in config_data["honeypots"]: for _honeypot in all_servers: - if 'q{}server'.format(honeypot).lower() == _honeypot.lower(): - if ARGV.port != '': + if f"q{honeypot}server".lower() == _honeypot.lower(): + if ARGV.port != "": ARGV.port = int(ARGV.port) - PARSED_ARG_PARSER_OPTIONAL['port'] = ARGV.port + PARSED_ARG_PARSER_OPTIONAL["port"] = ARGV.port x = locals()[_honeypot](**PARSED_ARG_PARSER_OPTIONAL) if not ARGV.test: x.run_server(process=True) @@ -190,17 +283,19 @@ def error(self, message): server_timeout(x, _honeypot) x.kill_server() temp_honeypots.append(x) - elif isinstance(config_data['honeypots'], str): - print('[x] Parsing honeypot [easy]') - if ':' in config_data['honeypots']: - print('[!] You cannot bind ports with [:] in this mode, use the honeypots dict instead') + elif isinstance(config_data["honeypots"], str): + print("[x] Parsing honeypot [easy]") + if ":" in config_data["honeypots"]: + print( + "[!] You cannot bind ports with [:] in this mode, use the honeypots dict instead" + ) exit() - for server in config_data['honeypots'].split(','): + for server in config_data["honeypots"].split(","): for honeypot in all_servers: - if 'q{}server'.format(server).lower() == honeypot.lower(): - if ARGV.port != '': + if f"q{server}server".lower() == honeypot.lower(): + if ARGV.port != "": ARGV.port = int(ARGV.port) - PARSED_ARG_PARSER_OPTIONAL['port'] = ARGV.port + PARSED_ARG_PARSER_OPTIONAL["port"] = ARGV.port x = locals()[honeypot](**PARSED_ARG_PARSER_OPTIONAL) if not ARGV.test: x.run_server(process=True) @@ -209,24 +304,42 @@ def error(self, message): x.kill_server() temp_honeypots.append(x) else: - print('[!] Unable to parse honeypot from config.json file') + print("[!] Unable to parse honeypot from config.json file") exit() if ARGV.sniffer: - print('[x] Start sniffer') - x = locals()['QBSniffer'](filter=config_data['sniffer_filter'], interface=config_data['sniffer_interface'], config=ARGV.config) + print("[x] Start sniffer") + x = locals()["QBSniffer"]( + filter=config_data["sniffer_filter"], + interface=config_data["sniffer_interface"], + config=ARGV.config, + ) x.run_sniffer(process=True) temp_honeypots.append(x) if not ARGV.test: - print('[x] Everything looks good!') + print("[x] Everything looks good!") while True: try: _servers = {} - logs.info(['system', {'type': 'network', 'bytes_sent': net_io_counters().bytes_sent, 'bytes_recv': net_io_counters().bytes_recv, 'packets_sent': net_io_counters().packets_sent, 'packets_recv': net_io_counters().packets_recv}]) + logs.info( + [ + "system", + { + "type": "network", + "bytes_sent": net_io_counters().bytes_sent, + "bytes_recv": net_io_counters().bytes_recv, + "packets_sent": net_io_counters().packets_sent, + "packets_recv": net_io_counters().packets_recv, + }, + ] + ) for server in temp_honeypots: - _servers[server.__class__.__name__] = {'memory': Process(server.process.pid).memory_percent(), 'cpu': Process(server.process.pid).cpu_percent()} - logs.info(['system', _servers]) + _servers[server.__class__.__name__] = { + "memory": Process(server.process.pid).memory_percent(), + "cpu": Process(server.process.pid).cpu_percent(), + } + logs.info(["system", _servers]) except Exception as e: print(e) sleep(20) @@ -234,26 +347,25 @@ def error(self, message): if len(temp_honeypots) > 0: for server in temp_honeypots: try: - print('[x] Killing {} tester'.format(server.__class__.__name__)) + print(f"[x] Killing {server.__class__.__name__} tester") server.kill_server() except Exception as e: print(e) - print('[x] Please wait few seconds') + print("[x] Please wait few seconds") sleep(5) - elif ARGV.setup != '': - + elif ARGV.setup != "": register(exit_handler) auto = ARGV.auto - if ARGV.termination_strategy == 'input': - print('[x] Use [Enter] to exit or python3 -m honeypots --kill') + if ARGV.termination_strategy == "input": + print("[x] Use [Enter] to exit or python3 -m honeypots --kill") - if ARGV.config != '': - print('[x] config.json file overrides --ip, --port, --username and --password') + if ARGV.config != "": + print("[x] config.json file overrides --ip, --port, --username and --password") if geteuid() == 0: auto = False - if ARGV.setup == 'all': + if ARGV.setup == "all": try: for honeypot in all_servers: status = False @@ -263,14 +375,14 @@ def error(self, message): except Exception as e: print(e) else: - servers = ARGV.setup.split(',') + servers = ARGV.setup.split(",") for server in servers: - print('[x] Parsing honeypot [normal]') - if ':' in server: + print("[x] Parsing honeypot [normal]") + if ":" in server: for honeypot in all_servers: - if 'q{}server'.format(server.split(':')[0]).lower() == honeypot.lower(): - ARGV.port = int(server.split(':')[1]) - PARSED_ARG_PARSER_OPTIONAL['port'] = ARGV.port + if "q{}server".format(server.split(":")[0]).lower() == honeypot.lower(): + ARGV.port = int(server.split(":")[1]) + PARSED_ARG_PARSER_OPTIONAL["port"] = ARGV.port x = locals()[honeypot](**PARSED_ARG_PARSER_OPTIONAL) status = False if not ARGV.test: @@ -279,9 +391,9 @@ def error(self, message): server_timeout(x, honeypot) x.kill_server() temp_honeypots.append([x, honeypot, status]) - elif ARGV.port != '': + elif ARGV.port != "": for honeypot in all_servers: - if 'q{}server'.format(server).lower() == honeypot.lower(): + if f"q{server}server".lower() == honeypot.lower(): x = locals()[honeypot](**PARSED_ARG_PARSER_OPTIONAL) status = False if not ARGV.test: @@ -292,50 +404,54 @@ def error(self, message): temp_honeypots.append([x, honeypot, status]) else: for honeypot in all_servers: - if 'q{}server'.format(server).lower() == honeypot.lower(): + if f"q{server}server".lower() == honeypot.lower(): x = locals()[honeypot](**PARSED_ARG_PARSER_OPTIONAL) status = False if not ARGV.test: status = x.run_server(process=True, auto=auto) else: - print('[x] {} was configured with random port, unable to test..'.format(honeypot)) + print( + "[x] {} was configured with random port, unable to test..".format( + honeypot + ) + ) temp_honeypots.append([x, honeypot, status]) - running_honeypots = {'good': [], 'bad': []} + running_honeypots = {"good": [], "bad": []} if len(temp_honeypots) > 0: good = True for server in temp_honeypots: if server[2] == False or server[2] is None: - running_honeypots['bad'].append(server[1]) + running_honeypots["bad"].append(server[1]) else: - running_honeypots['good'].append(server[1]) + running_honeypots["good"].append(server[1]) - if len(running_honeypots['good']) > 0: - print('[x] {} running..'.format(', '.join(running_honeypots['good']))) + if len(running_honeypots["good"]) > 0: + print("[x] {} running..".format(", ".join(running_honeypots["good"]))) - if len(running_honeypots['bad']) > 0: - print('[x] {} not running..'.format(', '.join(running_honeypots['bad']))) + if len(running_honeypots["bad"]) > 0: + print("[x] {} not running..".format(", ".join(running_honeypots["bad"]))) - if len(running_honeypots['bad']) == 0: - print('[x] Everything looks good!') + if len(running_honeypots["bad"]) == 0: + print("[x] Everything looks good!") - if len(running_honeypots['good']) > 0: + if len(running_honeypots["good"]) > 0: if not ARGV.test: Termination(ARGV.termination_strategy).await_termination() for server in temp_honeypots: try: if not ARGV.test: - print('[x] Killing {} honeypot'.format(server[0].__class__.__name__)) + print(f"[x] Killing {server[0].__class__.__name__} honeypot") else: - print('[x] Killing {} tester'.format(server[0].__class__.__name__)) + print(f"[x] Killing {server[0].__class__.__name__} tester") server[0].kill_server() except Exception as e: print(e) - print('[x] Please wait few seconds') + print("[x] Please wait few seconds") sleep(5) -if __name__ == '__main__': +if __name__ == "__main__": main_logic() diff --git a/honeypots/dhcp_server.py b/honeypots/dhcp_server.py index 89d0fdb..0fd31c9 100644 --- a/honeypots/dhcp_server.py +++ b/honeypots/dhcp_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') -filterwarnings(action='ignore', module='.*socket.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") +filterwarnings(action="ignore", module=".*socket.*") from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor @@ -20,31 +21,48 @@ from socket import inet_aton from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 -class QDHCPServer(): +class QDHCPServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 67 - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 67 + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def dhcp_server_main(self): _q_s = self class CustomDatagramProtocolProtocol(DatagramProtocol): - def check_bytes(self, string): if isinstance(string, bytes): return string.decode() @@ -52,34 +70,52 @@ def check_bytes(self, string): return str(string) def payload(self, value, message): - op, htype, hlen, hops, xid, secs, flags, ciaddr, yiaddr, siaddr, giaddr, chaddr = unpack('1s1s1s1s4s2s2s4s4s4s4s16s', message[:44]) - #op, htype, hlen, hops, xid, secs, flags, ciaddr - response = b'\x02\x01\x06\x00' + xid + b'\x00\x00\x00\x00\x00\x00\x00\x00' - #yiaddr, siaddr, giaddr, chaddr - response += inet_aton(_q_s.dhcp_ip_lease) + inet_aton(_q_s.dhcp_ip) + inet_aton('0.0.0.0') + chaddr - #sname, file, magic - response += b'\x00' * 64 + b'\x00' * 128 + b'\x63\x82\x53\x63' + ( + op, + htype, + hlen, + hops, + xid, + secs, + flags, + ciaddr, + yiaddr, + siaddr, + giaddr, + chaddr, + ) = unpack("1s1s1s1s4s2s2s4s4s4s4s16s", message[:44]) + # op, htype, hlen, hops, xid, secs, flags, ciaddr + response = b"\x02\x01\x06\x00" + xid + b"\x00\x00\x00\x00\x00\x00\x00\x00" + # yiaddr, siaddr, giaddr, chaddr + response += ( + inet_aton(_q_s.dhcp_ip_lease) + + inet_aton(_q_s.dhcp_ip) + + inet_aton("0.0.0.0") + + chaddr + ) + # sname, file, magic + response += b"\x00" * 64 + b"\x00" * 128 + b"\x63\x82\x53\x63" # options response += bytes([53, 1, value]) response += bytes([54, 4]) + inet_aton(_q_s.dhcp_ip) response += bytes([1, 4]) + inet_aton(_q_s.subnet_mask) response += bytes([3, 4]) + inet_aton(_q_s.router) response += bytes([6, 4]) + inet_aton(_q_s.dns_server) - response += bytes([51, 4]) + b'\x00\x00\xa8\xc0' # lease - response += b'\xff' + response += bytes([51, 4]) + b"\x00\x00\xa8\xc0" # lease + response += b"\xff" return response def parse_options(self, raw): options = {} tag_name = None tag_size = None - tag = '' + tag = "" for idx, b in enumerate(raw): if tag_name is None: tag_name = b elif tag_name is not None and tag_size is None: tag_size = b - tag = '' + tag = "" else: if tag_size: tag_size -= 1 @@ -88,24 +124,37 @@ def parse_options(self, raw): options.update({self.check_bytes(tag_name): self.check_bytes(tag)}) tag_name = None tag_size = None - tag = '' + tag = "" return options def datagramReceived(self, data, addr): try: - mac_address = unpack('!28x6s', data[:34])[0].hex(':') + mac_address = unpack("!28x6s", data[:34])[0].hex(":") except StructError: mac_address = "None" data = self.parse_options(data[240:]) - data.update({'mac_address': mac_address}) - _q_s.logs.info({'server': 'dhcp_server', 'action': 'query', 'status': 'success', 'src_ip': addr[0], 'src_port': addr[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': data}) + data.update({"mac_address": mac_address}) + _q_s.logs.info( + { + "server": "dhcp_server", + "action": "query", + "status": "success", + "src_ip": addr[0], + "src_port": addr[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": data, + } + ) self.transport.loseConnection() - reactor.listenUDP(port=self.port, protocol=CustomDatagramProtocolProtocol(), interface=self.ip) + reactor.listenUDP( + port=self.port, protocol=CustomDatagramProtocolProtocol(), interface=self.ip + ) reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -117,13 +166,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'dhcp_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "dhcp_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -132,19 +207,21 @@ def run_server(self, process=False, auto=False): self.dhcp_server_main() def close_port(self): - ret = close_port_wrapper('dhcp_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("dhcp_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('dhcp_server', self.uuid, self.process) + ret = kill_server_wrapper("dhcp_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None): pass -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qdhcpserver = QDHCPServer(ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config) + qdhcpserver = QDHCPServer( + ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config + ) qdhcpserver.run_server() diff --git a/honeypots/dns_server.py b/honeypots/dns_server.py index ca85808..4c11713 100644 --- a/honeypots/dns_server.py +++ b/honeypots/dns_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.names import dns, error, client from twisted.names.server import DNSServerFactory @@ -19,26 +20,44 @@ from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QDNSServer(): +class QDNSServer: def __init__(self, **kwargs): self.auto_disabled = None - self.resolver_addresses = [('8.8.8.8', 53)] + self.resolver_addresses = [("8.8.8.8", 53)] self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 53 - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 53 + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def dns_server_main(self): @@ -50,17 +69,37 @@ def queryUDP(self, queries, timeout=2): def queryFailed(reason): return defer.fail(error.DomainError()) + res.addErrback(queryFailed) return res class CustomDNSServerFactory(DNSServerFactory): def gotResolverResponse(self, response, protocol, message, address): args = (self, response, protocol, message, address) - _q_s.logs.info({'server': 'dns_server', 'action': 'connection', 'src_ip': address[0], 'src_port': address[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "dns_server", + "action": "connection", + "src_ip": address[0], + "src_port": address[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) with suppress(Exception): for items in response: for item in items: - _q_s.logs.info({'server': 'dns_server', 'action': 'query', 'src_ip': address[0], 'src_port': address[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': item.payload}) + _q_s.logs.info( + { + "server": "dns_server", + "action": "query", + "src_ip": address[0], + "src_port": address[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": item.payload, + } + ) return DNSServerFactory.gotResolverResponse(*args) self.resolver = CustomCilentResolver(servers=self.resolver_addresses) @@ -71,7 +110,7 @@ def gotResolverResponse(self, response, protocol, message, address): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -83,13 +122,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'dns_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "dns_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -99,24 +164,25 @@ def run_server(self, process=False, auto=False): return None def close_port(self): - ret = close_port_wrapper('dns_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("dns_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('dns_server', self.uuid, self.process) + ret = kill_server_wrapper("dns_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, domain=None): with suppress(Exception): from dns.resolver import Resolver + res = Resolver(configure=False) res.nameservers = [self.ip] res.port = self.port - temp_domain = domain or 'example.org' - r = res.query(temp_domain, 'a') + temp_domain = domain or "example.org" + r = res.query(temp_domain, "a") -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: qdnsserver = QDNSServer(ip=parsed.ip, port=parsed.port, config=parsed.config) diff --git a/honeypots/elastic_server.py b/honeypots/elastic_server.py index d58f1a9..eac05bf 100644 --- a/honeypots/elastic_server.py +++ b/honeypots/elastic_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,11 +8,12 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') -filterwarnings(action='ignore', module='.*elasticsearch.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") +filterwarnings(action="ignore", module=".*elasticsearch.*") from base64 import b64encode, b64decode from requests.packages.urllib3 import disable_warnings @@ -26,40 +27,63 @@ from os import path, getenv from OpenSSL import crypto from tempfile import gettempdir, _get_candidate_names -from honeypots.helper import check_if_server_is_running, close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, set_local_vars, setup_logger +from honeypots.helper import ( + check_if_server_is_running, + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + set_local_vars, + setup_logger, +) from contextlib import suppress disable_warnings() -class QElasticServer(): +class QElasticServer: def __init__(self, **kwargs): self.auto_disabled = None self.key = path.join(gettempdir(), next(_get_candidate_names())) self.cert = path.join(gettempdir(), next(_get_candidate_names())) self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 9200 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'elastic' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 9200 + ) + self.username = ( + kwargs.get("username", None) + or (hasattr(self, "username") and self.username) + or "elastic" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) def CreateCert(self, host_name, key, cert): pk = crypto.PKey() pk.generate_key(crypto.TYPE_RSA, 2048) c = crypto.X509() - c.get_subject().C = 'US' - c.get_subject().ST = 'OR' - c.get_subject().L = 'None' - c.get_subject().O = 'None' - c.get_subject().OU = 'None' + c.get_subject().C = "US" + c.get_subject().ST = "OR" + c.get_subject().L = "None" + c.get_subject().O = "None" + c.get_subject().OU = "None" c.get_subject().CN = next(_get_candidate_names()) c.set_serial_number(0) before, after = (0, 60 * 60 * 24 * 365 * 2) @@ -67,21 +91,21 @@ def CreateCert(self, host_name, key, cert): c.gmtime_adj_notAfter(after) c.set_issuer(c.get_subject()) c.set_pubkey(pk) - c.sign(pk, 'sha256') - open(cert, 'wb').write(crypto.dump_certificate(crypto.FILETYPE_PEM, c)) - open(key, 'wb').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk)) + c.sign(pk, "sha256") + open(cert, "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, c)) + open(key, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk)) def elastic_server_main(self): _q_s = self class CustomElasticServerHandler(SimpleHTTPRequestHandler): - - server_version = '' - sys_version = '' + server_version = "" + sys_version = "" def _dump_headers(self): headers = {} with suppress(Exception): + def check_bytes(string): if isinstance(string, bytes): return string.decode() @@ -91,7 +115,18 @@ def check_bytes(string): for item, value in dict(self.headers).items(): headers.update({check_bytes(item): check_bytes(value)}) - _q_s.logs.info({'server': 'elastic_server', 'action': 'dump', 'data': check_bytes(self.raw_requestline), 'src_ip': self.client_address[0], 'src_port': self.client_address[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'headers': headers}) + _q_s.logs.info( + { + "server": "elastic_server", + "action": "dump", + "data": check_bytes(self.raw_requestline), + "src_ip": self.client_address[0], + "src_port": self.client_address[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "headers": headers, + } + ) return headers def _remove_headers(self, headers): @@ -107,75 +142,308 @@ def _compress_gzip(self, content): def _set_response_gzip(self, content, code): self.send_response(code) gzip_compressed_data = self._compress_gzip(content) - self.send_header('content-encoding', 'gzip') - self.send_header('content-length', str(len(gzip_compressed_data))) - self.send_header('content-type', 'application/json; charset=UTF-8') + self.send_header("content-encoding", "gzip") + self.send_header("content-length", str(len(gzip_compressed_data))) + self.send_header("content-type", "application/json; charset=UTF-8") self.end_headers() return gzip_compressed_data def do_HEAD(self): self.send_response(200) - self.send_header('content-encoding', 'gzip') - self.send_header('content-type', 'application/json; charset=UTF-8') + self.send_header("content-encoding", "gzip") + self.send_header("content-type", "application/json; charset=UTF-8") self.end_headers() def _set_response_gzip_auth(self, content, code): self._dump_headers() self.send_response(code) - self._remove_headers([b'server:', b'date:']) + self._remove_headers([b"server:", b"date:"]) gzip_compressed_data = self._compress_gzip(content) - self.send_header('content-encoding', 'gzip') - self.send_header('content-length', str(len(gzip_compressed_data))) - self.send_header('content-type', 'application/json; charset=UTF-8') - self.send_header('WWW-Authenticate', 'Basic realm="security" charset="UTF-8"') + self.send_header("content-encoding", "gzip") + self.send_header("content-length", str(len(gzip_compressed_data))) + self.send_header("content-type", "application/json; charset=UTF-8") + self.send_header("WWW-Authenticate", 'Basic realm="security" charset="UTF-8"') self.end_headers() return gzip_compressed_data def do_GET(self): - username = '' - password = '' - e_name = '045dffec8b60' - e_cluster_name = 'R&DBackup' - e_host = '172.17.0.2' - e_transport_address = e_host + ':9300' - e_build_type = 'en' - e_os_name = 'Linux' - e_os_pretty_name = 'CentOS Linux 8' - e_os_version = '5.8.0-53-generic' + username = "" + password = "" + e_name = "045dffec8b60" + e_cluster_name = "R&DBackup" + e_host = "172.17.0.2" + e_transport_address = e_host + ":9300" + e_build_type = "en" + e_os_name = "Linux" + e_os_pretty_name = "CentOS Linux 8" + e_os_version = "5.8.0-53-generic" key = self.server.get_auth_key() - if self.headers.get('Authorization') is None: - _q_s.logs.info({'server': 'elastic_server', 'action': 'login', 'status': 'failed', 'src_ip': self.client_address[0], 'src_port': self.client_address[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) - auth_paylaod = bytes(dumps({'error': {'root_cause': [{'type': 'security_exception', 'reason': 'unable to authenticate user [{}] for REST request [/]'.format(username), 'header': {'WWW-Authenticate': 'Basic realm=\"security\" charset=\"UTF-8\"'}}], 'type': 'security_exception', 'reason': 'unable to authenticate user [{}] for REST request [/]'.format(username), 'header': {'WWW-Authenticate': 'Basic realm=\"security\" charset=\"UTF-8\"'}}, 'status': 401}), 'utf-8') + if self.headers.get("Authorization") is None: + _q_s.logs.info( + { + "server": "elastic_server", + "action": "login", + "status": "failed", + "src_ip": self.client_address[0], + "src_port": self.client_address[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) + auth_paylaod = bytes( + dumps( + { + "error": { + "root_cause": [ + { + "type": "security_exception", + "reason": "unable to authenticate user [{}] for REST request [/]".format( + username + ), + "header": { + "WWW-Authenticate": 'Basic realm="security" charset="UTF-8"' + }, + } + ], + "type": "security_exception", + "reason": "unable to authenticate user [{}] for REST request [/]".format( + username + ), + "header": { + "WWW-Authenticate": 'Basic realm="security" charset="UTF-8"' + }, + }, + "status": 401, + } + ), + "utf-8", + ) self.wfile.write(self._set_response_gzip_auth(auth_paylaod, 401)) - elif self.headers.get('Authorization') == 'Basic ' + str(key): - extracted = '' - _q_s.logs.info({'server': 'elastic_server', 'action': 'login', 'status': 'success', 'src_ip': self.client_address[0], 'src_port': self.client_address[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': _q_s.username, 'password': _q_s.password}) + elif self.headers.get("Authorization") == "Basic " + str(key): + extracted = "" + _q_s.logs.info( + { + "server": "elastic_server", + "action": "login", + "status": "success", + "src_ip": self.client_address[0], + "src_port": self.client_address[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": _q_s.username, + "password": _q_s.password, + } + ) with suppress(Exception): extracted = urlparse(self.path).path - if extracted == '/': - normal_payload = bytes(dumps({'name': e_name, 'cluster_name': e_cluster_name, 'cluster_uuid': '09cf5BKcTCG2U8z2ndwGEw', 'version': {'number': '7.12.1', 'build_flavor': 'default', 'build_type': e_build_type, 'build_hash': '3186837139b9c6b6d23c3200870651f10d3343b7', 'build_date': '2021-04-20T20:56:39.040728659Z', 'build_snapshot': False, 'lucene_version': '8.8.0', 'minimum_wire_compatibility_version': '6.8.0', 'minimum_index_compatibility_version': '6.0.0-beta1'}, 'tagline': 'You Know, for Search'}), 'utf-8') + if extracted == "/": + normal_payload = bytes( + dumps( + { + "name": e_name, + "cluster_name": e_cluster_name, + "cluster_uuid": "09cf5BKcTCG2U8z2ndwGEw", + "version": { + "number": "7.12.1", + "build_flavor": "default", + "build_type": e_build_type, + "build_hash": "3186837139b9c6b6d23c3200870651f10d3343b7", + "build_date": "2021-04-20T20:56:39.040728659Z", + "build_snapshot": False, + "lucene_version": "8.8.0", + "minimum_wire_compatibility_version": "6.8.0", + "minimum_index_compatibility_version": "6.0.0-beta1", + }, + "tagline": "You Know, for Search", + } + ), + "utf-8", + ) self.wfile.write(self._set_response_gzip(normal_payload, 200)) - elif extracted.startswith('/_nodes'): - _nodes_payload = bytes(dumps({'_nodes': {'total': 1, 'successful': 1, 'failed': 0}, 'cluster_name': e_cluster_name, 'nodes': {'rvyTV3xvTgyt74ti4u12bw': {'name': e_name, 'transport_address': e_transport_address, 'host': e_host, 'src_ip': e_host, 'version': '7.12.1', 'build_flavor': 'default', 'build_type': e_build_type, 'build_hash': '3186837139b9c6b6d23c3200870651f10d3343b7', 'roles': ['data', 'data_cold', 'data_content', 'data_frozen', 'data_hot', 'data_warm', 'ingest', 'master', 'ml', 'remote_cluster_client', 'transform'], 'attributes': {'ml.machine_memory': '16685318144', 'xpack.installed': 'true', 'transform.node': 'true', 'ml.max_open_jobs': '20', 'ml.max_jvm_size': '8342470656'}, 'process': {'refresh_interval_in_millis': 1000, 'id': 7, 'mlockall': False}}, 'os': {'refresh_interval_in_millis': 1000, 'name': e_os_name, 'pretty_name': e_os_pretty_name, 'arch': 'amd64', 'version': e_os_version, 'available_processors': 32, 'allocated_processors': 8}, 'process': {'refresh_interval_in_millis': 1000, 'id': 7, 'mlockall': False}}}), 'utf-8') + elif extracted.startswith("/_nodes"): + _nodes_payload = bytes( + dumps( + { + "_nodes": {"total": 1, "successful": 1, "failed": 0}, + "cluster_name": e_cluster_name, + "nodes": { + "rvyTV3xvTgyt74ti4u12bw": { + "name": e_name, + "transport_address": e_transport_address, + "host": e_host, + "src_ip": e_host, + "version": "7.12.1", + "build_flavor": "default", + "build_type": e_build_type, + "build_hash": "3186837139b9c6b6d23c3200870651f10d3343b7", + "roles": [ + "data", + "data_cold", + "data_content", + "data_frozen", + "data_hot", + "data_warm", + "ingest", + "master", + "ml", + "remote_cluster_client", + "transform", + ], + "attributes": { + "ml.machine_memory": "16685318144", + "xpack.installed": "true", + "transform.node": "true", + "ml.max_open_jobs": "20", + "ml.max_jvm_size": "8342470656", + }, + "process": { + "refresh_interval_in_millis": 1000, + "id": 7, + "mlockall": False, + }, + }, + "os": { + "refresh_interval_in_millis": 1000, + "name": e_os_name, + "pretty_name": e_os_pretty_name, + "arch": "amd64", + "version": e_os_version, + "available_processors": 32, + "allocated_processors": 8, + }, + "process": { + "refresh_interval_in_millis": 1000, + "id": 7, + "mlockall": False, + }, + }, + } + ), + "utf-8", + ) self.wfile.write(self._set_response_gzip(_nodes_payload, 200)) - elif extracted.startswith('/_cluster/health'): - _cluster_health_payload = bytes(dumps({'cluster_name': e_cluster_name, 'status': 'green', 'timed_out': False, 'number_of_nodes': 1, 'number_of_data_nodes': 1, 'active_primary_shards': 0, 'active_shards': 0, 'relocating_shards': 0, 'initializing_shards': 0, 'unassigned_shards': 0, 'delayed_unassigned_shards': 0, 'number_of_pending_tasks': 0, 'number_of_in_flight_fetch': 0, 'task_max_waiting_in_queue_millis': 0, 'active_shards_percent_as_number': 100.0}), 'utf-8') + elif extracted.startswith("/_cluster/health"): + _cluster_health_payload = bytes( + dumps( + { + "cluster_name": e_cluster_name, + "status": "green", + "timed_out": False, + "number_of_nodes": 1, + "number_of_data_nodes": 1, + "active_primary_shards": 0, + "active_shards": 0, + "relocating_shards": 0, + "initializing_shards": 0, + "unassigned_shards": 0, + "delayed_unassigned_shards": 0, + "number_of_pending_tasks": 0, + "number_of_in_flight_fetch": 0, + "task_max_waiting_in_queue_millis": 0, + "active_shards_percent_as_number": 100.0, + } + ), + "utf-8", + ) self.wfile.write(self._set_response_gzip(_cluster_health_payload, 200)) - elif extracted.startswith('/_'): - _index = extracted.split('/')[1].lower() - _payload = bytes(dumps({'error': {'root_cause': [{'type': 'invalid_index_name_exception', 'reason': 'Invalid index name [{}], must not start with "_".'.format(_index), 'index_uuid': '_na_', 'index': _index}], 'type': 'invalid_index_name_exception', 'reason': 'Invalid index name [{}], must not start with "_".'.format(_index), 'index_uuid': '_na_', 'index': _index}, 'status': 400}), 'utf-8') + elif extracted.startswith("/_"): + _index = extracted.split("/")[1].lower() + _payload = bytes( + dumps( + { + "error": { + "root_cause": [ + { + "type": "invalid_index_name_exception", + "reason": f'Invalid index name [{_index}], must not start with "_".', + "index_uuid": "_na_", + "index": _index, + } + ], + "type": "invalid_index_name_exception", + "reason": f'Invalid index name [{_index}], must not start with "_".', + "index_uuid": "_na_", + "index": _index, + }, + "status": 400, + } + ), + "utf-8", + ) self.wfile.write(self._set_response_gzip(_payload, 400)) else: - _search = extracted.split('/')[1].lower() - _search_payload = bytes(dumps({'error': {'root_cause': [{'type': 'index_not_found_exception', 'reason': 'no such index [{}]'.format(_search), 'resource.type': 'index_or_alias', 'resource.id': _search, 'index_uuid': '_na_', 'index': _search}], 'type': 'index_not_found_exception', 'reason': 'no such index [{}]'.format(_search), 'resource.type': 'index_or_alias', 'resource.id': _search, 'index_uuid': '_na_', 'index': _search}, 'status': 404}), 'utf-8') + _search = extracted.split("/")[1].lower() + _search_payload = bytes( + dumps( + { + "error": { + "root_cause": [ + { + "type": "index_not_found_exception", + "reason": f"no such index [{_search}]", + "resource.type": "index_or_alias", + "resource.id": _search, + "index_uuid": "_na_", + "index": _search, + } + ], + "type": "index_not_found_exception", + "reason": f"no such index [{_search}]", + "resource.type": "index_or_alias", + "resource.id": _search, + "index_uuid": "_na_", + "index": _search, + }, + "status": 404, + } + ), + "utf-8", + ) self.wfile.write(self._set_response_gzip(_search_payload, 404)) else: - authorization_string = self.headers.get('Authorization').split(' ') - basic = b64decode(authorization_string[1]).decode('utf-8') - username, password = basic.split(':') - _q_s.logs.info({'server': 'elastic_server', 'action': 'login', 'status': 'failed', 'src_ip': self.client_address[0], 'src_port': self.client_address[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) - auth_paylaod = bytes(dumps({'error': {'root_cause': [{'type': 'security_exception', 'reason': 'missing authentication credentials for REST request [/]', 'header': {'WWW-Authenticate': 'Basic realm=\"security\" charset=\"UTF-8\"'}}], 'type': 'security_exception', 'reason': 'missing authentication credentials for REST request [/]', 'header': {'WWW-Authenticate': 'Basic realm=\"security\" charset=\"UTF-8\"'}}, 'status': 401}), 'utf-8') + authorization_string = self.headers.get("Authorization").split(" ") + basic = b64decode(authorization_string[1]).decode("utf-8") + username, password = basic.split(":") + _q_s.logs.info( + { + "server": "elastic_server", + "action": "login", + "status": "failed", + "src_ip": self.client_address[0], + "src_port": self.client_address[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) + auth_paylaod = bytes( + dumps( + { + "error": { + "root_cause": [ + { + "type": "security_exception", + "reason": "missing authentication credentials for REST request [/]", + "header": { + "WWW-Authenticate": 'Basic realm="security" charset="UTF-8"' + }, + } + ], + "type": "security_exception", + "reason": "missing authentication credentials for REST request [/]", + "header": { + "WWW-Authenticate": 'Basic realm="security" charset="UTF-8"' + }, + }, + "status": 401, + } + ), + "utf-8", + ) self.wfile.write(self._set_response_gzip_auth(auth_paylaod, 401)) do_POST = do_GET @@ -183,36 +451,50 @@ def do_GET(self): do_DELETE = do_GET def send_error(self, code, message=None): - self.error_message_format = 'Error!' + self.error_message_format = "Error!" SimpleHTTPRequestHandler.send_error(self, code, message) def log_message(self, format, *args): return def handle_one_request(self): - _q_s.logs.info({'server': 'elastic_server', 'action': 'connection', 'src_ip': self.client_address[0], 'src_port': self.client_address[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "elastic_server", + "action": "connection", + "src_ip": self.client_address[0], + "src_port": self.client_address[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) return SimpleHTTPRequestHandler.handle_one_request(self) class CustomElasticServer(ThreadingHTTPServer): - key = b64encode(bytes('%s:%s' % ('elastic', 'changeme'), 'utf-8')).decode('ascii') + key = b64encode(bytes("%s:%s" % ("elastic", "changeme"), "utf-8")).decode("ascii") def __init__(self, address, handlerClass=CustomElasticServerHandler): super().__init__(address, handlerClass) def set_auth_key(self, username, password): - self.key = b64encode('{}:{}'.format(username, password).encode('utf-8')).decode('ascii') + self.key = b64encode(f"{username}:{password}".encode()).decode("ascii") def get_auth_key(self): return self.key server = CustomElasticServer((self.ip, self.port)) server.set_auth_key(self.username, self.password) - self.CreateCert('localhost', self.key, self.cert) - server.socket = wrap_socket(server.socket, keyfile=self.key, certfile=self.cert, server_side=True,) + self.CreateCert("localhost", self.key, self.cert) + server.socket = wrap_socket( + server.socket, + keyfile=self.key, + certfile=self.cert, + server_side=True, + ) server.serve_forever() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -224,13 +506,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'elastic_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "elastic_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -240,26 +554,38 @@ def run_server(self, process=False, auto=False): return None def close_port(self): - ret = close_port_wrapper('elastic_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("elastic_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('elastic_server', self.uuid, self.process) + ret = kill_server_wrapper("elastic_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from elasticsearch import Elasticsearch + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password - es = Elasticsearch(['https://{}:{}'.format(_ip, _port)], http_auth=(_username, _password), verify_certs=False) - es.search(index='test', body={}, size=99) + es = Elasticsearch( + [f"https://{_ip}:{_port}"], + http_auth=(_username, _password), + verify_certs=False, + ) + es.search(index="test", body={}, size=99) -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qelasticserver = QElasticServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qelasticserver = QElasticServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qelasticserver.run_server() diff --git a/honeypots/ftp_server.py b/honeypots/ftp_server.py index f463f1f..b24a12f 100644 --- a/honeypots/ftp_server.py +++ b/honeypots/ftp_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,12 +8,21 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') -from twisted.protocols.ftp import FTPAnonymousShell, FTPFactory, FTP, AUTH_FAILURE, IFTPShell, GUEST_LOGGED_IN_PROCEED, AuthorizationError, BAD_CMD_SEQ, USR_LOGGED_IN_PROCEED +filterwarnings(action="ignore", module=".*OpenSSL.*") + +from twisted.protocols.ftp import ( + FTPAnonymousShell, + FTPFactory, + FTP, + IFTPShell, + GUEST_LOGGED_IN_PROCEED, + AuthorizationError, + USR_LOGGED_IN_PROCEED, +) from twisted.internet import reactor, defer from twisted.cred.portal import Portal from twisted.cred import portal, credentials @@ -25,29 +34,60 @@ from random import choice from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress from tempfile import TemporaryDirectory -class QFTPServer(): +class QFTPServer: def __init__(self, **kwargs): self.auto_disabled = None - self.mocking_server = choice(['ProFTPD 1.2.10', 'ProFTPD 1.3.4a', 'FileZilla ftp 0.9.43', 'Gene6 ftpd 3.10.0', 'FileZilla ftp 0.9.33', 'ProFTPD 1.2.8']) + self.mocking_server = choice( + [ + "ProFTPD 1.2.10", + "ProFTPD 1.3.4a", + "FileZilla ftp 0.9.43", + "Gene6 ftpd 3.10.0", + "FileZilla ftp 0.9.33", + "ProFTPD 1.2.8", + ] + ) self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 21 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 21 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) self.temp_folder = TemporaryDirectory() disable_logger(1, tlog) @@ -63,7 +103,7 @@ def requestAvatar(self, avatarId, mind, *interfaces): for iface in interfaces: if iface is IFTPShell: avatar = FTPAnonymousShell(self.anonymousRoot) - return IFTPShell, avatar, getattr(avatar, 'logout', lambda: None) + return IFTPShell, avatar, getattr(avatar, "logout", lambda: None) raise NotImplementedError("Only IFTPShell interface is supported by this realm") @implementer(ICredentialsChecker) @@ -87,7 +127,6 @@ def requestAvatarId(self, credentials): return defer.fail(UnauthorizedLogin()) class CustomFTPProtocol(FTP): - def check_bytes(self, string): if isinstance(string, bytes): return string.decode() @@ -95,7 +134,16 @@ def check_bytes(self, string): return str(string) def connectionMade(self): - _q_s.logs.info({'server': 'ftp_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "ftp_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) self.state = self.UNAUTH self.setTimeout(self.timeOut) self.reply("220.2", self.factory.welcomeMessage) @@ -103,18 +151,43 @@ def connectionMade(self): def processCommand(self, cmd, *params): with suppress(Exception): if "capture_commands" in _q_s.options: - _q_s.logs.info({'server': 'ftp_server', 'action': 'command', 'data': {"cmd": self.check_bytes(cmd.upper()), "args": self.check_bytes(params)}, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "ftp_server", + "action": "command", + "data": { + "cmd": self.check_bytes(cmd.upper()), + "args": self.check_bytes(params), + }, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) return super().processCommand(cmd, *params) def ftp_PASS(self, password): username = self.check_bytes(self._user) password = self.check_bytes(password) - status = 'failed' + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'ftp_server', 'action': 'login', 'status': status, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + status = "success" + _q_s.logs.info( + { + "server": "ftp_server", + "action": "login", + "status": status, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) if self.factory.allowAnonymous and self._user == self.factory.userAnonymous: creds = credentials.Anonymous() @@ -149,7 +222,7 @@ def _ebLogin(failure): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -161,13 +234,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' + status = "success" - self.logs.info({'server': 'ftp_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) + self.logs.info( + { + "server": "ftp_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) - if status == 'success': + if status == "success": return True else: self.kill_server() @@ -177,16 +282,17 @@ def run_server(self, process=False, auto=False): return None def close_port(self): - ret = close_port_wrapper('ftp_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("ftp_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('ftp_server', self.uuid, self.process) + ret = kill_server_wrapper("ftp_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from ftplib import FTP as FFTP + _ip = ip or self.ip _port = port or self.port _username = username or self.username @@ -198,8 +304,15 @@ def test_server(self, ip=None, port=None, username=None, password=None): f.quit() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - ftpserver = QFTPServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + ftpserver = QFTPServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) ftpserver.run_server() diff --git a/honeypots/helper.py b/honeypots/helper.py index 72590f9..3d40ac5 100644 --- a/honeypots/helper.py +++ b/honeypots/helper.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,19 +8,20 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" import sys from warnings import filterwarnings -filterwarnings(action='ignore', module='.*requests.*') + +filterwarnings(action="ignore", module=".*requests.*") from psutil import process_iter from signal import SIGTERM from argparse import ArgumentParser from socket import socket, AF_INET, SOCK_STREAM from json import JSONEncoder, dumps, load -from logging import Handler, Formatter, DEBUG, getLogger, addLevelName, INFO, Logger +from logging import Handler, Formatter, DEBUG, getLogger from sys import stdout from datetime import datetime from logging.handlers import RotatingFileHandler, SysLogHandler @@ -29,7 +30,6 @@ from psycopg2 import sql from psycopg2 import connect as psycopg2_connect from time import sleep -from traceback import format_exc from collections.abc import Mapping from urllib.parse import urlparse from sqlite3 import connect as sqlite3_connect @@ -37,7 +37,7 @@ from contextlib import suppress old_stderr = sys.stderr -sys.stderr = open(devnull, 'w') +sys.stderr = open(devnull, "w") def check_privileges(): @@ -45,6 +45,7 @@ def check_privileges(): return getuid() == 0 with suppress(Exception): import ctypes + return ctypes.windll.shell32.IsUserAnAdmin() != 0 return False @@ -52,60 +53,62 @@ def check_privileges(): def set_local_vars(self, config): with suppress(Exception): honeypot = None - if config and config != '': + if config and config != "": with open(config) as f: config_data = load(f) - honeypots = config_data['honeypots'] + honeypots = config_data["honeypots"] honeypot = self.__class__.__name__[1:-6].lower() if honeypot and honeypot in honeypots: for var in honeypots[honeypot]: setattr(self, var, honeypots[honeypot][var]) - if var == 'port': - setattr(self, 'auto_disabled', True) + if var == "port": + self.auto_disabled = True def parse_record(record, custom_filter, type_): - timestamp = {'timestamp': datetime.utcnow().isoformat()} + timestamp = {"timestamp": datetime.utcnow().isoformat()} try: if custom_filter is not None: - if 'remove_errors' in custom_filter['honeypots']['options']: - if 'error' in record.msg: + if "remove_errors" in custom_filter["honeypots"]["options"]: + if "error" in record.msg: return None if isinstance(record.msg, Mapping): - if 'remove_init' in custom_filter['honeypots']['options']: - if record.msg.get('action', None) == 'process': + if "remove_init" in custom_filter["honeypots"]["options"]: + if record.msg.get("action", None) == "process": return None - if 'remove_word_server' in custom_filter['honeypots']['options']: - if 'server' in record.msg: - record.msg['server'] = record.msg['server'].replace('_server', '') - if 'honeypots' in custom_filter: + if "remove_word_server" in custom_filter["honeypots"]["options"]: + if "server" in record.msg: + record.msg["server"] = record.msg["server"].replace("_server", "") + if "honeypots" in custom_filter: for key in record.msg.copy(): - if key in custom_filter['honeypots']['change']: - record.msg[custom_filter['honeypots']['change'][key]] = record.msg.pop(key) + if key in custom_filter["honeypots"]["change"]: + record.msg[custom_filter["honeypots"]["change"][key]] = record.msg.pop( + key + ) for key in record.msg.copy(): - if key in custom_filter['honeypots']['remove']: + if key in custom_filter["honeypots"]["remove"]: del record.msg[key] - if custom_filter['honeypots']['contains']: - if not all(k in record.msg for k in custom_filter['honeypots']['contains']): + if custom_filter["honeypots"]["contains"]: + if not all(k in record.msg for k in custom_filter["honeypots"]["contains"]): return None if isinstance(record.msg, Mapping): record.msg = serialize_object({**timestamp, **record.msg}) else: record.msg = serialize_object(record.msg) except Exception as e: - record.msg = serialize_object({'name': record.name, 'error': repr(e)}) + record.msg = serialize_object({"name": record.name, "error": repr(e)}) with suppress(Exception): - if type_ == 'file': + if type_ == "file": if custom_filter is not None: - if 'dump_json_to_file' in custom_filter['honeypots']['options']: + if "dump_json_to_file" in custom_filter["honeypots"]["options"]: record.msg = dumps(record.msg, sort_keys=True, cls=ComplexEncoder) - elif type_ == 'db_postgres': + elif type_ == "db_postgres": pass - elif type_ == 'db_sqlite': - for item in ['data', 'error']: + elif type_ == "db_sqlite": + for item in ["data", "error"]: if item in record.msg: if not isinstance(record.msg[item], str): - record.msg[item] = repr(record.msg[item]).replace('\x00', ' ') + record.msg[item] = repr(record.msg[item]).replace("\x00", " ") else: record.msg = dumps(record.msg, sort_keys=True, cls=ComplexEncoder) return record @@ -114,87 +117,123 @@ def parse_record(record, custom_filter, type_): def get_running_servers(): temp_list = [] with suppress(Exception): - honeypots = ['QDNSServer', 'QFTPServer', 'QHTTPProxyServer', 'QHTTPServer', 'QHTTPSServer', 'QIMAPServer', 'QMysqlServer', 'QPOP3Server', 'QPostgresServer', 'QRedisServer', 'QSMBServer', 'QSMTPServer', 'QSOCKS5Server', 'QSSHServer', 'QTelnetServer', 'QVNCServer', 'QElasticServer', 'QMSSQLServer', 'QLDAPServer', 'QNTPServer', 'QMemcacheServer', 'QOracleServer', 'QSNMPServer'] + honeypots = [ + "QDNSServer", + "QFTPServer", + "QHTTPProxyServer", + "QHTTPServer", + "QHTTPSServer", + "QIMAPServer", + "QMysqlServer", + "QPOP3Server", + "QPostgresServer", + "QRedisServer", + "QSMBServer", + "QSMTPServer", + "QSOCKS5Server", + "QSSHServer", + "QTelnetServer", + "QVNCServer", + "QElasticServer", + "QMSSQLServer", + "QLDAPServer", + "QNTPServer", + "QMemcacheServer", + "QOracleServer", + "QSNMPServer", + ] for process in process_iter(): - cmdline = ' '.join(process.cmdline()) + cmdline = " ".join(process.cmdline()) for honeypot in honeypots: - if '--custom' in cmdline and honeypot in cmdline: - temp_list.append(cmdline.split(' --custom ')[1]) + if "--custom" in cmdline and honeypot in cmdline: + temp_list.append(cmdline.split(" --custom ")[1]) return temp_list def disable_logger(logger_type, object): if logger_type == 1: temp_name = path.join(gettempdir(), next(_get_candidate_names())) - object.startLogging(open(temp_name, 'w'), setStdout=False) + object.startLogging(open(temp_name, "w"), setStdout=False) def setup_logger(name, temp_name, config, drop=False): - logs = 'terminal' - logs_location = '' - syslog_address = '' - syslog_facility = '' + logs = "terminal" + logs_location = "" + syslog_address = "" + syslog_facility = "" config_data = None custom_filter = None - if config and config != '': + if config and config != "": with suppress(Exception): with open(config) as f: config_data = load(f) - logs = config_data.get('logs', logs) - logs_location = config_data.get('logs_location', logs_location) - syslog_address = config_data.get('syslog_address', syslog_address) - syslog_facility = config_data.get('syslog_facility', syslog_facility) - custom_filter = config_data.get('custom_filter', custom_filter) - if logs_location == '' or logs_location is None: - logs_location = path.join(gettempdir(), 'logs') + logs = config_data.get("logs", logs) + logs_location = config_data.get("logs_location", logs_location) + syslog_address = config_data.get("syslog_address", syslog_address) + syslog_facility = config_data.get("syslog_facility", syslog_facility) + custom_filter = config_data.get("custom_filter", custom_filter) + if logs_location == "" or logs_location is None: + logs_location = path.join(gettempdir(), "logs") if not path.exists(logs_location): makedirs(logs_location) file_handler = None ret_logs_obj = getLogger(temp_name) ret_logs_obj.setLevel(DEBUG) - if 'db_postgres' in logs or 'db_sqlite' in logs: + if "db_postgres" in logs or "db_sqlite" in logs: ret_logs_obj.addHandler(CustomHandler(temp_name, logs, custom_filter, config_data, drop)) - elif 'terminal' in logs: + elif "terminal" in logs: ret_logs_obj.addHandler(CustomHandler(temp_name, logs, custom_filter)) - if 'file' in logs: + if "file" in logs: max_bytes = 10000 backup_count = 10 with suppress(Exception): if config_data is not None: - if 'honeypots' in config_data: - temp_server_name = name[1:].lower().replace('server', '') - if temp_server_name in config_data['honeypots']: - if 'log_file_name' in config_data['honeypots'][temp_server_name]: - temp_name = config_data['honeypots'][temp_server_name]['log_file_name'] - if 'max_bytes' in config_data['honeypots'][temp_server_name]: - max_bytes = config_data['honeypots'][temp_server_name]['max_bytes'] - if 'backup_count' in config_data['honeypots'][temp_server_name]: - backup_count = config_data['honeypots'][temp_server_name]['backup_count'] - file_handler = CustomHandlerFileRotate(temp_name, logs, custom_filter, path.join(logs_location, temp_name), maxBytes=max_bytes, backupCount=backup_count) + if "honeypots" in config_data: + temp_server_name = name[1:].lower().replace("server", "") + if temp_server_name in config_data["honeypots"]: + if "log_file_name" in config_data["honeypots"][temp_server_name]: + temp_name = config_data["honeypots"][temp_server_name]["log_file_name"] + if "max_bytes" in config_data["honeypots"][temp_server_name]: + max_bytes = config_data["honeypots"][temp_server_name]["max_bytes"] + if "backup_count" in config_data["honeypots"][temp_server_name]: + backup_count = config_data["honeypots"][temp_server_name][ + "backup_count" + ] + file_handler = CustomHandlerFileRotate( + temp_name, + logs, + custom_filter, + path.join(logs_location, temp_name), + maxBytes=max_bytes, + backupCount=backup_count, + ) ret_logs_obj.addHandler(file_handler) - if 'syslog' in logs: - if syslog_address == '': - address = ('localhost', 514) + if "syslog" in logs: + if syslog_address == "": + address = ("localhost", 514) else: - address = (syslog_address.split('//')[1].split(':')[0], int(syslog_address.split('//')[1].split(':')[1])) + address = ( + syslog_address.split("//")[1].split(":")[0], + int(syslog_address.split("//")[1].split(":")[1]), + ) syslog = SysLogHandler(address=address, facility=syslog_facility) - formatter = Formatter('[%(name)s] [%(levelname)s] - %(message)s') + formatter = Formatter("[%(name)s] [%(levelname)s] - %(message)s") syslog.setFormatter(formatter) ret_logs_obj.addHandler(syslog) return ret_logs_obj def clean_all(): - for entry in scandir('.'): - if entry.is_file() and entry.name.endswith('_server.py'): + for entry in scandir("."): + if entry.is_file() and entry.name.endswith("_server.py"): kill_servers(entry.name) def kill_servers(name): with suppress(Exception): for process in process_iter(): - cmdline = ' '.join(process.cmdline()) - if '--custom' in cmdline and name in cmdline: + cmdline = " ".join(process.cmdline()) + if "--custom" in cmdline and name in cmdline: process.send_signal(SIGTERM) process.kill() @@ -202,8 +241,8 @@ def kill_servers(name): def check_if_server_is_running(uuid): with suppress(Exception): for process in process_iter(): - cmdline = ' '.join(process.cmdline()) - if '--custom' in cmdline and uuid in cmdline: + cmdline = " ".join(process.cmdline()) + if "--custom" in cmdline and uuid in cmdline: return True return False @@ -213,8 +252,8 @@ def kill_server_wrapper(server_name, name, process): if process is not None: process.kill() for process in process_iter(): - cmdline = ' '.join(process.cmdline()) - if '--custom' in cmdline and name in cmdline: + cmdline = " ".join(process.cmdline()) + if "--custom" in cmdline and name in cmdline: process.send_signal(SIGTERM) process.kill() return True @@ -225,7 +264,7 @@ def get_free_port(): port = 0 with suppress(Exception): tcp = socket(AF_INET, SOCK_STREAM) - tcp.bind(('', 0)) + tcp.bind(("", 0)) addr, port = tcp.getsockname() tcp.close() return port @@ -238,7 +277,7 @@ def close_port_wrapper(server_name, ip, port, logs): if sock.connect_ex((ip, port)) == 0: for process in process_iter(): with suppress(Exception): - for conn in process.connections(kind='inet'): + for conn in process.connections(kind="inet"): if port == conn.laddr.port: process.send_signal(SIGTERM) process.kill() @@ -249,18 +288,18 @@ def close_port_wrapper(server_name, ip, port, logs): if sock.connect_ex((ip, port)) != 0 and ret: return True else: - logs.error({'server': server_name, 'error': 'port_open.. {} still open..'.format(ip)}) + logs.error({"server": server_name, "error": f"port_open.. {ip} still open.."}) return False class ComplexEncoder(JSONEncoder): def default(self, obj): - return repr(obj).replace('\x00', ' ') + return repr(obj).replace("\x00", " ") class ComplexEncoder_db(JSONEncoder): def default(self, obj): - return 'Something wrong, deleted..' + return "Something wrong, deleted.." def serialize_object(_dict): @@ -271,81 +310,117 @@ def serialize_object(_dict): elif isinstance(_dict, (int, float)): return str(_dict) elif isinstance(_dict, str): - return _dict.replace('\x00', ' ') + return _dict.replace("\x00", " ") elif isinstance(_dict, bytes): - return _dict.decode('utf-8', 'ignore').replace('\x00', ' ') + return _dict.decode("utf-8", "ignore").replace("\x00", " ") else: - return repr(_dict).replace('\x00', ' ') + return repr(_dict).replace("\x00", " ") class CustomHandlerFileRotate(RotatingFileHandler): - def __init__(self, uuid='', logs='', custom_filter=None, filename='', mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False, errors=None): + def __init__( + self, + uuid="", + logs="", + custom_filter=None, + filename="", + mode="a", + maxBytes=0, + backupCount=0, + encoding=None, + delay=False, + errors=None, + ): self.logs = logs self.custom_filter = custom_filter RotatingFileHandler.__init__(self, filename, mode, maxBytes, backupCount, encoding, delay) def emit(self, record): - _record = parse_record(record, self.custom_filter, 'file') + _record = parse_record(record, self.custom_filter, "file") if _record is not None: super().emit(_record) class CustomHandler(Handler): - def __init__(self, uuid='', logs='', custom_filter=None, config=None, drop=False): - self.db = {'db_postgres': None, 'db_sqlite': None} + def __init__(self, uuid="", logs="", custom_filter=None, config=None, drop=False): + self.db = {"db_postgres": None, "db_sqlite": None} self.logs = logs self.uuid = uuid self.custom_filter = custom_filter - if config and config != '' and 'db_postgres' in self.logs: - parsed = urlparse(config['postgres']) - self.db['db_postgres'] = postgres_class(host=parsed.hostname, port=parsed.port, username=parsed.username, password=parsed.password, db=parsed.path[1:], uuid=self.uuid, drop=drop) - if config and config != '' and 'db_sqlite' in self.logs: - self.db['db_sqlite'] = sqlite_class(file=config["sqlite_file"], drop=drop, uuid=self.uuid) + if config and config != "" and "db_postgres" in self.logs: + parsed = urlparse(config["postgres"]) + self.db["db_postgres"] = postgres_class( + host=parsed.hostname, + port=parsed.port, + username=parsed.username, + password=parsed.password, + db=parsed.path[1:], + uuid=self.uuid, + drop=drop, + ) + if config and config != "" and "db_sqlite" in self.logs: + self.db["db_sqlite"] = sqlite_class( + file=config["sqlite_file"], drop=drop, uuid=self.uuid + ) Handler.__init__(self) def emit(self, record): try: - if 'db_postgres' in self.logs: - if self.db['db_postgres']: + if "db_postgres" in self.logs: + if self.db["db_postgres"]: if isinstance(record.msg, list): - if record.msg[0] == 'sniffer' or record.msg[0] == 'errors': - self.db['db_postgres'].insert_into_data_safe(record.msg[0], dumps(serialize_object(record.msg[1]), cls=ComplexEncoder)) + if record.msg[0] == "sniffer" or record.msg[0] == "errors": + self.db["db_postgres"].insert_into_data_safe( + record.msg[0], + dumps(serialize_object(record.msg[1]), cls=ComplexEncoder), + ) elif isinstance(record.msg, Mapping): - if 'server' in record.msg: - self.db['db_postgres'].insert_into_data_safe('servers', dumps(serialize_object(record.msg), cls=ComplexEncoder)) - if 'db_sqlite' in self.logs: - _record = parse_record(record, self.custom_filter, 'db_sqlite') + if "server" in record.msg: + self.db["db_postgres"].insert_into_data_safe( + "servers", dumps(serialize_object(record.msg), cls=ComplexEncoder) + ) + if "db_sqlite" in self.logs: + _record = parse_record(record, self.custom_filter, "db_sqlite") if _record: - self.db['db_sqlite'].insert_into_data_safe(_record.msg) - if 'terminal' in self.logs: - _record = parse_record(record, self.custom_filter, 'terminal') + self.db["db_sqlite"].insert_into_data_safe(_record.msg) + if "terminal" in self.logs: + _record = parse_record(record, self.custom_filter, "terminal") if _record: - stdout.write(_record.msg + '\n') - if 'syslog' in self.logs: - _record = parse_record(record, self.custom_filter, 'terminal') + stdout.write(_record.msg + "\n") + if "syslog" in self.logs: + _record = parse_record(record, self.custom_filter, "terminal") if _record: - stdout.write(_record.msg + '\n') + stdout.write(_record.msg + "\n") except Exception as e: if self.custom_filter is not None: - if 'honeypots' in self.custom_filter: - if 'remove_errors' in self.custom_filter['honeypots']['options']: - return None - stdout.write(dumps({'error': repr(e), 'logger': repr(record)}, sort_keys=True, cls=ComplexEncoder) + '\n') + if "honeypots" in self.custom_filter: + if "remove_errors" in self.custom_filter["honeypots"]["options"]: + return + stdout.write( + dumps( + {"error": repr(e), "logger": repr(record)}, sort_keys=True, cls=ComplexEncoder + ) + + "\n" + ) stdout.flush() -class postgres_class(): - def __init__(self, host=None, port=None, username=None, password=None, db=None, drop=False, uuid=None): +class postgres_class: + def __init__( + self, host=None, port=None, username=None, password=None, db=None, drop=False, uuid=None + ): self.host = host self.port = port self.username = username self.password = password self.db = db self.uuid = uuid - self.mapped_tables = ['errors', 'servers', 'sniffer', 'system'] + self.mapped_tables = ["errors", "servers", "sniffer", "system"] self.wait_until_up() if drop: - self.con = psycopg2_connect(host=self.host, port=self.port, user=self.username, password=self.password) + self.con = psycopg2_connect( + host=self.host, port=self.port, user=self.username, password=self.password + ) self.con.set_isolation_level(0) self.cur = self.con.cursor() self.drop_db() @@ -353,15 +428,23 @@ def __init__(self, host=None, port=None, username=None, password=None, db=None, self.create_db() self.con.close() else: - self.con = psycopg2_connect(host=self.host, port=self.port, user=self.username, password=self.password) + self.con = psycopg2_connect( + host=self.host, port=self.port, user=self.username, password=self.password + ) self.con.set_isolation_level(0) self.cur = self.con.cursor() if not self.check_db_if_exists(): self.create_db() self.con.close() - self.con = psycopg2_connect(host=self.host, port=self.port, user=self.username, password=self.password, database=self.db) + self.con = psycopg2_connect( + host=self.host, + port=self.port, + user=self.username, + password=self.password, + database=self.db, + ) self.con.set_isolation_level(0) - self.con.set_client_encoding('UTF8') + self.con.set_client_encoding("UTF8") self.cur = self.con.cursor() self.create_tables() @@ -369,13 +452,19 @@ def wait_until_up(self): test = True while test: with suppress(Exception): - print('{} - Waiting on postgres connection'.format(self.uuid)) + print(f"{self.uuid} - Waiting on postgres connection") stdout.flush() - conn = psycopg2_connect(host=self.host, port=self.port, user=self.username, password=self.password, connect_timeout=1) + conn = psycopg2_connect( + host=self.host, + port=self.port, + user=self.username, + password=self.password, + connect_timeout=1, + ) conn.close() test = False sleep(1) - print('{} - postgres connection is good'.format(self.uuid)) + print(f"{self.uuid} - postgres connection is good") def addattr(self, x, val): self.__dict__[x] = val @@ -383,50 +472,84 @@ def addattr(self, x, val): def check_db_if_exists(self): exists = False with suppress(Exception): - self.cur.execute('SELECT exists(SELECT 1 from pg_catalog.pg_database where datname = %s)', (self.db,)) + self.cur.execute( + "SELECT exists(SELECT 1 from pg_catalog.pg_database where datname = %s)", + (self.db,), + ) if self.cur.fetchone()[0]: exists = True return exists def drop_db(self): with suppress(Exception): - print('[x] Dropping {} db'.format(self.db)) + print(f"[x] Dropping {self.db} db") if self.check_db_if_exists(): - self.cur.execute(sql.SQL('drop DATABASE IF EXISTS {}').format(sql.Identifier(self.db))) + self.cur.execute( + sql.SQL("drop DATABASE IF EXISTS {}").format(sql.Identifier(self.db)) + ) sleep(2) - self.cur.execute(sql.SQL('CREATE DATABASE {}').format(sql.Identifier(self.db))) + self.cur.execute(sql.SQL("CREATE DATABASE {}").format(sql.Identifier(self.db))) def create_db(self): print("create") - self.cur.execute(sql.SQL('CREATE DATABASE {}').format(sql.Identifier(self.db))) + self.cur.execute(sql.SQL("CREATE DATABASE {}").format(sql.Identifier(self.db))) - def drop_tables(self,): + def drop_tables( + self, + ): for x in self.mapped_tables: - self.cur.execute(sql.SQL('drop TABLE IF EXISTS {}').format(sql.Identifier(x + '_table'))) + self.cur.execute( + sql.SQL("drop TABLE IF EXISTS {}").format(sql.Identifier(x + "_table")) + ) def create_tables(self): for x in self.mapped_tables: - self.cur.execute(sql.SQL('CREATE TABLE IF NOT EXISTS {} (id SERIAL NOT NULL,date timestamp with time zone DEFAULT now(),data json)').format(sql.Identifier(x + '_table'))) + self.cur.execute( + sql.SQL( + "CREATE TABLE IF NOT EXISTS {} (id SERIAL NOT NULL,date timestamp with time zone DEFAULT now(),data json)" + ).format(sql.Identifier(x + "_table")) + ) def insert_into_data_safe(self, table, obj): with suppress(Exception): - self.cur.execute(sql.SQL('INSERT INTO {} (id,date, data) VALUES (DEFAULT ,now(), %s)').format(sql.Identifier(table + '_table')), [obj]) + self.cur.execute( + sql.SQL("INSERT INTO {} (id,date, data) VALUES (DEFAULT ,now(), %s)").format( + sql.Identifier(table + "_table") + ), + [obj], + ) -class sqlite_class(): +class sqlite_class: def __init__(self, file=None, drop=False, uuid=None): self.file = file self.uuid = uuid - self.mapped_tables = ['servers'] - self.servers_table_template = {'server': 'servers_table', 'action': None, 'status': None, 'src_ip': None, 'src_port': None, 'username': None, 'password': None, 'dest_ip': None, 'dest_port': None, 'data': None, 'error': None} + self.mapped_tables = ["servers"] + self.servers_table_template = { + "server": "servers_table", + "action": None, + "status": None, + "src_ip": None, + "src_port": None, + "username": None, + "password": None, + "dest_ip": None, + "dest_port": None, + "data": None, + "error": None, + } self.wait_until_up() if drop: - self.con = sqlite3_connect(self.file, timeout=1, isolation_level=None, check_same_thread=False) + self.con = sqlite3_connect( + self.file, timeout=1, isolation_level=None, check_same_thread=False + ) self.cur = self.con.cursor() self.drop_db() self.drop_tables() self.con.close() - self.con = sqlite3_connect(self.file, timeout=1, isolation_level=None, check_same_thread=False) + self.con = sqlite3_connect( + self.file, timeout=1, isolation_level=None, check_same_thread=False + ) self.cur = self.con.cursor() self.create_tables() @@ -434,21 +557,21 @@ def wait_until_up(self): test = True while test: with suppress(Exception): - print('{} - Waiting on sqlite connection'.format(self.uuid)) + print(f"{self.uuid} - Waiting on sqlite connection") conn = sqlite3_connect(self.file, timeout=1, check_same_thread=False) conn.close() test = False sleep(1) - print('{} - sqlite connection is good'.format(self.uuid)) + print(f"{self.uuid} - sqlite connection is good") def drop_db_test(self): with suppress(Exception): file_exists = False sql_file = False - with open(self.file, 'rb') as f: + with open(self.file, "rb") as f: file_exists = True header = f.read(100) - if header[:16] == b'SQLite format 3\x00': + if header[:16] == b"SQLite format 3\x00": sql_file = True if sql_file: print("yes") @@ -458,43 +581,104 @@ def drop_db(self): file = Path(self.file) file.unlink(missing_ok=False) - def drop_tables(self,): + def drop_tables( + self, + ): with suppress(Exception): for x in self.mapped_tables: - self.cur.execute("DROP TABLE IF EXISTS '{:s}'".format(x)) + self.cur.execute(f"DROP TABLE IF EXISTS '{x:s}'") def create_tables(self): with suppress(Exception): - self.cur.execute("CREATE TABLE IF NOT EXISTS '{:s}' (id INTEGER PRIMARY KEY,date DATETIME DEFAULT CURRENT_TIMESTAMP,server text, action text, status text, src_ip text, src_port text,dest_ip text, dest_port text, username text, password text, data text, error text)".format('servers_table')) + self.cur.execute( + "CREATE TABLE IF NOT EXISTS '{:s}' (id INTEGER PRIMARY KEY,date DATETIME DEFAULT CURRENT_TIMESTAMP,server text, action text, status text, src_ip text, src_port text,dest_ip text, dest_port text, username text, password text, data text, error text)".format( + "servers_table" + ) + ) def insert_into_data_safe(self, obj): with suppress(Exception): parsed = {k: v for k, v in obj.items() if v is not None} dict_ = {**self.servers_table_template, **parsed} - self.cur.execute("INSERT INTO servers_table (server, action, status, src_ip, src_port, dest_ip, dest_port, username, password, data, error) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (dict_['server'], dict_['action'], dict_['status'], dict_['src_ip'], dict_['src_port'], dict_['dest_ip'], dict_['dest_port'], dict_['username'], dict_['password'], dict_['data'], dict_['error'])) + self.cur.execute( + "INSERT INTO servers_table (server, action, status, src_ip, src_port, dest_ip, dest_port, username, password, data, error) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + dict_["server"], + dict_["action"], + dict_["status"], + dict_["src_ip"], + dict_["src_port"], + dict_["dest_ip"], + dict_["dest_port"], + dict_["username"], + dict_["password"], + dict_["data"], + dict_["error"], + ), + ) def server_arguments(): - _server_parser = ArgumentParser(prog='Server') - _server_parsergroupdeq = _server_parser.add_argument_group('Initialize Server') - _server_parsergroupdeq.add_argument('--ip', type=str, help='Change server ip, current is 0.0.0.0', required=False, metavar='') - _server_parsergroupdeq.add_argument('--port', type=int, help='Change port', required=False, metavar='') - _server_parsergroupdeq.add_argument('--username', type=str, help='Change username', required=False, metavar='') - _server_parsergroupdeq.add_argument('--password', type=str, help='Change password', required=False, metavar='') - _server_parsergroupdeq.add_argument('--resolver_addresses', type=str, help='Change resolver address', required=False, metavar='') - _server_parsergroupdeq.add_argument('--domain', type=str, help='A domain to test', required=False, metavar='') - _server_parsergroupdeq.add_argument('--folders', type=str, help='folders for smb as name:target,name:target', required=False, metavar='') - _server_parsergroupdeq.add_argument('--options', type=str, help='Extra options', metavar='', default='') - _server_parsergroupdes = _server_parser.add_argument_group('Sinffer options') - _server_parsergroupdes.add_argument('--filter', type=str, help='setup the Sinffer filter', required=False) - _server_parsergroupdes.add_argument('--interface', type=str, help='sinffer interface E.g eth0', required=False) - _server_parsergroupdef = _server_parser.add_argument_group('Initialize Loging') - _server_parsergroupdef.add_argument('--config', type=str, help='config file for logs and database', required=False, default='') - _server_parsergroupdea = _server_parser.add_argument_group('Auto Configuration') - _server_parsergroupdea.add_argument('--docker', action='store_true', help='Run project in docker', required=False) - _server_parsergroupdea.add_argument('--aws', action='store_true', help='Run project in aws', required=False) - _server_parsergroupdea.add_argument('--test', action='store_true', help='Test current server', required=False) - _server_parsergroupdea.add_argument('--custom', action='store_true', help='Run custom server', required=False) - _server_parsergroupdea.add_argument('--auto', action='store_true', help='Run auto configured with random port', required=False) - _server_parsergroupdef.add_argument('--uuid', type=str, help='unique id', required=False) + _server_parser = ArgumentParser(prog="Server") + _server_parsergroupdeq = _server_parser.add_argument_group("Initialize Server") + _server_parsergroupdeq.add_argument( + "--ip", type=str, help="Change server ip, current is 0.0.0.0", required=False, metavar="" + ) + _server_parsergroupdeq.add_argument( + "--port", type=int, help="Change port", required=False, metavar="" + ) + _server_parsergroupdeq.add_argument( + "--username", type=str, help="Change username", required=False, metavar="" + ) + _server_parsergroupdeq.add_argument( + "--password", type=str, help="Change password", required=False, metavar="" + ) + _server_parsergroupdeq.add_argument( + "--resolver_addresses", + type=str, + help="Change resolver address", + required=False, + metavar="", + ) + _server_parsergroupdeq.add_argument( + "--domain", type=str, help="A domain to test", required=False, metavar="" + ) + _server_parsergroupdeq.add_argument( + "--folders", + type=str, + help="folders for smb as name:target,name:target", + required=False, + metavar="", + ) + _server_parsergroupdeq.add_argument( + "--options", type=str, help="Extra options", metavar="", default="" + ) + _server_parsergroupdes = _server_parser.add_argument_group("Sinffer options") + _server_parsergroupdes.add_argument( + "--filter", type=str, help="setup the Sinffer filter", required=False + ) + _server_parsergroupdes.add_argument( + "--interface", type=str, help="sinffer interface E.g eth0", required=False + ) + _server_parsergroupdef = _server_parser.add_argument_group("Initialize Loging") + _server_parsergroupdef.add_argument( + "--config", type=str, help="config file for logs and database", required=False, default="" + ) + _server_parsergroupdea = _server_parser.add_argument_group("Auto Configuration") + _server_parsergroupdea.add_argument( + "--docker", action="store_true", help="Run project in docker", required=False + ) + _server_parsergroupdea.add_argument( + "--aws", action="store_true", help="Run project in aws", required=False + ) + _server_parsergroupdea.add_argument( + "--test", action="store_true", help="Test current server", required=False + ) + _server_parsergroupdea.add_argument( + "--custom", action="store_true", help="Run custom server", required=False + ) + _server_parsergroupdea.add_argument( + "--auto", action="store_true", help="Run auto configured with random port", required=False + ) + _server_parsergroupdef.add_argument("--uuid", type=str, help="unique id", required=False) return _server_parser.parse_args() diff --git a/honeypots/http_proxy_server.py b/honeypots/http_proxy_server.py index 59cac7d..5903daf 100644 --- a/honeypots/http_proxy_server.py +++ b/honeypots/http_proxy_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,11 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from pathlib import Path from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') +filterwarnings(action="ignore", module=".*OpenSSL.*") from dns.resolver import query as dsnquery from twisted.internet import reactor @@ -21,7 +21,16 @@ from subprocess import Popen from email.parser import BytesParser from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress @@ -29,43 +38,70 @@ DUMMY_TEMPLATE = (Path(__file__).parent / "data" / "dummy_page.html").read_text() -class QHTTPProxyServer(): +class QHTTPProxyServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 8080 - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 8080 + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def http_proxy_server_main(self): _q_s = self class CustomProtocolParent(Protocol): - def __init__(self): self.buffer = None self.client = None def resolve_domain(self, request_string): with suppress(Exception): - _, parsed_request = request_string.split(b'\r\n', 1) + _, parsed_request = request_string.split(b"\r\n", 1) headers = BytesParser().parsebytes(parsed_request) - host = headers['host'].split(':') - _q_s.logs.info({'server': 'http_proxy_server', 'action': 'query', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': host[0]}) + host = headers["host"].split(":") + _q_s.logs.info( + { + "server": "http_proxy_server", + "action": "query", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": host[0], + } + ) # return '127.0.0.1' - return dsnquery(host[0], 'A')[0].address + return dsnquery(host[0], "A")[0].address return None def dataReceived(self, data): - _q_s.logs.info({'server': 'http_proxy_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "http_proxy_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) ip = self.resolve_domain(data) if ip: self.write(_create_dummy_response(DUMMY_TEMPLATE)) @@ -89,7 +125,7 @@ def write(self, data): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -101,13 +137,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'http_proxy_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "http_proxy_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -116,20 +178,21 @@ def run_server(self, process=False, auto=False): self.http_proxy_server_main() def close_port(self): - ret = close_port_wrapper('http_proxy_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("http_proxy_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('http_proxy_server', self.uuid, self.process) + ret = kill_server_wrapper("http_proxy_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, domain=None): with suppress(Exception): from requests import get + _ip = ip or self.ip _port = port or self.port - _domain = domain or 'http://yahoo.com' - get(_domain, proxies={'http': 'http://{}:{}'.format(_ip, _port)}).text.encode('ascii', 'ignore') + _domain = domain or "http://yahoo.com" + get(_domain, proxies={"http": f"http://{_ip}:{_port}"}).text.encode("ascii", "ignore") def _create_dummy_response(content: str) -> bytes: @@ -142,8 +205,10 @@ def _create_dummy_response(content: str) -> bytes: return "\r\n".join(response).encode() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qhttpproxyserver = QHTTPProxyServer(ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config) + qhttpproxyserver = QHTTPProxyServer( + ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config + ) qhttpproxyserver.run_server() diff --git a/honeypots/http_server.py b/honeypots/http_server.py index c6adc51..305293a 100644 --- a/honeypots/http_server.py +++ b/honeypots/http_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from cgi import FieldStorage from requests.packages.urllib3 import disable_warnings @@ -23,42 +24,85 @@ from tempfile import gettempdir, _get_candidate_names from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress disable_warnings() -class QHTTPServer(): +class QHTTPServer: def __init__(self, **kwargs): self.auto_disabled = None self.key = path.join(gettempdir(), next(_get_candidate_names())) self.cert = path.join(gettempdir(), next(_get_candidate_names())) - self.mocking_server = choice(['Apache', 'nginx', 'Microsoft-IIS/7.5', 'Microsoft-HTTPAPI/2.0', 'Apache/2.2.15', 'SmartXFilter', 'Microsoft-IIS/8.5', 'Apache/2.4.6', 'Apache-Coyote/1.1', 'Microsoft-IIS/7.0', 'Apache/2.4.18', 'AkamaiGHost', 'Apache/2.2.25', 'Microsoft-IIS/10.0', 'Apache/2.2.3', 'nginx/1.12.1', 'Apache/2.4.29', 'cloudflare', 'Apache/2.2.22']) + self.mocking_server = choice( + [ + "Apache", + "nginx", + "Microsoft-IIS/7.5", + "Microsoft-HTTPAPI/2.0", + "Apache/2.2.15", + "SmartXFilter", + "Microsoft-IIS/8.5", + "Apache/2.4.6", + "Apache-Coyote/1.1", + "Microsoft-IIS/7.0", + "Apache/2.4.18", + "AkamaiGHost", + "Apache/2.2.25", + "Microsoft-IIS/10.0", + "Apache/2.2.3", + "nginx/1.12.1", + "Apache/2.4.29", + "cloudflare", + "Apache/2.2.22", + ] + ) self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 80 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 80 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def http_server_main(self): _q_s = self class MainResource(Resource): - isLeaf = True - home_file = b''' + home_file = b""" @@ -79,9 +123,9 @@ class MainResource(Resource): -''' +""" - login_file = b''' + login_file = b""" @@ -110,7 +154,7 @@ class MainResource(Resource): -''' +""" def check_bytes(self, string): if isinstance(string, bytes): @@ -119,80 +163,136 @@ def check_bytes(self, string): return str(string) def render(self, request): - headers = {} client_ip = "" with suppress(Exception): + def check_bytes(string): if isinstance(string, bytes): return string.decode() else: return str(string) + for item, value in dict(request.requestHeaders.getAllRawHeaders()).items(): - headers.update({check_bytes(item): ','.join(map(check_bytes, value))}) - headers.update({'method': check_bytes(request.method)}) - headers.update({'uri': check_bytes(request.uri)}) + headers.update({check_bytes(item): ",".join(map(check_bytes, value))}) + headers.update({"method": check_bytes(request.method)}) + headers.update({"uri": check_bytes(request.uri)}) - if 'fix_get_client_ip' in _q_s.options: + if "fix_get_client_ip" in _q_s.options: with suppress(Exception): raw_headers = dict(request.requestHeaders.getAllRawHeaders()) - if b'X-Forwarded-For' in raw_headers: - client_ip = check_bytes(raw_headers[b'X-Forwarded-For'][0]) - elif b'X-Real-IP' in raw_headers: - client_ip = check_bytes(raw_headers[b'X-Real-IP'][0]) + if b"X-Forwarded-For" in raw_headers: + client_ip = check_bytes(raw_headers[b"X-Forwarded-For"][0]) + elif b"X-Real-IP" in raw_headers: + client_ip = check_bytes(raw_headers[b"X-Real-IP"][0]) if client_ip == "": client_ip = request.getClientAddress().host with suppress(Exception): if "capture_commands" in _q_s.options: - _q_s.logs.info({'server': 'http_server', 'action': 'connection', 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': headers}) + _q_s.logs.info( + { + "server": "http_server", + "action": "connection", + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": headers, + } + ) else: - _q_s.logs.info({'server': 'http_server', 'action': 'connection', 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) - - if _q_s.mocking_server != '': - request.responseHeaders.removeHeader('Server') - request.responseHeaders.addRawHeader('Server', _q_s.mocking_server) - - if request.method == b'GET' or request.method == b'POST': - _q_s.logs.info({'server': 'http_server', 'action': request.method.decode(), 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) - - if request.method == b'GET': - if request.uri == b'/login.html': - if _q_s.username != '' and _q_s.password != '': - request.responseHeaders.addRawHeader('Content-Type', 'text/html; charset=utf-8') + _q_s.logs.info( + { + "server": "http_server", + "action": "connection", + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) + + if _q_s.mocking_server != "": + request.responseHeaders.removeHeader("Server") + request.responseHeaders.addRawHeader("Server", _q_s.mocking_server) + + if request.method == b"GET" or request.method == b"POST": + _q_s.logs.info( + { + "server": "http_server", + "action": request.method.decode(), + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) + + if request.method == b"GET": + if request.uri == b"/login.html": + if _q_s.username != "" and _q_s.password != "": + request.responseHeaders.addRawHeader( + "Content-Type", "text/html; charset=utf-8" + ) return self.login_file - request.responseHeaders.addRawHeader('Content-Type', 'text/html; charset=utf-8') + request.responseHeaders.addRawHeader( + "Content-Type", "text/html; charset=utf-8" + ) return self.login_file - elif request.method == b'POST': + elif request.method == b"POST": self.headers = request.getAllHeaders() - if request.uri == b'/login.html' or b'/': - if _q_s.username != '' and _q_s.password != '': - form = FieldStorage(fp=request.content, headers=self.headers, environ={'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': self.headers[b'content-type'], }) - if 'username' in form and 'password' in form: - username = self.check_bytes(form['username'].value) - password = self.check_bytes(form['password'].value) - status = 'failed' + if request.uri == b"/login.html" or b"/": + if _q_s.username != "" and _q_s.password != "": + form = FieldStorage( + fp=request.content, + headers=self.headers, + environ={ + "REQUEST_METHOD": "POST", + "CONTENT_TYPE": self.headers[b"content-type"], + }, + ) + if "username" in form and "password" in form: + username = self.check_bytes(form["username"].value) + password = self.check_bytes(form["password"].value) + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'http_server', 'action': 'login', 'status': status, 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'username': username, 'password': password, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) - - request.responseHeaders.addRawHeader('Content-Type', 'text/html; charset=utf-8') + status = "success" + _q_s.logs.info( + { + "server": "http_server", + "action": "login", + "status": status, + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "username": username, + "password": password, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) + + request.responseHeaders.addRawHeader( + "Content-Type", "text/html; charset=utf-8" + ) return self.home_file else: - request.responseHeaders.addRawHeader('Content-Type', 'text/html; charset=utf-8') + request.responseHeaders.addRawHeader( + "Content-Type", "text/html; charset=utf-8" + ) return self.home_file reactor.listenTCP(self.port, Site(MainResource())) reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -204,13 +304,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'http_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "http_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -219,26 +351,37 @@ def run_server(self, process=False, auto=False): self.http_server_main() def close_port(self): - ret = close_port_wrapper('http_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("http_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('http_server', self.uuid, self.process) + ret = kill_server_wrapper("http_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from requests import get, post + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password - get('http://{}:{}'.format(_ip, _port), verify=False) - post('http://{}:{}/login.html'.format(_ip, _port), data={'username': (None, _username), 'password': (None, _password)}) + get(f"http://{_ip}:{_port}", verify=False) + post( + f"http://{_ip}:{_port}/login.html", + data={"username": (None, _username), "password": (None, _password)}, + ) -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qhttpserver = QHTTPServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qhttpserver = QHTTPServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qhttpserver.run_server() diff --git a/honeypots/https_server.py b/honeypots/https_server.py index 30b4d85..679e80b 100644 --- a/honeypots/https_server.py +++ b/honeypots/https_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from OpenSSL import crypto from cgi import FieldStorage @@ -24,43 +25,87 @@ from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress disable_warnings() -class QHTTPSServer(): +class QHTTPSServer: def __init__(self, **kwargs): self.auto_disabled = None self.key = path.join(gettempdir(), next(_get_candidate_names())) self.cert = path.join(gettempdir(), next(_get_candidate_names())) - self.mocking_server = choice(['Apache', 'nginx', 'Microsoft-IIS/7.5', 'Microsoft-HTTPAPI/2.0', 'Apache/2.2.15', 'SmartXFilter', 'Microsoft-IIS/8.5', 'Apache/2.4.6', 'Apache-Coyote/1.1', 'Microsoft-IIS/7.0', 'Apache/2.4.18', 'AkamaiGHost', 'Apache/2.2.25', 'Microsoft-IIS/10.0', 'Apache/2.2.3', 'nginx/1.12.1', 'Apache/2.4.29', 'cloudflare', 'Apache/2.2.22']) + self.mocking_server = choice( + [ + "Apache", + "nginx", + "Microsoft-IIS/7.5", + "Microsoft-HTTPAPI/2.0", + "Apache/2.2.15", + "SmartXFilter", + "Microsoft-IIS/8.5", + "Apache/2.4.6", + "Apache-Coyote/1.1", + "Microsoft-IIS/7.0", + "Apache/2.4.18", + "AkamaiGHost", + "Apache/2.2.25", + "Microsoft-IIS/10.0", + "Apache/2.2.3", + "nginx/1.12.1", + "Apache/2.4.29", + "cloudflare", + "Apache/2.2.22", + ] + ) self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 443 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 443 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def CreateCert(self, host_name, key, cert): pk = crypto.PKey() pk.generate_key(crypto.TYPE_RSA, 2048) c = crypto.X509() - c.get_subject().C = 'US' - c.get_subject().ST = 'OR' - c.get_subject().L = 'None' - c.get_subject().O = 'None' - c.get_subject().OU = 'None' + c.get_subject().C = "US" + c.get_subject().ST = "OR" + c.get_subject().L = "None" + c.get_subject().O = "None" + c.get_subject().OU = "None" c.get_subject().CN = next(_get_candidate_names()) c.set_serial_number(0) before, after = (0, 60 * 60 * 24 * 365 * 2) @@ -68,17 +113,16 @@ def CreateCert(self, host_name, key, cert): c.gmtime_adj_notAfter(after) c.set_issuer(c.get_subject()) c.set_pubkey(pk) - c.sign(pk, 'sha256') - open(cert, 'wb').write(crypto.dump_certificate(crypto.FILETYPE_PEM, c)) - open(key, 'wb').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk)) + c.sign(pk, "sha256") + open(cert, "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, c)) + open(key, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk)) def https_server_main(self): _q_s = self class MainResource(Resource): - isLeaf = True - home_file = b''' + home_file = b""" @@ -99,9 +143,9 @@ class MainResource(Resource): -''' +""" - login_file = b''' + login_file = b""" @@ -130,7 +174,7 @@ class MainResource(Resource): -''' +""" def check_bytes(self, string): if isinstance(string, bytes): @@ -139,11 +183,11 @@ def check_bytes(self, string): return str(string) def render(self, request): - headers = {} client_ip = "" with suppress(Exception): + def check_bytes(string): if isinstance(string, bytes): return string.decode() @@ -151,71 +195,126 @@ def check_bytes(string): return str(string) for item, value in dict(request.requestHeaders.getAllRawHeaders()).items(): - headers.update({check_bytes(item): ','.join(map(check_bytes, value))}) - headers.update({'method': check_bytes(request.method)}) - headers.update({'uri': check_bytes(request.uri)}) + headers.update({check_bytes(item): ",".join(map(check_bytes, value))}) + headers.update({"method": check_bytes(request.method)}) + headers.update({"uri": check_bytes(request.uri)}) - if 'fix_get_client_ip' in _q_s.options: + if "fix_get_client_ip" in _q_s.options: with suppress(Exception): raw_headers = dict(request.requestHeaders.getAllRawHeaders()) - if b'X-Forwarded-For' in raw_headers: - client_ip = check_bytes(raw_headers[b'X-Forwarded-For'][0]) - elif b'X-Real-IP' in raw_headers: - client_ip = check_bytes(raw_headers[b'X-Real-IP'][0]) + if b"X-Forwarded-For" in raw_headers: + client_ip = check_bytes(raw_headers[b"X-Forwarded-For"][0]) + elif b"X-Real-IP" in raw_headers: + client_ip = check_bytes(raw_headers[b"X-Real-IP"][0]) if client_ip == "": client_ip = request.getClientAddress().host with suppress(Exception): if "capture_commands" in _q_s.options: - _q_s.logs.info({'server': 'https_server', 'action': 'connection', 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': headers}) + _q_s.logs.info( + { + "server": "https_server", + "action": "connection", + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": headers, + } + ) else: - _q_s.logs.info({'server': 'https_server', 'action': 'connection', 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) - - if _q_s.mocking_server != '': - request.responseHeaders.removeHeader('Server') - request.responseHeaders.addRawHeader('Server', _q_s.mocking_server) - - if request.method == b'GET' or request.method == b'POST': - _q_s.logs.info({'server': 'https_server', 'action': request.method.decode(), 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) - - if request.method == b'GET': - if request.uri == b'/login.html': - if _q_s.username != '' and _q_s.password != '': - request.responseHeaders.addRawHeader('Content-Type', 'text/html; charset=utf-8') + _q_s.logs.info( + { + "server": "https_server", + "action": "connection", + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) + + if _q_s.mocking_server != "": + request.responseHeaders.removeHeader("Server") + request.responseHeaders.addRawHeader("Server", _q_s.mocking_server) + + if request.method == b"GET" or request.method == b"POST": + _q_s.logs.info( + { + "server": "https_server", + "action": request.method.decode(), + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) + + if request.method == b"GET": + if request.uri == b"/login.html": + if _q_s.username != "" and _q_s.password != "": + request.responseHeaders.addRawHeader( + "Content-Type", "text/html; charset=utf-8" + ) return self.login_file - request.responseHeaders.addRawHeader('Content-Type', 'text/html; charset=utf-8') + request.responseHeaders.addRawHeader( + "Content-Type", "text/html; charset=utf-8" + ) return self.login_file - elif request.method == b'POST': + elif request.method == b"POST": self.headers = request.getAllHeaders() - if request.uri == b'/login.html' or b'/': - if _q_s.username != '' and _q_s.password != '': - form = FieldStorage(fp=request.content, headers=self.headers, environ={'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': self.headers[b'content-type'], }) - if 'username' in form and 'password' in form: - username = self.check_bytes(form['username'].value) - password = self.check_bytes(form['password'].value) - status = 'failed' + if request.uri == b"/login.html" or b"/": + if _q_s.username != "" and _q_s.password != "": + form = FieldStorage( + fp=request.content, + headers=self.headers, + environ={ + "REQUEST_METHOD": "POST", + "CONTENT_TYPE": self.headers[b"content-type"], + }, + ) + if "username" in form and "password" in form: + username = self.check_bytes(form["username"].value) + password = self.check_bytes(form["password"].value) + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'https_server', 'action': 'login', 'status': status, 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'username': username, 'password': password, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) - - request.responseHeaders.addRawHeader('Content-Type', 'text/html; charset=utf-8') + status = "success" + _q_s.logs.info( + { + "server": "https_server", + "action": "login", + "status": status, + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "username": username, + "password": password, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) + + request.responseHeaders.addRawHeader( + "Content-Type", "text/html; charset=utf-8" + ) return self.home_file else: - request.responseHeaders.addRawHeader('Content-Type', 'text/html; charset=utf-8') + request.responseHeaders.addRawHeader( + "Content-Type", "text/html; charset=utf-8" + ) return self.home_file - self.CreateCert('localhost', self.key, self.cert) + self.CreateCert("localhost", self.key, self.cert) ssl_context = ssl.DefaultOpenSSLContextFactory(self.key, self.cert) reactor.listenSSL(self.port, Site(MainResource()), ssl_context) reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -227,13 +326,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'https_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "https_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -242,26 +373,38 @@ def run_server(self, process=False, auto=False): self.https_server_main() def close_port(self): - ret = close_port_wrapper('https_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("https_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('https_server', self.uuid, self.process) + ret = kill_server_wrapper("https_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from requests import get, post + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password - get('https://{}:{}'.format(_ip, _port), verify=False) - post('https://{}:{}'.format(_ip, _port), data={'username': (None, _username), 'password': (None, _password)}, verify=False) + get(f"https://{_ip}:{_port}", verify=False) + post( + f"https://{_ip}:{_port}", + data={"username": (None, _username), "password": (None, _password)}, + verify=False, + ) -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qhttpsserver = QHTTPSServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qhttpsserver = QHTTPSServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qhttpsserver.run_server() diff --git a/honeypots/imap_server.py b/honeypots/imap_server.py index 4593fcb..61cb5b5 100644 --- a/honeypots/imap_server.py +++ b/honeypots/imap_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.mail.imap4 import IMAP4Server from twisted.internet.protocol import Factory @@ -20,35 +21,56 @@ from twisted import cred from subprocess import Popen from os import path, getenv -from honeypots.helper import check_if_server_is_running, close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, set_local_vars, setup_logger +from honeypots.helper import ( + check_if_server_is_running, + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + set_local_vars, + setup_logger, +) from uuid import uuid4 from contextlib import suppress -class QIMAPServer(): +class QIMAPServer: def __init__(self, **kwargs): self.auto_disabled = None - self.mocking_server = choice([b'OK Microsoft Exchange Server 2003 IMAP4rev1 server version 6.5.6944.0 DC9 ready']) + self.mocking_server = choice( + [b"OK Microsoft Exchange Server 2003 IMAP4rev1 server version 6.5.6944.0 DC9 ready"] + ) self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 143 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 143 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) def imap_server_main(self): - _q_s = self class CustomIMAP4Server(IMAP4Server): - def check_bytes(self, string): if isinstance(string, bytes): return string.decode() @@ -65,47 +87,84 @@ def parse_command(self, line): tag, cmd = args elif len(args) == 1: tag = args[0] - self.sendBadResponse(tag, 'Missing command') + self.sendBadResponse(tag, "Missing command") return None else: - self.sendBadResponse(None, 'Null command') + self.sendBadResponse(None, "Null command") return None cmd = cmd.upper() with suppress(Exception): if "capture_commands" in _q_s.options: - _q_s.logs.info({'server': 'imap_server', 'action': 'command', 'data': {"cmd": self.check_bytes(cmd), "tag": self.check_bytes(tag), "data": self.check_bytes(rest)}, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "imap_server", + "action": "command", + "data": { + "cmd": self.check_bytes(cmd), + "tag": self.check_bytes(tag), + "data": self.check_bytes(rest), + }, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) try: return self.dispatchCommand(tag, cmd, rest) except IllegalClientResponse as e: - self.sendBadResponse(tag, 'Illegal syntax: ' + str(e)) + self.sendBadResponse(tag, "Illegal syntax: " + str(e)) except IllegalOperation as e: - self.sendNegativeResponse(tag, 'Illegal operation: ' + str(e)) + self.sendNegativeResponse(tag, "Illegal operation: " + str(e)) except IllegalMailboxEncoding as e: - self.sendNegativeResponse(tag, 'Illegal mailbox name: ' + str(e)) + self.sendNegativeResponse(tag, "Illegal mailbox name: " + str(e)) def connectionMade(self): - _q_s.logs.info({'server': 'imap_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "imap_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) self.sendPositiveResponse(message=_q_s.mocking_server) def authenticateLogin(self, user, passwd): username = self.check_bytes(user) password = self.check_bytes(passwd) - status = 'failed' + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'imap_server', 'action': 'login', 'status': status, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + status = "success" + _q_s.logs.info( + { + "server": "imap_server", + "action": "login", + "status": status, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) raise cred.error.UnauthorizedLogin() def lineReceived(self, line): try: - _line = line.split(b' ')[1] - if _line.lower().startswith(b'login') or _line.lower().startswith(b'capability'): + _line = line.split(b" ")[1] + if _line.lower().startswith(b"login") or _line.lower().startswith( + b"capability" + ): IMAP4Server.lineReceived(self, line) except BaseException: pass @@ -125,7 +184,7 @@ def buildProtocol(self, address): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -137,13 +196,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' + status = "success" - self.logs.info({'server': 'imap_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) + self.logs.info( + { + "server": "imap_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) - if status == 'success': + if status == "success": return True else: self.kill_server() @@ -152,16 +243,17 @@ def run_server(self, process=False, auto=False): self.imap_server_main() def close_port(self): - ret = close_port_wrapper('imap_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("imap_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('imap_server', self.uuid, self.process) + ret = kill_server_wrapper("imap_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from imaplib import IMAP4 + _ip = ip or self.ip _port = port or self.port _username = username or self.username @@ -171,8 +263,15 @@ def test_server(self, ip=None, port=None, username=None, password=None): imap_test.login(_username, _password) -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qimapserver = QIMAPServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qimapserver = QIMAPServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qimapserver.run_server() diff --git a/honeypots/ipp_server.py b/honeypots/ipp_server.py index 0edff8b..97d0ea5 100644 --- a/honeypots/ipp_server.py +++ b/honeypots/ipp_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from typing import Dict from requests.packages.urllib3 import disable_warnings @@ -21,7 +22,16 @@ from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress from struct import unpack @@ -32,20 +42,29 @@ STATUS_CODE_BAD_REQUEST = b"\x04\x00" -class QIPPServer(): +class QIPPServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 631 - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 631 + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def ipp_server_main(self): @@ -53,25 +72,221 @@ def ipp_server_main(self): class MainResource(Resource): isLeaf = True - operations_supported = {0x0001: 'Reserved', 0x0002: 'Print-Job', 0x0003: 'Print-URI', 0x0004: 'Validate-Job', 0x0005: 'Create-Job', 0x0006: 'Send-Document', 0x0007: 'Send-URI', 0x0008: 'Cancel-Job', 0x0009: 'Get-Job-Attributes', 0x000A: 'Get-Jobs', 0x000B: 'Get-Printer-Attributes', 0x000C: 'Hold-Job', 0x000D: 'Release-Job', 0x000E: 'Restart-Job', 0x000F: 'Reserved', 0x0010: 'Pause-Printer', 0x0011: 'Resume-Printer', 0x0012: 'Purge-Jobs', 0x0013: 'Set-Printer-Attributes', 0x0014: 'Set-Job-Attributes', 0x0015: 'Get-Printer-Supported-Values', 0x0016: 'Create-Printer-Subscriptions', 0x0017: 'Create-Job-Subscriptions', 0x0018: 'Get-Subscription-Attributes', 0x0019: 'Get-Subscriptions', 0x001A: 'Renew-Subscription', 0x001B: 'Cancel-Subscription', 0x001C: 'Get-Notifications', 0x001D: 'ipp-indp-method', 0x001E: 'Get-Resource-Attributes', 0x001F: 'ipp-get-resources', 0x0020: 'Get-Resources', 0x0021: 'ipp-install', 0x0022: 'Enable-Printer', 0x0023: 'Disable-Printer', 0x0024: 'Pause-Printer-After-Current-Job', 0x0025: 'Hold-New-Jobs', 0x0026: 'Release-Held-New-Jobs', 0x0027: 'Deactivate-Printer', 0x0028: 'Activate-Printer', 0x0029: 'Restart-Printer', 0x002A: 'Shutdown-Printer', 0x002B: 'Startup-Printer', 0x002C: 'Reprocess-Job', 0x002D: 'Cancel-Current-Job', 0x002E: 'Suspend-Current-Job', 0x002F: 'Resume-Job', 0x0030: 'Promote-Job', 0x0031: 'Schedule-Job-After', 0x0033: 'Cancel-Document', 0x0034: 'Get-Document-Attributes', 0x0035: 'Get-Documents', 0x0036: 'Delete-Document', 0x0037: 'Set-Document-Attributes', 0x0038: 'Cancel-Jobs', 0x0039: 'Cancel-My-Jobs', 0x003A: 'Resubmit-Job', 0x003B: 'Close-Job', 0x003C: 'Identify-Printer', 0x003D: 'Validate-Document', 0x003E: 'Add-Document-Images', 0x003F: 'Acknowledge-Document', 0x0040: 'Acknowledge-Identify-Printer', 0x0041: 'Acknowledge-Job', 0x0042: 'Fetch-Document', 0x0043: 'Fetch-Job', 0x0044: 'Get-Output-Device-Attributes', 0x0045: 'Update-Active-Jobs', 0x0046: 'Deregister-Output-Device', 0x0047: 'Update-Document-Status', 0x0048: 'Update-Job-Status', 0x0049: 'Update-Output-Device-Attributes', 0x004A: 'Get-Next-Document-Data', 0x004B: 'Allocate-Printer-Resources', 0x004C: 'Create-Printer', 0x004D: 'Deallocate-Printer-Resources', 0x004E: 'Delete-Printer', 0x004F: 'Get-Printers', 0x0050: 'Shutdown-One-Printer', 0x0051: 'Startup-One-Printer', 0x0052: 'Cancel-Resource', 0x0053: 'Create-Resource', 0x0054: 'Install-Resource', 0x0055: 'Send-Resource-Data', 0x0056: 'Set-Resource-Attributes', 0x0057: 'Create-Resource-Subscriptions', 0x0058: 'Create-System-Subscriptions', 0x0059: 'Disable-All-Printers', 0x005A: 'Enable-All-Printers', 0x005B: 'Get-System-Attributes', 0x005C: 'Get-System-Supported-Values', 0x005D: 'Pause-All-Printers', 0x005E: 'Pause-All-Printers-After-Current-Job', 0x005F: 'Register-Output-Device', 0x0060: 'Restart-System', 0x0061: 'Resume-All-Printers', 0x0062: 'Set-System-Attributes', 0x0063: 'Shutdown-All-Printers', 0x0064: 'Startup-All-Printers', 0x0065: 'Get-Printer-Resources', 0x0066: 'Get-User-Printer-Attributes', 0x0067: 'Restart-One-Printer'} - - attribute_group_tags = {0x00: 'Reserved', 0x01: 'operation-attributes-tag', 0x02: 'job-attributes-tag', 0x03: 'end-of-attributes-tag', 0x04: 'printer-attributes-tag', 0x05: 'unsupported-attributes-tag', 0x06: 'subscription-attributes-tag', 0x07: 'event-notification-attributes-tag', 0x08: 'resource-attributes-tag', 0x09: 'document-attributes-tag', 0x0A: 'system-attributes-tag'} - - attribute_syntaxes = {0x20: 'Unassigned', 0x21: 'integer', 0x22: 'boolean', 0x23: 'enum', 0x30: 'octetString', 0x31: 'dateTime', 0x32: 'resolution', 0x33: 'rangeOfInteger', 0x34: 'begCollection', 0x35: 'textWithLanguage', 0x36: 'nameWithLanguage', 0x37: 'endCollection', 0x40: 'Unassigned', 0x41: 'textWithoutLanguage', 0x42: 'nameWithoutLanguage', 0x43: 'Unassigned', 0x44: 'keyword', 0x45: 'uri', 0x46: 'uriScheme', 0x47: 'charset', 0x48: 'naturalLanguage', 0x49: 'mimeMediaType', 0x4A: 'memberAttrName', 0x7F: 'extension'} - - status_codes = {0x0000: 'successful-ok', 0x0001: 'successful-ok-ignored-or-substituted-attributes', 0x0002: 'successful-ok-conflicting-attributes', 0x0003: 'successful-ok-ignored-subscriptions', 0x0004: 'ipp-indp-method', 0x0005: 'successful-ok-too-many-events', 0x0006: 'ipp-indp-method', 0x0007: 'successful-ok-events-complete', 0x0300: 'ipp-get-method', 0x0400: 'client-error-bad-request', 0x0401: 'client-error-forbidden', 0x0402: 'client-error-not-authenticated', 0x0403: 'client-error-not-authorized', 0x0404: 'client-error-not-possible', 0x0405: 'client-error-timeout', 0x0406: 'client-error-not-found', 0x0407: 'client-error-gone', 0x0408: 'client-error-request-entity-too-large', 0x0409: 'client-error-request-value-too-long', 0x040A: 'client-error-document-format-not-supported', 0x040B: 'client-error-attributes-or-values-not-supported', 0x040C: 'client-error-uri-scheme-not-supported', 0x040D: 'client-error-charset-not-supported', 0x040E: 'client-error-conflicting-attributes', 0x040F: 'client-error-compression-not-supported', 0x0410: 'client-error-compression-error', 0x0411: 'client-error-document-format-error', 0x0412: 'client-error-document-access-error', 0x0413: 'client-error-attributes-not-settable', 0x0414: 'client-error-ignored-all-subscriptions', 0x0415: 'client-error-too-many-subscriptions', 0x0416: 'ipp-indp-method', 0x0417: 'ipp-install', 0x0418: 'client-error-document-password-error', 0x0419: 'client-error-document-permission-error', 0x041A: 'client-error-document-security-error', 0x041B: 'client-error-document-unprintable-error', 0x041C: 'client-error-account-info-needed', 0x041D: 'client-error-account-closed', 0x041E: 'client-error-account-limit-reached', 0x041F: 'client-error-account-authorization-failed', 0x0420: 'client-error-not-fetchable', 0x0500: 'server-error-internal-error', 0x0501: 'server-error-operation-not-supported', 0x0502: 'server-error-service-unavailable', 0x0503: 'server-error-version-not-supported', 0x0504: 'server-error-device-error', 0x0505: 'server-error-temporary-error', 0x0506: 'server-error-not-accepting-jobs', 0x0507: 'server-error-busy', 0x0508: 'server-error-job-canceled', 0x0509: 'server-error-multiple-document-jobs-not-supported', 0x050A: 'server-error-printer-is-deactivated', 0x050B: 'server-error-too-many-jobs', 0x050C: 'server-error-too-many-documents'} + operations_supported = { + 0x0001: "Reserved", + 0x0002: "Print-Job", + 0x0003: "Print-URI", + 0x0004: "Validate-Job", + 0x0005: "Create-Job", + 0x0006: "Send-Document", + 0x0007: "Send-URI", + 0x0008: "Cancel-Job", + 0x0009: "Get-Job-Attributes", + 0x000A: "Get-Jobs", + 0x000B: "Get-Printer-Attributes", + 0x000C: "Hold-Job", + 0x000D: "Release-Job", + 0x000E: "Restart-Job", + 0x000F: "Reserved", + 0x0010: "Pause-Printer", + 0x0011: "Resume-Printer", + 0x0012: "Purge-Jobs", + 0x0013: "Set-Printer-Attributes", + 0x0014: "Set-Job-Attributes", + 0x0015: "Get-Printer-Supported-Values", + 0x0016: "Create-Printer-Subscriptions", + 0x0017: "Create-Job-Subscriptions", + 0x0018: "Get-Subscription-Attributes", + 0x0019: "Get-Subscriptions", + 0x001A: "Renew-Subscription", + 0x001B: "Cancel-Subscription", + 0x001C: "Get-Notifications", + 0x001D: "ipp-indp-method", + 0x001E: "Get-Resource-Attributes", + 0x001F: "ipp-get-resources", + 0x0020: "Get-Resources", + 0x0021: "ipp-install", + 0x0022: "Enable-Printer", + 0x0023: "Disable-Printer", + 0x0024: "Pause-Printer-After-Current-Job", + 0x0025: "Hold-New-Jobs", + 0x0026: "Release-Held-New-Jobs", + 0x0027: "Deactivate-Printer", + 0x0028: "Activate-Printer", + 0x0029: "Restart-Printer", + 0x002A: "Shutdown-Printer", + 0x002B: "Startup-Printer", + 0x002C: "Reprocess-Job", + 0x002D: "Cancel-Current-Job", + 0x002E: "Suspend-Current-Job", + 0x002F: "Resume-Job", + 0x0030: "Promote-Job", + 0x0031: "Schedule-Job-After", + 0x0033: "Cancel-Document", + 0x0034: "Get-Document-Attributes", + 0x0035: "Get-Documents", + 0x0036: "Delete-Document", + 0x0037: "Set-Document-Attributes", + 0x0038: "Cancel-Jobs", + 0x0039: "Cancel-My-Jobs", + 0x003A: "Resubmit-Job", + 0x003B: "Close-Job", + 0x003C: "Identify-Printer", + 0x003D: "Validate-Document", + 0x003E: "Add-Document-Images", + 0x003F: "Acknowledge-Document", + 0x0040: "Acknowledge-Identify-Printer", + 0x0041: "Acknowledge-Job", + 0x0042: "Fetch-Document", + 0x0043: "Fetch-Job", + 0x0044: "Get-Output-Device-Attributes", + 0x0045: "Update-Active-Jobs", + 0x0046: "Deregister-Output-Device", + 0x0047: "Update-Document-Status", + 0x0048: "Update-Job-Status", + 0x0049: "Update-Output-Device-Attributes", + 0x004A: "Get-Next-Document-Data", + 0x004B: "Allocate-Printer-Resources", + 0x004C: "Create-Printer", + 0x004D: "Deallocate-Printer-Resources", + 0x004E: "Delete-Printer", + 0x004F: "Get-Printers", + 0x0050: "Shutdown-One-Printer", + 0x0051: "Startup-One-Printer", + 0x0052: "Cancel-Resource", + 0x0053: "Create-Resource", + 0x0054: "Install-Resource", + 0x0055: "Send-Resource-Data", + 0x0056: "Set-Resource-Attributes", + 0x0057: "Create-Resource-Subscriptions", + 0x0058: "Create-System-Subscriptions", + 0x0059: "Disable-All-Printers", + 0x005A: "Enable-All-Printers", + 0x005B: "Get-System-Attributes", + 0x005C: "Get-System-Supported-Values", + 0x005D: "Pause-All-Printers", + 0x005E: "Pause-All-Printers-After-Current-Job", + 0x005F: "Register-Output-Device", + 0x0060: "Restart-System", + 0x0061: "Resume-All-Printers", + 0x0062: "Set-System-Attributes", + 0x0063: "Shutdown-All-Printers", + 0x0064: "Startup-All-Printers", + 0x0065: "Get-Printer-Resources", + 0x0066: "Get-User-Printer-Attributes", + 0x0067: "Restart-One-Printer", + } + + attribute_group_tags = { + 0x00: "Reserved", + 0x01: "operation-attributes-tag", + 0x02: "job-attributes-tag", + 0x03: "end-of-attributes-tag", + 0x04: "printer-attributes-tag", + 0x05: "unsupported-attributes-tag", + 0x06: "subscription-attributes-tag", + 0x07: "event-notification-attributes-tag", + 0x08: "resource-attributes-tag", + 0x09: "document-attributes-tag", + 0x0A: "system-attributes-tag", + } + + attribute_syntaxes = { + 0x20: "Unassigned", + 0x21: "integer", + 0x22: "boolean", + 0x23: "enum", + 0x30: "octetString", + 0x31: "dateTime", + 0x32: "resolution", + 0x33: "rangeOfInteger", + 0x34: "begCollection", + 0x35: "textWithLanguage", + 0x36: "nameWithLanguage", + 0x37: "endCollection", + 0x40: "Unassigned", + 0x41: "textWithoutLanguage", + 0x42: "nameWithoutLanguage", + 0x43: "Unassigned", + 0x44: "keyword", + 0x45: "uri", + 0x46: "uriScheme", + 0x47: "charset", + 0x48: "naturalLanguage", + 0x49: "mimeMediaType", + 0x4A: "memberAttrName", + 0x7F: "extension", + } + + status_codes = { + 0x0000: "successful-ok", + 0x0001: "successful-ok-ignored-or-substituted-attributes", + 0x0002: "successful-ok-conflicting-attributes", + 0x0003: "successful-ok-ignored-subscriptions", + 0x0004: "ipp-indp-method", + 0x0005: "successful-ok-too-many-events", + 0x0006: "ipp-indp-method", + 0x0007: "successful-ok-events-complete", + 0x0300: "ipp-get-method", + 0x0400: "client-error-bad-request", + 0x0401: "client-error-forbidden", + 0x0402: "client-error-not-authenticated", + 0x0403: "client-error-not-authorized", + 0x0404: "client-error-not-possible", + 0x0405: "client-error-timeout", + 0x0406: "client-error-not-found", + 0x0407: "client-error-gone", + 0x0408: "client-error-request-entity-too-large", + 0x0409: "client-error-request-value-too-long", + 0x040A: "client-error-document-format-not-supported", + 0x040B: "client-error-attributes-or-values-not-supported", + 0x040C: "client-error-uri-scheme-not-supported", + 0x040D: "client-error-charset-not-supported", + 0x040E: "client-error-conflicting-attributes", + 0x040F: "client-error-compression-not-supported", + 0x0410: "client-error-compression-error", + 0x0411: "client-error-document-format-error", + 0x0412: "client-error-document-access-error", + 0x0413: "client-error-attributes-not-settable", + 0x0414: "client-error-ignored-all-subscriptions", + 0x0415: "client-error-too-many-subscriptions", + 0x0416: "ipp-indp-method", + 0x0417: "ipp-install", + 0x0418: "client-error-document-password-error", + 0x0419: "client-error-document-permission-error", + 0x041A: "client-error-document-security-error", + 0x041B: "client-error-document-unprintable-error", + 0x041C: "client-error-account-info-needed", + 0x041D: "client-error-account-closed", + 0x041E: "client-error-account-limit-reached", + 0x041F: "client-error-account-authorization-failed", + 0x0420: "client-error-not-fetchable", + 0x0500: "server-error-internal-error", + 0x0501: "server-error-operation-not-supported", + 0x0502: "server-error-service-unavailable", + 0x0503: "server-error-version-not-supported", + 0x0504: "server-error-device-error", + 0x0505: "server-error-temporary-error", + 0x0506: "server-error-not-accepting-jobs", + 0x0507: "server-error-busy", + 0x0508: "server-error-job-canceled", + 0x0509: "server-error-multiple-document-jobs-not-supported", + 0x050A: "server-error-printer-is-deactivated", + 0x050B: "server-error-too-many-jobs", + 0x050C: "server-error-too-many-documents", + } def get_uint8_t(self, index, data): - return index + 1, unpack('b', data[index:index + 1])[0] + return index + 1, unpack("b", data[index : index + 1])[0] def get_uint16_t(self, index, data): - return index + 2, unpack('>H', data[index:index + 2])[0] + return index + 2, unpack(">H", data[index : index + 2])[0] def get_uint32_t(self, index, data): - return index + 4, unpack('>I', data[index:index + 4])[0] + return index + 4, unpack(">I", data[index : index + 4])[0] def get_string(self, index, length, data): - return index + length, data[index:index + length] + return index + length, data[index : index + length] def check_bytes(self, string): if isinstance(string, bytes): @@ -80,11 +295,11 @@ def check_bytes(self, string): return str(string) def render_POST(self, request): - headers = {} client_ip = "" with suppress(Exception): + def check_bytes(string): if isinstance(string, bytes): return string.decode() @@ -92,37 +307,56 @@ def check_bytes(string): return str(string) for item, value in dict(request.requestHeaders.getAllRawHeaders()).items(): - headers.update({check_bytes(item): ','.join(map(check_bytes, value))}) - headers.update({'method': check_bytes(request.method)}) - headers.update({'uri': check_bytes(request.uri)}) + headers.update({check_bytes(item): ",".join(map(check_bytes, value))}) + headers.update({"method": check_bytes(request.method)}) + headers.update({"uri": check_bytes(request.uri)}) - if 'fix_get_client_ip' in _q_s.options: + if "fix_get_client_ip" in _q_s.options: with suppress(Exception): raw_headers = dict(request.requestHeaders.getAllRawHeaders()) - if b'X-Forwarded-For' in raw_headers: - client_ip = check_bytes(raw_headers[b'X-Forwarded-For'][0]) - elif b'X-Real-IP' in raw_headers: - client_ip = check_bytes(raw_headers[b'X-Real-IP'][0]) + if b"X-Forwarded-For" in raw_headers: + client_ip = check_bytes(raw_headers[b"X-Forwarded-For"][0]) + elif b"X-Real-IP" in raw_headers: + client_ip = check_bytes(raw_headers[b"X-Real-IP"][0]) if client_ip == "": client_ip = request.getClientAddress().host with suppress(Exception): if "capture_commands" in _q_s.options: - _q_s.logs.info({'server': 'ipp_server', 'action': 'connection', 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': headers}) + _q_s.logs.info( + { + "server": "ipp_server", + "action": "connection", + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": headers, + } + ) else: - _q_s.logs.info({'server': 'ipp_server', 'action': 'connection', 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "ipp_server", + "action": "connection", + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) data = request.content.read() - response = '' + response = "" version = [0, 0] request_id = 0 - group = '' + group = "" groups = [] - groups_parsed = '' - operation = '' - status = 'success' + groups_parsed = "" + operation = "" + status = "success" with suppress(Exception): index, version[0] = self.get_uint8_t(0, data) @@ -137,45 +371,58 @@ def check_bytes(string): if uint8_t in self.attribute_syntaxes: while index < to_parse_len: try: - attribute = '' - value = '' - if self.attribute_syntaxes[uint8_t] == 'integer': + attribute = "" + value = "" + if self.attribute_syntaxes[uint8_t] == "integer": index, attribute = self.get_uint32_t(index, data) - elif self.attribute_syntaxes[uint8_t] == 'boolean': + elif self.attribute_syntaxes[uint8_t] == "boolean": index, attribute = self.get_uint8_t(index, data) else: index, uint16_t = self.get_uint16_t(index, data) index, attribute = self.get_string(index, uint16_t, data) index, uint16_t = self.get_uint16_t(index, data) index, value = self.get_string(index, uint16_t, data) - if attribute == b'': + if attribute == b"": groups[-1][1].append(self.check_bytes(value)) else: - groups.append([self.check_bytes(attribute), [self.check_bytes(value)]]) + groups.append( + [self.check_bytes(attribute), [self.check_bytes(value)]] + ) index, uint8_t = self.get_uint8_t(index, data) if uint8_t in self.attribute_group_tags: break except BaseException: - status = 'failed' + status = "failed" break with suppress(Exception): - response += '' - response = 'VERSION {}.{}|'.format(version[0], version[1]) - response += 'REQUEST {}|'.format(hex(request_id)) - response += 'OPERATION {}|'.format(operation) - response += 'GROUP {}|'.format(group) + response += "" + response = f"VERSION {version[0]}.{version[1]}|" + response += f"REQUEST {hex(request_id)}|" + response += f"OPERATION {operation}|" + response += f"GROUP {group}|" if len(groups) > 0: for i in groups: - groups_parsed += 'ATTR ' + i[0] + ' ' + ','.join(i[1]) + '|' + groups_parsed += "ATTR " + i[0] + " " + ",".join(i[1]) + "|" groups_parsed = groups_parsed.strip() response += groups_parsed with suppress(Exception): - if response[-1] == '|': + if response[-1] == "|": response = response[0:-1] if len(response) > 0: - _q_s.logs.info({'server': 'ipp_server', 'action': 'query', 'status': status, 'src_ip': client_ip, 'src_port': request.getClientAddress().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': {'request': response}}) + _q_s.logs.info( + { + "server": "ipp_server", + "action": "query", + "status": status, + "src_ip": client_ip, + "src_port": request.getClientAddress().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": {"request": response}, + } + ) return self.send_response(data, status != "failed") @staticmethod @@ -184,7 +431,9 @@ def send_response(request: bytes, successful: bool) -> bytes: if version not in [b"\x01\x01", b"\x02\x00", b"\x02\x01", b"\x02\x02"]: version = b"\x02\x00" status_code = STATUS_CODE_OK if successful else STATUS_CODE_BAD_REQUEST - attributes = attributes_dict_to_bytes({"attributes-charset": "utf-8", "attributes-natural-language": "en-us"}) + attributes = attributes_dict_to_bytes( + {"attributes-charset": "utf-8", "attributes-natural-language": "en-us"} + ) response = version + status_code + request_id + attributes return response @@ -192,7 +441,7 @@ def send_response(request: bytes, successful: bool) -> bytes: reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -204,13 +453,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'ipp_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "ipp_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -219,28 +494,29 @@ def run_server(self, process=False, auto=False): self.ipp_server_main() def close_port(self): - ret = close_port_wrapper('ipp_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("ipp_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('ipp_server', self.uuid, self.process) + ret = kill_server_wrapper("ipp_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None): with suppress(): from socket import socket, AF_INET, SOCK_STREAM + _ip = ip or self.ip _port = port or self.port - body = b'\x02\x00\x00\x0b\x00\x01/p\x01G\x00\x12attributes-charset\x00\x05utf-8H\x00\x1battributes-natural-language\x00\x02enE\x00\x0bprinter-uri\x00\x15ipp://127.0.0.1:631/D\x00\x14requested-attributes\x00\x03allD\x00\x00\x00\x12media-col-database\x03' + body = b"\x02\x00\x00\x0b\x00\x01/p\x01G\x00\x12attributes-charset\x00\x05utf-8H\x00\x1battributes-natural-language\x00\x02enE\x00\x0bprinter-uri\x00\x15ipp://127.0.0.1:631/D\x00\x14requested-attributes\x00\x03allD\x00\x00\x00\x12media-col-database\x03" - headers = """\ + headers = f"""\ POST / HTTP/1.1\r Content-Type: application/x-www-form-urlencoded\r - Content-Length: {}\r - Host: {}:{}\r + Content-Length: {len(body)}\r + Host: {_ip}:{_port}\r Connection: close\r - \r\n""".format(len(body), _ip, _port).encode() + \r\n""".encode() s = socket(AF_INET, SOCK_STREAM) s.connect((_ip, _port)) @@ -264,8 +540,10 @@ def attributes_dict_to_bytes(attributes: Dict[str, str]) -> bytes: return attributes_str -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qippserver = QIPPServer(ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config) + qippserver = QIPPServer( + ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config + ) qippserver.run_server() diff --git a/honeypots/irc_server.py b/honeypots/irc_server.py index 2dd0fa5..ed0671d 100644 --- a/honeypots/irc_server.py +++ b/honeypots/irc_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,52 +8,81 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') -filterwarnings(action='ignore', module='.*socket.*') -from twisted.internet.protocol import Protocol, Factory +filterwarnings(action="ignore", module=".*OpenSSL.*") +filterwarnings(action="ignore", module=".*socket.*") + +from twisted.internet.protocol import Factory from twisted.internet import reactor from twisted.words import service -from time import time from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QIRCServer(): +class QIRCServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 6667 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 6667 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def irc_server_main(self): _q_s = self class CustomIRCProtocol(service.IRCUser): - def connectionMade(self): - _q_s.logs.info({'server': 'irc_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "irc_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def handleCommand(self, command, prefix, params): - def check_bytes(string): if isinstance(string, bytes): return string.decode() @@ -62,18 +91,31 @@ def check_bytes(string): with suppress(Exception): if "capture_commands" in _q_s.options: - _q_s.logs.info({'server': 'irc_server', 'action': 'command', 'data': {"command": check_bytes(command), "prefix": check_bytes(prefix), "params": check_bytes(params)}, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "irc_server", + "action": "command", + "data": { + "command": check_bytes(command), + "prefix": check_bytes(prefix), + "params": check_bytes(params), + }, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) service.IRCUser.handleCommand(self, command, prefix, params) def dataReceived(self, data): - #_q_s.logs.info({'server': 'irc_server', 'action': 'command', 'data': check_bytes(data), 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + # _q_s.logs.info({'server': 'irc_server', 'action': 'command', 'data': check_bytes(data), 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) service.IRCUser.dataReceived(self, data) def irc_unknown(self, prefix, command, params): pass def irc_NICK(self, prefix, params): - def check_bytes(string): if isinstance(string, bytes): return string.decode() @@ -81,12 +123,24 @@ def check_bytes(string): return str(string) status = False - username = check_bytes(''.join(params)) + username = check_bytes("".join(params)) password = check_bytes(self.password) if password == check_bytes(_q_s.password): if username == _q_s.username: status = True - _q_s.logs.info({'server': 'irc_server', 'action': 'login', 'status': status, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'username': username, 'password': password, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "irc_server", + "action": "login", + "status": status, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "username": username, + "password": password, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) factory = Factory() factory.protocol = CustomIRCProtocol @@ -94,7 +148,7 @@ def check_bytes(string): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -106,13 +160,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'irc_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "irc_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -121,19 +201,19 @@ def run_server(self, process=False, auto=False): self.irc_server_main() def close_port(self): - ret = close_port_wrapper('irc_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("irc_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('irc_server', self.uuid, self.process) + ret = kill_server_wrapper("irc_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from warnings import filterwarnings - filterwarnings(action='ignore', module='.*socket.*') + + filterwarnings(action="ignore", module=".*socket.*") from socket import socket, AF_INET, SOCK_STREAM - from time import sleep _ip = ip or self.ip _port = port or self.port @@ -142,12 +222,19 @@ def test_server(self, ip=None, port=None, username=None, password=None): c = socket(AF_INET, SOCK_STREAM) c.connect((_ip, _port)) c.setblocking(False) - c.send("PASS {}\n".format(_password).encode()) + c.send(f"PASS {_password}\n".encode()) c.close() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - QIRCServer = QIRCServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + QIRCServer = QIRCServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) QIRCServer.run_server() diff --git a/honeypots/ldap_server.py b/honeypots/ldap_server.py index ca0b0f3..49a12bf 100644 --- a/honeypots/ldap_server.py +++ b/honeypots/ldap_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor @@ -20,34 +21,55 @@ from os import path, getenv from struct import unpack from binascii import unhexlify -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QLDAPServer(): +class QLDAPServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 389 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 389 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def ldap_server_main(self): _q_s = self class CustomLDAProtocol(Protocol): - _state = None def check_bytes(self, string): @@ -58,33 +80,51 @@ def check_bytes(self, string): def connectionMade(self): self._state = 1 - _q_s.logs.info({'server': 'ldap_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "ldap_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def parse_ldap_packet(self, data): - # V # 30[20] 0201[02] 60[1b] 0201[03] 04[0a] 7379736261636b757031 [80][0a] 7379736261636b757032 - username = '' - password = '' + username = "" + password = "" username_start = 0 username_end = 0 password_start = 0 password_end = 0 with suppress(Exception): - version = data.find(b'\x02\x01\x03') + version = data.find(b"\x02\x01\x03") if version > 0: username_start = version + 5 - username_end = unpack('b', data[version + 4:username_start])[0] + username_start + username_end = ( + unpack("b", data[version + 4 : username_start])[0] + username_start + ) username = data[username_start:username_end] auth_type = data[username_end] if auth_type == 0x80: if data[username_end + 1] == 0x82: password_start = username_end + 4 - password_end = unpack('>H', data[username_end + 2:username_end + 4])[0] + username_end + 4 + password_end = ( + unpack(">H", data[username_end + 2 : username_end + 4])[0] + + username_end + + 4 + ) else: password_start = username_end + 2 - password_end = unpack('b', data[username_end + 2:username_end + 3])[0] + username_start + 2 + password_end = ( + unpack("b", data[username_end + 2 : username_end + 3])[0] + + username_start + + 2 + ) password = data[password_start:password_end] return username, password @@ -95,23 +135,71 @@ def dataReceived(self, data): username, password = self.parse_ldap_packet(data) username = self.check_bytes(username) password = self.check_bytes(password) - if username != '' or password != '': + if username != "" or password != "": if username == _q_s.username and password == _q_s.password: - _q_s.logs.info({'server': 'ldap_server', 'action': 'login', 'status': 'success', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': _q_s.username, 'password': _q_s.password}) + _q_s.logs.info( + { + "server": "ldap_server", + "action": "login", + "status": "success", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": _q_s.username, + "password": _q_s.password, + } + ) else: - _q_s.logs.info({'server': 'ldap_server', 'action': 'login', 'status': 'failed', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) - self.transport.write(unhexlify(b'300c02010165070a013204000400')) + _q_s.logs.info( + { + "server": "ldap_server", + "action": "login", + "status": "failed", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) + self.transport.write(unhexlify(b"300c02010165070a013204000400")) elif self._state == 2: self._state = 3 username, password = self.parse_ldap_packet(data) username = self.check_bytes(username) password = self.check_bytes(password) - if username != '' or password != '': + if username != "" or password != "": if username == _q_s.username and password == _q_s.password: - _q_s.logs.info({'server': 'ldap_server', 'action': 'login', 'status': 'success', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': _q_s.username, 'password': _q_s.password}) + _q_s.logs.info( + { + "server": "ldap_server", + "action": "login", + "status": "success", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": _q_s.username, + "password": _q_s.password, + } + ) else: - _q_s.logs.info({'server': 'ldap_server', 'action': 'login', 'status': 'failed', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) - self.transport.write(unhexlify(b'300c02010265070a013204000400')) + _q_s.logs.info( + { + "server": "ldap_server", + "action": "login", + "status": "failed", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) + self.transport.write(unhexlify(b"300c02010265070a013204000400")) else: self.transport.loseConnection() @@ -124,7 +212,7 @@ def connectionLost(self, reason): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -136,13 +224,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' + status = "success" - self.logs.info({'server': 'ldap_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) + self.logs.info( + { + "server": "ldap_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) - if status == 'success': + if status == "success": return True else: self.kill_server() @@ -151,27 +271,44 @@ def run_server(self, process=False, auto=False): self.ldap_server_main() def close_port(self): - ret = close_port_wrapper('ldap_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("ldap_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('ldap_server', self.uuid, self.process) + ret = kill_server_wrapper("ldap_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from ldap3 import Server, Connection, ALL + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password - c = Connection(Server(_ip, port=_port, get_info=ALL), authentication='SIMPLE', user=_username, password=_password, check_names=True, lazy=False, client_strategy='SYNC', raise_exceptions=True) + c = Connection( + Server(_ip, port=_port, get_info=ALL), + authentication="SIMPLE", + user=_username, + password=_password, + check_names=True, + lazy=False, + client_strategy="SYNC", + raise_exceptions=True, + ) c.open() c.bind() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - QLDAPServer = QLDAPServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + QLDAPServer = QLDAPServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) QLDAPServer.run_server() diff --git a/honeypots/memcache_server.py b/honeypots/memcache_server.py index fef771c..196ac57 100644 --- a/honeypots/memcache_server.py +++ b/honeypots/memcache_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor @@ -20,75 +21,190 @@ from os import path, getenv from random import randint, uniform from time import time -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QMemcacheServer(): +class QMemcacheServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 11211 - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 11211 + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def memcache_server_main(self): _q_s = self class CustomRedisProtocol(Protocol): - _state = None def get_stats(self): items = randint(80000000, 90000000) - ret = '' - temp = {b'pid': randint(5, 400), b'uptime': randint(1000, 2000), b'time': int(time()), b'version': b'1.5.6', b'libevent': b'2.1.8-stable', b'pointer_size': 64, b'rusage_user': round(uniform(0.1, 0.9), 4), b'rusage_system': round(uniform(0.1, 0.9), 6), b'max_connections': 1024, b'curr_connections': randint(1, 1024), b'total_connections': 5, b'rejected_connections': 0, b'connection_structures': 2, b'reserved_fds': 20, b'cmd_get': 0, b'cmd_set': 40, b'cmd_flush': 0, b'cmd_touch': 0, b'get_hits': 0, b'get_misses': 0, b'get_expired': 0, b'get_flushed': 0, b'delete_misses': 0, b'delete_hits': 0, b'incr_misses': 0, b'incr_hits': 0, b'decr_misses': 0, b'decr_hits': 0, b'cas_misses': 0, b'cas_hits': 0, b'cas_badval': 0, b'touch_hits': 0, b'touch_misses': 0, b'auth_cmds': 0, b'auth_errors': 0, b'bytes_read': randint(7000000, 8000000), b'bytes_written': randint(500000, 1000000), b'limit_maxbytes': 33554432, b'accepting_conns': 1, b'listen_disabled_num': 0, b'time_in_listen_disabled_us': 0, b'threads': randint(4, 9000), b'conn_yields': 0, b'hash_power_level': 16, b'hash_bytes': 524288, b'hash_is_expanding': False, b'slab_reassign_rescues': 0, b'slab_reassign_chunk_rescues': 0, b'slab_reassign_evictions_nomem': 0, b'slab_reassign_inline_reclaim': 0, b'slab_reassign_busy_items': 0, b'slab_reassign_busy_deletes': 0, b'slab_reassign_running': False, b'slabs_moved': 0, b'lru_crawler_running': 0, b'lru_crawler_starts': randint(500000, 700000), b'lru_maintainer_juggles': randint(400000, 500000), b'malloc_fails': 0, b'log_worker_dropped': 0, b'log_worker_written': 0, b'log_watcher_skipped': 0, b'log_watcher_sent': 0, b'bytes': randint(13554432, 33554432), b'curr_items': items, b'total_items': items, b'slab_global_page_pool': 0, b'expired_unfetched': 0, b'evicted_unfetched': 0, b'evicted_active': 0, b'evictions': 0, b'reclaimed': 0, b'crawler_reclaimed': 0, b'crawler_items_checked': randint(5000, 6000), b'lrutail_reflocked': 0, b'moves_to_cold': randint(5000, 6000), b'moves_to_warm': randint(5000, 6000), b'moves_within_lru': 0, b'direct_reclaims': 0, b'lru_bumps_dropped': 0} + ret = "" + temp = { + b"pid": randint(5, 400), + b"uptime": randint(1000, 2000), + b"time": int(time()), + b"version": b"1.5.6", + b"libevent": b"2.1.8-stable", + b"pointer_size": 64, + b"rusage_user": round(uniform(0.1, 0.9), 4), + b"rusage_system": round(uniform(0.1, 0.9), 6), + b"max_connections": 1024, + b"curr_connections": randint(1, 1024), + b"total_connections": 5, + b"rejected_connections": 0, + b"connection_structures": 2, + b"reserved_fds": 20, + b"cmd_get": 0, + b"cmd_set": 40, + b"cmd_flush": 0, + b"cmd_touch": 0, + b"get_hits": 0, + b"get_misses": 0, + b"get_expired": 0, + b"get_flushed": 0, + b"delete_misses": 0, + b"delete_hits": 0, + b"incr_misses": 0, + b"incr_hits": 0, + b"decr_misses": 0, + b"decr_hits": 0, + b"cas_misses": 0, + b"cas_hits": 0, + b"cas_badval": 0, + b"touch_hits": 0, + b"touch_misses": 0, + b"auth_cmds": 0, + b"auth_errors": 0, + b"bytes_read": randint(7000000, 8000000), + b"bytes_written": randint(500000, 1000000), + b"limit_maxbytes": 33554432, + b"accepting_conns": 1, + b"listen_disabled_num": 0, + b"time_in_listen_disabled_us": 0, + b"threads": randint(4, 9000), + b"conn_yields": 0, + b"hash_power_level": 16, + b"hash_bytes": 524288, + b"hash_is_expanding": False, + b"slab_reassign_rescues": 0, + b"slab_reassign_chunk_rescues": 0, + b"slab_reassign_evictions_nomem": 0, + b"slab_reassign_inline_reclaim": 0, + b"slab_reassign_busy_items": 0, + b"slab_reassign_busy_deletes": 0, + b"slab_reassign_running": False, + b"slabs_moved": 0, + b"lru_crawler_running": 0, + b"lru_crawler_starts": randint(500000, 700000), + b"lru_maintainer_juggles": randint(400000, 500000), + b"malloc_fails": 0, + b"log_worker_dropped": 0, + b"log_worker_written": 0, + b"log_watcher_skipped": 0, + b"log_watcher_sent": 0, + b"bytes": randint(13554432, 33554432), + b"curr_items": items, + b"total_items": items, + b"slab_global_page_pool": 0, + b"expired_unfetched": 0, + b"evicted_unfetched": 0, + b"evicted_active": 0, + b"evictions": 0, + b"reclaimed": 0, + b"crawler_reclaimed": 0, + b"crawler_items_checked": randint(5000, 6000), + b"lrutail_reflocked": 0, + b"moves_to_cold": randint(5000, 6000), + b"moves_to_warm": randint(5000, 6000), + b"moves_within_lru": 0, + b"direct_reclaims": 0, + b"lru_bumps_dropped": 0, + } for key, value in temp.items(): key = key.decode() if isinstance(value, bytes): value = value.decode() - ret += 'STAT {} {}\r\n'.format(key, value) + ret += f"STAT {key} {value}\r\n" - ret = ret.encode() + b'END\r\n' + ret = ret.encode() + b"END\r\n" return ret def get_key(self, key): - ret = b'' + ret = b"" with suppress(Exception): random = randint(80000000, 90000000) - temp = 'VALUE {} 0 {}\r\n{}\r\nEND\r\n'.format(key.decode(), len(str(random)), random) + temp = f"VALUE {key.decode()} 0 {len(str(random))}\r\n{random}\r\nEND\r\n" ret = temp.encode() return ret def connectionMade(self): - _q_s.logs.info({'server': 'memcache_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "memcache_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def dataReceived(self, data): with suppress(Exception): - _data = data.split(b'\r\n')[0].split(b' ') - if _data[0] == b'stats': + _data = data.split(b"\r\n")[0].split(b" ") + if _data[0] == b"stats": self.transport.write(self.get_stats()) - elif _data[0] == b'get': + elif _data[0] == b"get": self.transport.write(self.get_key(_data[1])) - elif _data[0] == b'set': + elif _data[0] == b"set": name = _data[1] size = _data[4] - value = data.split(b'\r\n')[1] - self.transport.write(b'STORED\r\n') + value = data.split(b"\r\n")[1] + self.transport.write(b"STORED\r\n") else: - self.transport.write(b'ERROR\r\n') - if _data[0] != b'': - _q_s.logs.info({'server': 'memcache_server', 'action': _data[0].decode(), 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + self.transport.write(b"ERROR\r\n") + if _data[0] != b"": + _q_s.logs.info( + { + "server": "memcache_server", + "action": _data[0].decode(), + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) self.transport.loseConnection() factory = Factory() @@ -97,7 +213,7 @@ def dataReceived(self, data): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -109,13 +225,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' + status = "success" - self.logs.info({'server': 'memcache_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) + self.logs.info( + { + "server": "memcache_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) - if status == 'success': + if status == "success": return True else: self.kill_server() @@ -124,30 +266,33 @@ def run_server(self, process=False, auto=False): self.memcache_server_main() def close_port(self): - ret = close_port_wrapper('memcache_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("memcache_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('memcache_server', self.uuid, self.process) + ret = kill_server_wrapper("memcache_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from warnings import filterwarnings - filterwarnings(action='ignore', module='.*socket.*') + + filterwarnings(action="ignore", module=".*socket.*") from socket import socket, AF_INET, SOCK_STREAM _ip = ip or self.ip _port = port or self.port c = socket(AF_INET, SOCK_STREAM) c.connect((_ip, _port)) - c.send(b'stats\r\n') + c.send(b"stats\r\n") data, address = c.recvfrom(10000) c.close() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - QMemcacheServer = QMemcacheServer(ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config) + QMemcacheServer = QMemcacheServer( + ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config + ) QMemcacheServer.run_server() diff --git a/honeypots/mssql_server.py b/honeypots/mssql_server.py index 3bc6a14..66185bf 100644 --- a/honeypots/mssql_server.py +++ b/honeypots/mssql_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor @@ -21,35 +22,56 @@ from os import path, getenv from struct import unpack, pack from binascii import unhexlify, hexlify -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QMSSQLServer(): +class QMSSQLServer: def __init__(self, **kwargs): self.auto_disabled = None self.file_name = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 1433 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 1433 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def mssql_server_main(self): _q_s = self class CustomMSSQLProtocol(Protocol): - _state = None def check_bytes(self, string): @@ -58,53 +80,112 @@ def check_bytes(self, string): else: return str(string) - def create_payload(self, server_name=b'', token_error_msg=b'', error_code=2): - ret = '040100c000350100aaa80002000000010e440041006e0020006500720072006f007200200068006100730020006f00630063007500720072006500640020007700680069006c0065002000650073007400610062006c0069007300680069006e00670020006100200063006f006e006e0065006300740069006f006e00200074006f00200074006800650020007300650072007600650072002e00095200260044006200610063006b00750070000001000000fd020000000000000000000000' + def create_payload(self, server_name=b"", token_error_msg=b"", error_code=2): + ret = "040100c000350100aaa80002000000010e440041006e0020006500720072006f007200200068006100730020006f00630063007500720072006500640020007700680069006c0065002000650073007400610062006c0069007300680069006e00670020006100200063006f006e006e0065006300740069006f006e00200074006f00200074006800650020007300650072007600650072002e00095200260044006200610063006b00750070000001000000fd020000000000000000000000" with suppress(Exception): - if server_name == b'': - server_name = b'R&Dbackup' - if token_error_msg == b'': - token_error_msg = b'An error has occurred while establishing a connection to the server.' - server_name_hex = ('00'.join(hex(c)[2:] for c in server_name)).encode('utf-8') + b'00' - server_name_hex_len = hexlify(pack('b', len(server_name))) - token_error_msg_hex = ('00'.join(hex(c)[2:] for c in token_error_msg)).encode('utf-8') + b'00' - token_error_msg_hex_len = hexlify(pack('H', len(unhexlify(data_stream)))) + data_stream[8:] + if server_name == b"": + server_name = b"R&Dbackup" + if token_error_msg == b"": + token_error_msg = ( + b"An error has occurred while establishing a connection to the server." + ) + server_name_hex = ("00".join(hex(c)[2:] for c in server_name)).encode( + "utf-8" + ) + b"00" + server_name_hex_len = hexlify(pack("b", len(server_name))) + token_error_msg_hex = ("00".join(hex(c)[2:] for c in token_error_msg)).encode( + "utf-8" + ) + b"00" + token_error_msg_hex_len = hexlify(pack("H", len(unhexlify(data_stream)))) + + data_stream[8:] + ) return ret def connectionMade(self): self._state = 1 - _q_s.logs.info({'server': 'mssql_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "mssql_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def dataReceived(self, data): if self._state == 1: - version = b'11000000' - if(data[0] == 0x12): - self.transport.write(unhexlify(b'0401002500000100000015000601001b000102001c000103001d0000ff' + version + b'00000200')) - elif(data[0] == 0x10): - value_start, value_length = unpack('=HH', data[48:52]) - username = data[8 + value_start:8 + value_start + (value_length * 2)].replace(b'\x00', b'').decode('utf-8') - value_start, value_length = unpack('=HH', data[52:56]) - password = data[8 + value_start:8 + value_start + (value_length * 2)] - password = password.replace(b'\x00', b'').replace(b'\xa5', b'') - password_decrypted = '' + version = b"11000000" + if data[0] == 0x12: + self.transport.write( + unhexlify( + b"0401002500000100000015000601001b000102001c000103001d0000ff" + + version + + b"00000200" + ) + ) + elif data[0] == 0x10: + value_start, value_length = unpack("=HH", data[48:52]) + username = ( + data[8 + value_start : 8 + value_start + (value_length * 2)] + .replace(b"\x00", b"") + .decode("utf-8") + ) + value_start, value_length = unpack("=HH", data[52:56]) + password = data[8 + value_start : 8 + value_start + (value_length * 2)] + password = password.replace(b"\x00", b"").replace(b"\xa5", b"") + password_decrypted = "" for x in password: - password_decrypted += chr(((x ^ 0xa5) & 0x0F) << 4 | ((x ^ 0xa5) & 0xF0) >> 4) + password_decrypted += chr( + ((x ^ 0xA5) & 0x0F) << 4 | ((x ^ 0xA5) & 0xF0) >> 4 + ) username = self.check_bytes(username) password = self.check_bytes(password_decrypted) - status = 'failed' + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'mssql_server', 'action': 'login', 'status': status, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + status = "success" + _q_s.logs.info( + { + "server": "mssql_server", + "action": "login", + "status": status, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) - self.transport.write(unhexlify(self.create_payload(token_error_msg=b'Login Failed', error_code=18456))) + self.transport.write( + unhexlify( + self.create_payload( + token_error_msg=b"Login Failed", error_code=18456 + ) + ) + ) else: self.transport.loseConnection() @@ -117,7 +198,7 @@ def connectionLost(self, reason): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -129,13 +210,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' + status = "success" - self.logs.info({'server': 'mssql_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) + self.logs.info( + { + "server": "mssql_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) - if status == 'success': + if status == "success": return True else: self.kill_server() @@ -144,26 +257,36 @@ def run_server(self, process=False, auto=False): self.mssql_server_main() def close_port(self): - ret = close_port_wrapper('mssql_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("mssql_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('mssql_server', self.uuid, self.process) + ret = kill_server_wrapper("mssql_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from pymssql import connect as pconnect + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password - conn = pconnect(host=_ip, port=str(_port), user=_username, password=_password, database='dbname') + conn = pconnect( + host=_ip, port=str(_port), user=_username, password=_password, database="dbname" + ) cursor = conn.cursor() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - QMSSQLServer = QMSSQLServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + QMSSQLServer = QMSSQLServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) QMSSQLServer.run_server() diff --git a/honeypots/mysql_server.py b/honeypots/mysql_server.py index 0bc56e8..5ec9dae 100644 --- a/honeypots/mysql_server.py +++ b/honeypots/mysql_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor @@ -20,66 +21,121 @@ from hashlib import sha1 from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QMysqlServer(): +class QMysqlServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 3306 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 3306 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) self.words = [self.password.encode()] disable_logger(1, tlog) - def load_words(self,): - with open(self.file_name, 'r', encoding='utf-8') as file: + def load_words( + self, + ): + with open(self.file_name, encoding="utf-8") as file: self.words = file.read().splitlines() def greeting(self): - base = ['\x0a', '5.7.00' + '\0', '\x36\x00\x00\x00', '12345678' + '\0', '\xff\xf7', '\x21', '\x02\x00', '\x0f\x81', '\x15', '\0' * 10, '123456789012' + '\0', 'mysql_native_password' + '\0'] - payload_len = list(pack('> 32) - 2208988800.0 - f = float(int(i) & 0xffffffff) / (4294967296) + f = float(int(i) & 0xFFFFFFFF) / (4294967296) return i, f def datagramReceived(self, data, addr): - version = 'UnKnown' - mode = 'UnKnown' - success = 'failed' + version = "UnKnown" + mode = "UnKnown" + success = "failed" unpacked = None - _q_s.logs.info({'server': 'ntp_server', 'action': 'connection', 'src_ip': addr[0], 'src_port': addr[1]}) - if len(data) == calcsize('!B B B b I I I Q Q Q Q'): + _q_s.logs.info( + { + "server": "ntp_server", + "action": "connection", + "src_ip": addr[0], + "src_port": addr[1], + } + ) + if len(data) == calcsize("!B B B b I I I Q Q Q Q"): version = data[0] >> 3 & 0x7 mode = data[0] & 0x7 - unpacked = unpack('!B B B b I I I Q Q Q Q', data) + unpacked = unpack("!B B B b I I I Q Q Q Q", data) if unpacked is not None: i, f = self.system_time_to_ntp(time()) - response = pack('!B B B b I I I Q Q Q Q', 0 << 6 | 3 << 3 | 2, data[1], data[2], data[3], 0, 0, 0, 0, data[10], 0, i + f) + response = pack( + "!B B B b I I I Q Q Q Q", + 0 << 6 | 3 << 3 | 2, + data[1], + data[2], + data[3], + 0, + 0, + 0, + 0, + data[10], + 0, + i + f, + ) self.transport.write(response, addr) - success = 'success' - - _q_s.logs.info({'server': 'ntp_server', 'action': 'query', 'status': 'success', 'src_ip': addr[0], 'src_port': addr[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': {'version': version, 'mode': mode}}) + success = "success" + + _q_s.logs.info( + { + "server": "ntp_server", + "action": "query", + "status": "success", + "src_ip": addr[0], + "src_port": addr[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": {"version": version, "mode": mode}, + } + ) self.transport.loseConnection() - reactor.listenUDP(port=self.port, protocol=CustomDatagramProtocolProtocol(), interface=self.ip) + reactor.listenUDP( + port=self.port, protocol=CustomDatagramProtocolProtocol(), interface=self.ip + ) reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -92,13 +148,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'ntp_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "ntp_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -107,30 +189,38 @@ def run_server(self, process=False, auto=False): self.ntp_server_main() def close_port(self): - ret = close_port_wrapper('ntp_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("ntp_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('ntp_server', self.uuid, self.process) + ret = kill_server_wrapper("ntp_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from warnings import filterwarnings - filterwarnings(action='ignore', module='.*socket.*') + + filterwarnings(action="ignore", module=".*socket.*") from socket import socket, AF_INET, SOCK_DGRAM _ip = ip or self.ip _port = port or self.port c = socket(AF_INET, SOCK_DGRAM) - c.sendto(b'\x1b' + 47 * b'\0', (_ip, _port)) + c.sendto(b"\x1b" + 47 * b"\0", (_ip, _port)) data, address = c.recvfrom(256) - ret_time = unpack('!12I', data)[10] - 2208988800 + ret_time = unpack("!12I", data)[10] - 2208988800 c.close() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - QNTPServer = QNTPServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + QNTPServer = QNTPServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) QNTPServer.run_server() diff --git a/honeypots/oracle_server.py b/honeypots/oracle_server.py index 2eea583..37958ce 100644 --- a/honeypots/oracle_server.py +++ b/honeypots/oracle_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor @@ -20,42 +21,64 @@ from os import path, getenv from struct import unpack from re import findall -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running, set_local_vars +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, + set_local_vars, +) from uuid import uuid4 from contextlib import suppress -class QOracleServer(): +class QOracleServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 1521 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 1521 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def oracle_server_main(self): _q_s = self class CustomRedisProtocol(Protocol): - _state = None def wrong_password(self): - payload = b'\x02B\xc5\xbb\xe7\x7f\x02B\xac\x11\x00\x02\x08\x00E\x00\x01\x02Md@\x00@\x06\x94l\xac\x11\x00\x02\xac\x11\x00\x01\x05\xf1\xa5\xa8\xab\xf5\xff\x94\x98\xdf\xd5\xa1\x80\x18\x01\xf5Y\x1a\x00\x00\x01\x01\x08\nJ\xe7\xf0,\xb2,\xfe\x08\x00\x00\x00\xce\x06\x00\x00\x00\x00\x00\x04\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\xf9\x03\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x006\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x82\x1c\x86u\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf9\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003ORA-01017: invalid username/password; logon denied\n' + payload = b"\x02B\xc5\xbb\xe7\x7f\x02B\xac\x11\x00\x02\x08\x00E\x00\x01\x02Md@\x00@\x06\x94l\xac\x11\x00\x02\xac\x11\x00\x01\x05\xf1\xa5\xa8\xab\xf5\xff\x94\x98\xdf\xd5\xa1\x80\x18\x01\xf5Y\x1a\x00\x00\x01\x01\x08\nJ\xe7\xf0,\xb2,\xfe\x08\x00\x00\x00\xce\x06\x00\x00\x00\x00\x00\x04\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\xf9\x03\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x006\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x82\x1c\x86u\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf9\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003ORA-01017: invalid username/password; logon denied\n" return payload def refuse_payload(self): - payload = b'\x00\x08\x00\x00\x04\x00\x00\x00' + payload = b"\x00\x08\x00\x00\x04\x00\x00\x00" return payload def parse_payload(self, data): @@ -63,30 +86,59 @@ def parse_payload(self, data): program = None local_user = None with suppress(Exception): - packet_len, packet_checksum, packet_type, packet_reserved_bytes, packet_header_checksum = unpack('>hhbbh', data[0:8]) - if b'(DESCRIPTION=' in data: - connect = data[data.index(b'(DESCRIPTION='):].split(b'\0')[0] - found_temp = findall(rb'[^\(\)]+', connect) + ( + packet_len, + packet_checksum, + packet_type, + packet_reserved_bytes, + packet_header_checksum, + ) = unpack(">hhbbh", data[0:8]) + if b"(DESCRIPTION=" in data: + connect = data[data.index(b"(DESCRIPTION=") :].split(b"\0")[0] + found_temp = findall(rb"[^\(\)]+", connect) if len(found_temp) > 0: - found_fixed = [item for item in found_temp if not item.endswith(b'=')] + found_fixed = [item for item in found_temp if not item.endswith(b"=")] if len(found_fixed) > 0: for item in found_fixed: - name, value = item.split(b'=') - if name.startswith(b'SERVICE_NAME'): + name, value = item.split(b"=") + if name.startswith(b"SERVICE_NAME"): service_name = value.decode() - elif name.startswith(b'PROGRAM'): + elif name.startswith(b"PROGRAM"): program = value.decode() - elif name.startswith(b'USER'): + elif name.startswith(b"USER"): local_user = value.decode() return service_name, program, local_user def connectionMade(self): - _q_s.logs.info({'server': 'oracle_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "oracle_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def dataReceived(self, data): service_name, program, local_user = self.parse_payload(data) if service_name or program or local_user: - _q_s.logs.info({'server': 'oracle_server', 'action': 'login', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': {'local_user': local_user, 'program': program, 'service_name': service_name}}) + _q_s.logs.info( + { + "server": "oracle_server", + "action": "login", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": { + "local_user": local_user, + "program": program, + "service_name": service_name, + }, + } + ) self.transport.write(self.refuse_payload()) self.transport.loseConnection() @@ -96,7 +148,7 @@ def dataReceived(self, data): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -108,13 +160,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'oracle_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "oracle_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -123,20 +201,21 @@ def run_server(self, process=False, auto=False): self.oracle_server_main() def close_port(self): - ret = close_port_wrapper('oracle_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("oracle_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('oracle_server', self.uuid, self.process) + ret = kill_server_wrapper("oracle_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from warnings import filterwarnings - filterwarnings(action='ignore', module='.*socket.*') + + filterwarnings(action="ignore", module=".*socket.*") from socket import socket, AF_INET, SOCK_STREAM - payload = b'\x00\x00\x03\x04\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00E\x00\x01F\xb9\xd9@\x00@\x06\x81\xd6\x7f\x00\x00\x01\x7f\x00\x00\x01\xbf\xce\x06\x13\xacW\xde\xc0Z\xb5\x0cI\x80\x18\x02\x00\xff:\x00\x00\x01\x01\x08\n\x1bdZ^\x1bdZ^\x01\x12\x00\x00\x01\x00\x00\x00\x01>\x01,\x0cA \x00\xff\xff\x7f\x08\x00\x00\x01\x00\x00\xc8\x00J\x00\x00\x14\x00AA\xa7C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01(DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=xe)(CID=(PROGRAM=linux_1)(HOST=xxxxxxxxxxxxxx)(USER=xxxxxxxxxxxxxx))(CONNECTION_ID=xxxxxxxxxxxxxxxxxxxxxxxx))(ADDRESS=(PROTOCOL=tcp)(HOST=xxxxxxx)(PORT=xxxx)))' + payload = b"\x00\x00\x03\x04\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00E\x00\x01F\xb9\xd9@\x00@\x06\x81\xd6\x7f\x00\x00\x01\x7f\x00\x00\x01\xbf\xce\x06\x13\xacW\xde\xc0Z\xb5\x0cI\x80\x18\x02\x00\xff:\x00\x00\x01\x01\x08\n\x1bdZ^\x1bdZ^\x01\x12\x00\x00\x01\x00\x00\x00\x01>\x01,\x0cA \x00\xff\xff\x7f\x08\x00\x00\x01\x00\x00\xc8\x00J\x00\x00\x14\x00AA\xa7C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01(DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=xe)(CID=(PROGRAM=linux_1)(HOST=xxxxxxxxxxxxxx)(USER=xxxxxxxxxxxxxx))(CONNECTION_ID=xxxxxxxxxxxxxxxxxxxxxxxx))(ADDRESS=(PROTOCOL=tcp)(HOST=xxxxxxx)(PORT=xxxx)))" _ip = ip or self.ip _port = port or self.port c = socket(AF_INET, SOCK_STREAM) @@ -146,8 +225,15 @@ def test_server(self, ip=None, port=None, username=None, password=None): c.close() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - QOracleServer = QOracleServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + QOracleServer = QOracleServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) QOracleServer.run_server() diff --git a/honeypots/pjl_server.py b/honeypots/pjl_server.py index da3cbc1..51ed607 100644 --- a/honeypots/pjl_server.py +++ b/honeypots/pjl_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,62 +8,79 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from re import split as resplit -from struct import unpack -from binascii import unhexlify -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QPJLServer(): +class QPJLServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.printer = b'Brother HL-L2360' - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.printer = b"Brother HL-L2360" + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 9100 - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' - self.template = {'ProductName': 'Brother HL-L2360', - 'FormatterNumber': 'Q910CHL', - 'PrinterNumber': 'L2360', - 'ProductSerialNumber': 'VNB1897514', - 'ServiceID': '20157', - 'FirmwareDateCode': '20051103', - 'MaxPrintResolution': '900', - 'ControllerNumber': 'Q910CHL', - 'DeviceDescription': 'Brother HL-L2360', - 'DeviceLang': 'ZJS PJL', - 'TotalMemory': '6890816', - 'AvailableMemory': '3706526', - 'Personality': '0', - 'EngFWVer': '10', - 'IPAddress': '172.17.0.2', - 'HWAddress': '0025B395EA01'} + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 9100 + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) + self.template = { + "ProductName": "Brother HL-L2360", + "FormatterNumber": "Q910CHL", + "PrinterNumber": "L2360", + "ProductSerialNumber": "VNB1897514", + "ServiceID": "20157", + "FirmwareDateCode": "20051103", + "MaxPrintResolution": "900", + "ControllerNumber": "Q910CHL", + "DeviceDescription": "Brother HL-L2360", + "DeviceLang": "ZJS PJL", + "TotalMemory": "6890816", + "AvailableMemory": "3706526", + "Personality": "0", + "EngFWVer": "10", + "IPAddress": "172.17.0.2", + "HWAddress": "0025B395EA01", + } disable_logger(1, tlog) def pjl_server_main(self): _q_s = self class Custompjlrotocol(Protocol): - _state = None def check_bytes(self, string): @@ -74,19 +91,39 @@ def check_bytes(self, string): def connectionMade(self): self._state = 1 - _q_s.logs.info({'server': 'pjl_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "pjl_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def dataReceived(self, data): # Control to PJL (Removed) - data = data.replace(b'\x1b%-12345X', b'') - if data.lower().startswith(b'@pjl echo'): - self.transport.write(b'@PJL ' + data[10:] + b'\x1b') - elif data.lower().startswith(b'@pjl info id'): - self.transport.write(b'@PJL INFO ID\r\n' + _q_s.printer + b'\r\n\x1b') - elif data.lower().startswith(b'@pjl prodinfo'): - prodinfo = '\r\n'.join([k + " = " + v for k, v in _q_s.template.items()]) - self.transport.write(prodinfo.encode('utf-8') + b'\x1b') - _q_s.logs.info({'server': 'ntp_server', 'action': 'query', 'status': 'success', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': {'command': self.check_bytes(data)}}) + data = data.replace(b"\x1b%-12345X", b"") + if data.lower().startswith(b"@pjl echo"): + self.transport.write(b"@PJL " + data[10:] + b"\x1b") + elif data.lower().startswith(b"@pjl info id"): + self.transport.write(b"@PJL INFO ID\r\n" + _q_s.printer + b"\r\n\x1b") + elif data.lower().startswith(b"@pjl prodinfo"): + prodinfo = "\r\n".join([k + " = " + v for k, v in _q_s.template.items()]) + self.transport.write(prodinfo.encode("utf-8") + b"\x1b") + _q_s.logs.info( + { + "server": "ntp_server", + "action": "query", + "status": "success", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": {"command": self.check_bytes(data)}, + } + ) self.transport.loseConnection() def connectionLost(self, reason): @@ -98,7 +135,7 @@ def connectionLost(self, reason): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -110,13 +147,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'pjl_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "pjl_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -125,28 +188,31 @@ def run_server(self, process=False, auto=False): self.pjl_server_main() def close_port(self): - ret = close_port_wrapper('pjl_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("pjl_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('pjl_server', self.uuid, self.process) + ret = kill_server_wrapper("pjl_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from warnings import filterwarnings - filterwarnings(action='ignore', module='.*socket.*') + + filterwarnings(action="ignore", module=".*socket.*") from socket import socket, AF_INET, SOCK_STREAM _ip = ip or self.ip _port = port or self.port c = socket(AF_INET, SOCK_STREAM) - c.sendto(b'\x1b%-12345X@PJL prodinfo', (_ip, _port)) + c.sendto(b"\x1b%-12345X@PJL prodinfo", (_ip, _port)) c.close() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qpjlserver = QPJLServer(ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config) + qpjlserver = QPJLServer( + ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config + ) qpjlserver.run_server() diff --git a/honeypots/pop3_server.py b/honeypots/pop3_server.py index 1087454..82a3829 100644 --- a/honeypots/pop3_server.py +++ b/honeypots/pop3_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from typing import Tuple from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.mail.pop3 import POP3, POP3Error from twisted.internet.protocol import Factory @@ -20,35 +21,56 @@ from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QPOP3Server(): +class QPOP3Server: def __init__(self, **kwargs): self.auto_disabled = None - self.mocking_server = choice(['Microsoft Exchange POP3 service is ready']) + self.mocking_server = choice(["Microsoft Exchange POP3 service is ready"]) self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 110 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 110 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def pop3_server_main(self): _q_s = self class CustomPOP3Protocol(POP3): - self._user = None def check_bytes(self, string): @@ -58,50 +80,85 @@ def check_bytes(self, string): return str(string) def connectionMade(self): - _q_s.logs.info({'server': 'pop3_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "pop3_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) self._user = None - self.successResponse('{}'.format(_q_s.mocking_server)) + self.successResponse(f"{_q_s.mocking_server}") def processCommand(self, command: bytes, *args): - with suppress(Exception): if "capture_commands" in _q_s.options: - _q_s.logs.info({'server': 'pop3_server', 'action': 'command', 'data': {"cmd": self.check_bytes(command), "args": self.check_bytes(b" ".join(args))}, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "pop3_server", + "action": "command", + "data": { + "cmd": self.check_bytes(command), + "args": self.check_bytes(b" ".join(args)), + }, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) - if not (command.lower().startswith(b'user') or command.lower().startswith(b'pass')): - self.failResponse('Authentication failed') - return + if not ( + command.lower().startswith(b"user") or command.lower().startswith(b"pass") + ): + self.failResponse("Authentication failed") + return None if self.blocked is not None: self.blocked.append((command, args)) - return + return None command = command.upper() authCmd = command in self.AUTH_CMDS if not self.mbox and not authCmd: raise POP3Error(b"not authenticated yet: cannot do " + command) - f = getattr(self, "do_{}".format(self.check_bytes(command)), None) + f = getattr(self, f"do_{self.check_bytes(command)}", None) if f: return f(*args) raise POP3Error(b"Unknown protocol command: " + command) def do_USER(self, user): self._user = user - self.successResponse('USER Ok') + self.successResponse("USER Ok") def do_PASS(self, password: bytes, *words: Tuple[bytes]): if self._user: username = self.check_bytes(self._user) password = self.check_bytes(b" ".join((password,) + words)) - status = 'failed' + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'pop3_server', 'action': 'login', 'status': status, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) - self.failResponse('Authentication failed') + status = "success" + _q_s.logs.info( + { + "server": "pop3_server", + "action": "login", + "status": status, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) + self.failResponse("Authentication failed") else: - self.failResponse('USER first, then PASS') + self.failResponse("USER first, then PASS") self._user = None @@ -120,7 +177,7 @@ def buildProtocol(self, address): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -132,13 +189,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' + status = "success" - self.logs.info({'server': 'pop3_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) + self.logs.info( + { + "server": "pop3_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) - if status == 'success': + if status == "success": return True else: self.kill_server() @@ -147,16 +236,17 @@ def run_server(self, process=False, auto=False): self.pop3_server_main() def close_port(self): - ret = close_port_wrapper('pop3_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("pop3_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('pop3_server', self.uuid, self.process) + ret = kill_server_wrapper("pop3_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from poplib import POP3 as poplibPOP3 + _ip = ip or self.ip _port = port or self.port _username = username or self.username @@ -167,8 +257,15 @@ def test_server(self, ip=None, port=None, username=None, password=None): pp.pass_(_password) -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qpop3server = QPOP3Server(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qpop3server = QPOP3Server( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qpop3server.run_server() diff --git a/honeypots/postgres_server.py b/honeypots/postgres_server.py index 79412ef..317ed5d 100644 --- a/honeypots/postgres_server.py +++ b/honeypots/postgres_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor @@ -19,34 +20,55 @@ from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QPostgresServer(): +class QPostgresServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 5432 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 5432 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def postgres_server_main(self): _q_s = self class CustomPostgresProtocol(Protocol): - _state = None _variables = {} @@ -57,39 +79,60 @@ def check_bytes(self, string): return str(string) def read_data_custom(self, data): - _data = data.decode('utf-8') - length = unpack('!I', data[0:4]) - encoded_list = (_data[8:-1].split('\x00')) + _data = data.decode("utf-8") + length = unpack("!I", data[0:4]) + encoded_list = _data[8:-1].split("\x00") self._variables = dict(zip(*([iter(encoded_list)] * 2))) def read_password_custom(self, data): - data = data.decode('utf-8') - self._variables['password'] = data[5:].split('\x00')[0] + data = data.decode("utf-8") + self._variables["password"] = data[5:].split("\x00")[0] def connectionMade(self): self._state = 1 self._variables = {} - _q_s.logs.info({'server': 'postgres_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "postgres_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def dataReceived(self, data): if self._state == 1: self._state = 2 - self.transport.write(b'N') + self.transport.write(b"N") elif self._state == 2: self.read_data_custom(data) self._state = 3 - self.transport.write(b'R\x00\x00\x00\x08\x00\x00\x00\x03') + self.transport.write(b"R\x00\x00\x00\x08\x00\x00\x00\x03") elif self._state == 3: - if data[0] == 112 and 'user' in self._variables: + if data[0] == 112 and "user" in self._variables: self.read_password_custom(data) - username = self.check_bytes(self._variables['user']) - password = self.check_bytes(self._variables['password']) - status = 'failed' + username = self.check_bytes(self._variables["user"]) + password = self.check_bytes(self._variables["password"]) + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'postgres_server', 'action': 'login', 'status': status, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + status = "success" + _q_s.logs.info( + { + "server": "postgres_server", + "action": "login", + "status": status, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) self.transport.loseConnection() else: @@ -105,7 +148,7 @@ def connectionLost(self, reason): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -117,13 +160,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'postgres_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "postgres_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -132,16 +207,17 @@ def run_server(self, process=False, auto=False): self.postgres_server_main() def close_port(self): - ret = close_port_wrapper('postgres_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("postgres_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('postgres_server', self.uuid, self.process) + ret = kill_server_wrapper("postgres_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): - from psycopg2 import sql, connect + from psycopg2 import connect + _ip = ip or self.ip _port = port or self.port _username = username or self.username @@ -149,8 +225,15 @@ def test_server(self, ip=None, port=None, username=None, password=None): x = connect(host=_ip, port=_port, user=_username, password=_password) -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qpostgresserver = QPostgresServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qpostgresserver = QPostgresServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qpostgresserver.run_server() diff --git a/honeypots/qbsniffer.py b/honeypots/qbsniffer.py index 3896b45..4966553 100644 --- a/honeypots/qbsniffer.py +++ b/honeypots/qbsniffer.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*scapy.*') + +filterwarnings(action="ignore", module=".*scapy.*") from scapy.all import * from sys import stdout @@ -25,19 +26,56 @@ from uuid import uuid4 -class QBSniffer(): - def __init__(self, filter=None, interface=None, config=''): - self.current_ip = ifaddresses(interface)[AF_INET][0]['addr'].encode('utf-8') - self.current_mac = ifaddresses(interface)[AF_LINK][0]['addr'].encode('utf-8') +class QBSniffer: + def __init__(self, filter=None, interface=None, config=""): + self.current_ip = ifaddresses(interface)[AF_INET][0]["addr"].encode("utf-8") + self.current_mac = ifaddresses(interface)[AF_LINK][0]["addr"].encode("utf-8") self.filter = filter self.interface = interface - self.method = 'TCPUDP' - self.ICMP_codes = [(0, 0, 'Echo/Ping reply'), (3, 0, 'Destination network unreachable'), (3, 1, 'Destination host unreachable'), (3, 2, 'Desination protocol unreachable'), (3, 3, 'Destination port unreachable'), (3, 4, 'Fragmentation required'), (3, 5, 'Source route failed'), (3, 6, 'Destination network unknown'), (3, 7, 'Destination host unknown'), (3, 8, 'Source host isolated'), (3, 9, 'Network administratively prohibited'), (3, 10, 'Host administratively prohibited'), (3, 11, 'Network unreachable for TOS'), (3, 12, 'Host unreachable for TOS'), (3, 13, 'Communication administratively prohibited'), (3, 14, 'Host Precedence Violation'), (3, 15, 'Precendence cutoff in effect'), (4, 0, 'Source quench'), - (5, 0, 'Redirect Datagram for the Network'), (5, 1, 'Redirect Datagram for the Host'), (5, 2, 'Redirect Datagram for the TOS & network'), (5, 3, 'Redirect Datagram for the TOS & host'), (8, 0, 'Echo/Ping Request'), (9, 0, 'Router advertisement'), (10, 0, 'Router discovery/selection/solicitation'), (11, 0, 'TTL expired in transit'), (11, 1, 'Fragment reassembly time exceeded'), (12, 0, 'Pointer indicates the error'), (12, 1, 'Missing a required option'), (12, 2, 'Bad length'), (13, 0, 'Timestamp'), (14, 0, 'Timestamp Reply'), (15, 0, 'Information Request'), (16, 0, 'Information Reply'), (17, 0, 'Address Mask Request'), (18, 0, 'Address Mask Reply'), (30, 0, 'Information Request')] + self.method = "TCPUDP" + self.ICMP_codes = [ + (0, 0, "Echo/Ping reply"), + (3, 0, "Destination network unreachable"), + (3, 1, "Destination host unreachable"), + (3, 2, "Desination protocol unreachable"), + (3, 3, "Destination port unreachable"), + (3, 4, "Fragmentation required"), + (3, 5, "Source route failed"), + (3, 6, "Destination network unknown"), + (3, 7, "Destination host unknown"), + (3, 8, "Source host isolated"), + (3, 9, "Network administratively prohibited"), + (3, 10, "Host administratively prohibited"), + (3, 11, "Network unreachable for TOS"), + (3, 12, "Host unreachable for TOS"), + (3, 13, "Communication administratively prohibited"), + (3, 14, "Host Precedence Violation"), + (3, 15, "Precendence cutoff in effect"), + (4, 0, "Source quench"), + (5, 0, "Redirect Datagram for the Network"), + (5, 1, "Redirect Datagram for the Host"), + (5, 2, "Redirect Datagram for the TOS & network"), + (5, 3, "Redirect Datagram for the TOS & host"), + (8, 0, "Echo/Ping Request"), + (9, 0, "Router advertisement"), + (10, 0, "Router discovery/selection/solicitation"), + (11, 0, "TTL expired in transit"), + (11, 1, "Fragment reassembly time exceeded"), + (12, 0, "Pointer indicates the error"), + (12, 1, "Missing a required option"), + (12, 2, "Bad length"), + (13, 0, "Timestamp"), + (14, 0, "Timestamp Reply"), + (15, 0, "Information Request"), + (16, 0, "Information Reply"), + (17, 0, "Address Mask Request"), + (18, 0, "Address Mask Reply"), + (30, 0, "Information Request"), + ] self.allowed_ports = [] self.allowed_ips = [] - self.common = rcompile(rb'pass|user|login') - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] + self.common = rcompile(rb"pass|user|login") + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] self.config = config if config: self.logs = setup_logger(__class__.__name__, self.uuid, config) @@ -48,7 +86,7 @@ def find_ICMP(self, x1, x2): for _ in self.ICMP_codes: if x1 == _[0] and x2 == _[1]: return _[2] - return 'None' + return "None" def get_layers(self, packet): try: @@ -63,48 +101,176 @@ def scapy_sniffer_main(self): _q_s = self def capture_logic(packet): - _layers, hex_payloads, raw_payloads, _fields, _raw, _hex = [], {}, {}, {}, 'None', 'None' + _layers, hex_payloads, raw_payloads, _fields, _raw, _hex = ( + [], + {}, + {}, + {}, + "None", + "None", + ) _layers = list(self.get_layers(packet)) for layer in _layers: try: _fields[layer] = packet[layer].fields - if 'load' in _fields[layer]: - raw_payloads[layer] = _fields[layer]['load'] - hex_payloads[layer] = hexlify(_fields[layer]['load']) + if "load" in _fields[layer]: + raw_payloads[layer] = _fields[layer]["load"] + hex_payloads[layer] = hexlify(_fields[layer]["load"]) if rsearch(self.common, raw_payloads[layer]): - _q_s.logs.info(['sniffer', {'action': 'creds_check', 'payload': raw_payloads[layer]}]) + _q_s.logs.info( + [ + "sniffer", + {"action": "creds_check", "payload": raw_payloads[layer]}, + ] + ) except Exception as e: - _q_s.logs.error(['errors', {'error': 'capture_logic_1', 'type': 'error -> ' + repr(e)}]) + _q_s.logs.error( + ["errors", {"error": "capture_logic_1", "type": "error -> " + repr(e)}] + ) try: - if _q_s.method == 'ALL': + if _q_s.method == "ALL": try: - _q_s.logs.info(['sniffer', {'action': 'all', 'ip': _q_s.current_ip, 'mac': _q_s.current_mac, 'layers': _layers, 'fields': _fields, 'payload': hex_payloads}]) + _q_s.logs.info( + [ + "sniffer", + { + "action": "all", + "ip": _q_s.current_ip, + "mac": _q_s.current_mac, + "layers": _layers, + "fields": _fields, + "payload": hex_payloads, + }, + ] + ) except Exception as e: - _q_s.logs.error(['errors', {'error': 'capture_logic_2', 'type': 'error -> ' + repr(e)}]) - elif _q_s.method == 'TCPUDP': - if packet.haslayer('IP') and len(hex_payloads) > 0 and packet['IP'].src != _q_s.current_ip: - if packet.haslayer('TCP'): + _q_s.logs.error( + ["errors", {"error": "capture_logic_2", "type": "error -> " + repr(e)}] + ) + elif _q_s.method == "TCPUDP": + if ( + packet.haslayer("IP") + and len(hex_payloads) > 0 + and packet["IP"].src != _q_s.current_ip + ): + if packet.haslayer("TCP"): try: - _q_s.logs.info(['sniffer', {'action': 'tcppayload', 'ip': _q_s.current_ip, 'mac': _q_s.current_mac, 'dest_ip': packet['IP'].src, 'dest_port':packet['TCP'].sport, 'dst_ip':packet['IP'].dst, 'dst_port':packet['TCP'].dport, 'raw_payload':raw_payloads, 'payload':hex_payloads}]) + _q_s.logs.info( + [ + "sniffer", + { + "action": "tcppayload", + "ip": _q_s.current_ip, + "mac": _q_s.current_mac, + "dest_ip": packet["IP"].src, + "dest_port": packet["TCP"].sport, + "dst_ip": packet["IP"].dst, + "dst_port": packet["TCP"].dport, + "raw_payload": raw_payloads, + "payload": hex_payloads, + }, + ] + ) except Exception as e: - _q_s.logs.error(['errors', {'error': 'capture_logic_3', 'type': 'error -> ' + repr(e)}]) - elif packet.haslayer('UDP'): + _q_s.logs.error( + [ + "errors", + { + "error": "capture_logic_3", + "type": "error -> " + repr(e), + }, + ] + ) + elif packet.haslayer("UDP"): try: - _q_s.logs.info(['sniffer', {'action': 'udppayload', 'ip': _q_s.current_ip, 'mac': _q_s.current_mac, 'dest_ip': packet['IP'].src, 'dest_port':packet['UDP'].sport, 'dst_ip':packet['IP'].dst, 'dst_port':packet['UDP'].dport, 'raw_payload':raw_payloads, 'payload':hex_payloads}]) + _q_s.logs.info( + [ + "sniffer", + { + "action": "udppayload", + "ip": _q_s.current_ip, + "mac": _q_s.current_mac, + "dest_ip": packet["IP"].src, + "dest_port": packet["UDP"].sport, + "dst_ip": packet["IP"].dst, + "dst_port": packet["UDP"].dport, + "raw_payload": raw_payloads, + "payload": hex_payloads, + }, + ] + ) except Exception as e: - _q_s.logs.error(['errors', {'error': 'capture_logic_4', 'type': 'error -> ' + repr(e)}]) + _q_s.logs.error( + [ + "errors", + { + "error": "capture_logic_4", + "type": "error -> " + repr(e), + }, + ] + ) - if packet.haslayer('IP') and packet.haslayer('ICMP') and packet['IP'].src != _q_s.current_ip: - _q_s.logs.info(['sniffer', {'action': 'icmp', 'ip': _q_s.current_ip, 'mac': _q_s.current_mac, 'dest_ip': packet['IP'].src, 'dst_ip':packet['IP'].dst, 'ICMP_Code':packet['ICMP'].code, 'ICMP_Type':packet['ICMP'].type, 'ICMP_MSG':self.find_ICMP(packet['ICMP'].type, packet['ICMP'].code)}]) + if ( + packet.haslayer("IP") + and packet.haslayer("ICMP") + and packet["IP"].src != _q_s.current_ip + ): + _q_s.logs.info( + [ + "sniffer", + { + "action": "icmp", + "ip": _q_s.current_ip, + "mac": _q_s.current_mac, + "dest_ip": packet["IP"].src, + "dst_ip": packet["IP"].dst, + "ICMP_Code": packet["ICMP"].code, + "ICMP_Type": packet["ICMP"].type, + "ICMP_MSG": self.find_ICMP( + packet["ICMP"].type, packet["ICMP"].code + ), + }, + ] + ) - if packet.haslayer('IP') and packet.haslayer('TCP') and packet['IP'].src != _q_s.current_ip: - if packet['TCP'].flags == 2: - _q_s.logs.info(['sniffer', {'action': 'tcpscan', 'ip': _q_s.current_ip, 'mac': _q_s.current_mac, 'dest_ip': packet['IP'].src, 'dest_port':packet['TCP'].sport, 'dst_ip':packet['IP'].dst, 'dst_port':packet['TCP'].dport, 'raw_payload':raw_payloads, 'payload':hex_payloads}]) - send(IP(dst=packet['IP'].src, src=packet['IP'].dst) / TCP(dport=packet['TCP'].sport, sport=packet['TCP'].dport, ack=(packet['TCP'].seq + 1), flags='SA'), verbose=False) + if ( + packet.haslayer("IP") + and packet.haslayer("TCP") + and packet["IP"].src != _q_s.current_ip + ): + if packet["TCP"].flags == 2: + _q_s.logs.info( + [ + "sniffer", + { + "action": "tcpscan", + "ip": _q_s.current_ip, + "mac": _q_s.current_mac, + "dest_ip": packet["IP"].src, + "dest_port": packet["TCP"].sport, + "dst_ip": packet["IP"].dst, + "dst_port": packet["TCP"].dport, + "raw_payload": raw_payloads, + "payload": hex_payloads, + }, + ] + ) + send( + IP(dst=packet["IP"].src, src=packet["IP"].dst) + / TCP( + dport=packet["TCP"].sport, + sport=packet["TCP"].dport, + ack=(packet["TCP"].seq + 1), + flags="SA", + ), + verbose=False, + ) except Exception as e: - _q_s.logs.error(['errors', {'error': 'capture_logic_5', 'type': 'error -> ' + repr(e)}]) + _q_s.logs.error( + ["errors", {"error": "capture_logic_5", "type": "error -> " + repr(e)}] + ) stdout.flush() @@ -112,7 +278,7 @@ def capture_logic(packet): def run_sniffer(self, process=None): if process: - self.process = Process(name='QSniffer_', target=self.scapy_sniffer_main) + self.process = Process(name="QSniffer_", target=self.scapy_sniffer_main) self.process.start() else: self.scapy_sniffer_main() @@ -122,8 +288,9 @@ def kill_sniffer(self): self.process.join() -if __name__ == '__main__': +if __name__ == "__main__": from server_options import server_arguments + parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: qsniffer = QSniffer(filter=parsed.filter, interface=parsed.interface, config=parsed.config) diff --git a/honeypots/rdp_server.py b/honeypots/rdp_server.py index 642330c..d22c863 100644 --- a/honeypots/rdp_server.py +++ b/honeypots/rdp_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,43 +8,64 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*paramiko.*') + +filterwarnings(action="ignore", module=".*paramiko.*") from socket import socket, SHUT_RDWR, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR from ssl import SSLContext, PROTOCOL_TLSv1_2, CERT_NONE from subprocess import Popen from os import path, getenv -from honeypots.helper import check_if_server_is_running, close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, set_local_vars, setup_logger +from honeypots.helper import ( + check_if_server_is_running, + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + set_local_vars, + setup_logger, +) from uuid import uuid4 from contextlib import suppress -from threading import Event, Thread -from binascii import hexlify +from threading import Thread from struct import unpack from OpenSSL import crypto from tempfile import gettempdir, _get_candidate_names -class QRDPServer(): +class QRDPServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None self.key = path.join(gettempdir(), next(_get_candidate_names())) self.cert = path.join(gettempdir(), next(_get_candidate_names())) - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 3389 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 3389 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) def rdp_server_main(self): _q_s = self @@ -53,11 +74,11 @@ def CreateCert(host_name, key, cert): pk = crypto.PKey() pk.generate_key(crypto.TYPE_RSA, 2048) c = crypto.X509() - c.get_subject().C = 'US' - c.get_subject().ST = 'OR' - c.get_subject().L = 'None' - c.get_subject().O = 'None' - c.get_subject().OU = 'None' + c.get_subject().C = "US" + c.get_subject().ST = "OR" + c.get_subject().L = "None" + c.get_subject().O = "None" + c.get_subject().OU = "None" c.get_subject().CN = next(_get_candidate_names()) c.set_serial_number(0) before, after = (0, 60 * 60 * 24 * 365 * 2) @@ -65,9 +86,9 @@ def CreateCert(host_name, key, cert): c.gmtime_adj_notAfter(after) c.set_issuer(c.get_subject()) c.set_pubkey(pk) - c.sign(pk, 'sha256') - open(cert, 'wb').write(crypto.dump_certificate(crypto.FILETYPE_PEM, c)) - open(key, 'wb').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk)) + c.sign(pk, "sha256") + open(cert, "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, c)) + open(key, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk)) class ConnectionHandle(Thread): def __init__(self, sock, key, cert): @@ -84,7 +105,7 @@ def check_bytes(self, string): def get_value(self, length, data): with suppress(Exception): - var = b'' + var = b"" for idx, _ in enumerate(data): if _ == 0 and data[idx + 1] == 0: break @@ -94,10 +115,10 @@ def get_value(self, length, data): var += bytes([_]) if length / 2 == len(var): return var - return b'' + return b"" def extract_cookie(self, data): - cookie = b'' + cookie = b"" with suppress(Exception): for idx, _ in enumerate(data): if _ == 13 and data[idx + 1] == 10: @@ -107,10 +128,20 @@ def extract_cookie(self, data): return cookie def extract_creds(self, data): - user = '' - password = '' + user = "" + password = "" with suppress(Exception): - flag, flags, code_page, option_flags, domain_length, user_length, password_length, shell_length, working_dir_length = unpack('HHIIHHHHH', data[15:37]) + ( + flag, + flags, + code_page, + option_flags, + domain_length, + user_length, + password_length, + shell_length, + working_dir_length, + ) = unpack("HHIIHHHHH", data[15:37]) location = 37 domain = self.get_value(domain_length, data[location:]) location = location + domain_length + 2 @@ -125,20 +156,40 @@ def extract_creds(self, data): def run(self): # There is no good documentation on how RDP protocol works (It took a bit of time to figure it out - Use b1105eb1-d1f7-414b-ad68-fd0c5a7823e4 test case) - cookie = '' + cookie = "" rdpdr = False cliprdr = False rdpsnd = False - initiator = b'\x00\x06' + initiator = b"\x00\x06" with suppress(Exception): - _q_s.logs.info({'server': 'rdp_server', 'action': 'connection', 'src_ip': self.sock.getpeername()[0], 'src_port': self.sock.getpeername()[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "rdp_server", + "action": "connection", + "src_ip": self.sock.getpeername()[0], + "src_port": self.sock.getpeername()[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) # Client X.224 Connection Request PDU data = self.sock.recv(1024) - if b'Cookie' in data: + if b"Cookie" in data: cookie = self.extract_cookie(data[11:]) cookie = self.check_bytes(cookie) - _q_s.logs.info({'server': 'rdp_server', 'action': 'stshash', 'mstshash': 'success', 'src_ip': self.sock.getpeername()[0], 'src_port': self.sock.getpeername()[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': {'stshash': cookie}}) + _q_s.logs.info( + { + "server": "rdp_server", + "action": "stshash", + "mstshash": "success", + "src_ip": self.sock.getpeername()[0], + "src_port": self.sock.getpeername()[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": {"stshash": cookie}, + } + ) # Server X.224 Connection Confirm PDU # data[0] version @@ -146,21 +197,25 @@ def run(self): # 14 (x0e) X.224 len # TLS only \x02\x00\x08\x00\x01\x00\x00\x00 - self.sock.send(b'\x03\x00\x00\x13\x0e\xd0\x00\x00\x12\x34\x00\x02\x00\x08\x00\x01\x00\x00\x00') + self.sock.send( + b"\x03\x00\x00\x13\x0e\xd0\x00\x00\x12\x34\x00\x02\x00\x08\x00\x01\x00\x00\x00" + ) ctx = SSLContext(PROTOCOL_TLSv1_2) - ctx.set_ciphers('RSA:!aNULL') + ctx.set_ciphers("RSA:!aNULL") ctx.check_hostname = False ctx.verify_mode = CERT_NONE ctx.load_cert_chain(certfile=self.cert, keyfile=self.key) - self.sock = ctx.wrap_socket(self.sock, server_side=True, do_handshake_on_connect=True) + self.sock = ctx.wrap_socket( + self.sock, server_side=True, do_handshake_on_connect=True + ) data = self.sock.recv(1024) - if b'rdpdr' in data: + if b"rdpdr" in data: rdpdr = True - if b'cliprdr' in data: + if b"cliprdr" in data: cliprdr = True - if b'rdpsnd' in data: + if b"rdpsnd" in data: rdpsnd = True # MCS Connect Response PDU with GCC Conference Create Response @@ -185,14 +240,16 @@ def run(self): # \x08\x0c SC_MULTITRANSPORT # \x08\x00\x00\x00\x00\x00 - self.sock.send(b'\x03\x00\x00\x7c\x02\xf0\x80\x7f\x66\x74\x0a\x01\x00\x02\x01\x00\x30\x1a\x02\x01\x22\x02\x01\x03\x02\x01\x00\x02\x01\x01\x02\x01\x00\x02\x01\x01\x02\x03\x00\xff\xf8\x02\x01\x02\x04\x4e\x00\x05\x00\x14\x7c\x00\x01\x2a\x14\x76\x0a\x01\x01\x00\x01\xc0\x00\x4d\x63\x44\x6e\x38\x01\x0c\x0e\x00\x04\x00\x08\x00\x03\x00\x00\x00\x03\x00\x02\x0c\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x0c\x10\x00\xeb\x03\x04\x00\xec\x03\xed\x03\xee\x03\xef\x03\x04\x0c\x06\x00\xf0\x03\x08\x0c\x08\x00\x00\x00\x00\x00') + self.sock.send( + b"\x03\x00\x00\x7c\x02\xf0\x80\x7f\x66\x74\x0a\x01\x00\x02\x01\x00\x30\x1a\x02\x01\x22\x02\x01\x03\x02\x01\x00\x02\x01\x01\x02\x01\x00\x02\x01\x01\x02\x03\x00\xff\xf8\x02\x01\x02\x04\x4e\x00\x05\x00\x14\x7c\x00\x01\x2a\x14\x76\x0a\x01\x01\x00\x01\xc0\x00\x4d\x63\x44\x6e\x38\x01\x0c\x0e\x00\x04\x00\x08\x00\x03\x00\x00\x00\x03\x00\x02\x0c\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x0c\x10\x00\xeb\x03\x04\x00\xec\x03\xed\x03\xee\x03\xef\x03\x04\x0c\x06\x00\xf0\x03\x08\x0c\x08\x00\x00\x00\x00\x00" + ) data = self.sock.recv(1024) data = self.sock.recv(1024) # Server MCS Attach-User Confirm PDU # 03 00 00 0b 02 f0 80 2e 00 00 06 - self.sock.send(b'\x03\x00\x00\x0b\x02\xf0\x80\x2e\x00' + initiator) + self.sock.send(b"\x03\x00\x00\x0b\x02\xf0\x80\x2e\x00" + initiator) # Multiple channel join # 03 00 00 0c 02 f0 80 38 00 06 03 eb @@ -204,30 +261,49 @@ def run(self): data = self.sock.recv(1024) if len(data) > 14: if data[15] == 64: - username = '' - password = '' - status = 'failed' + username = "" + password = "" + status = "failed" username, password = self.extract_creds(data) username = self.check_bytes(username) password = self.check_bytes(password) if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'rdp_server', 'action': 'login', 'status': status, 'src_ip': self.sock.getpeername()[0], 'src_port': self.sock.getpeername()[1], 'username': username, 'password': password, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + status = "success" + _q_s.logs.info( + { + "server": "rdp_server", + "action": "login", + "status": status, + "src_ip": self.sock.getpeername()[0], + "src_port": self.sock.getpeername()[1], + "username": username, + "password": password, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) break else: - self.sock.send(b'\x03\x00\x00\x0f\x02\xf0\x80\x3e\x00' + initiator + b'\x03' + bytes([data[-1]]) + b'\x03' + bytes([data[-1]])) + self.sock.send( + b"\x03\x00\x00\x0f\x02\xf0\x80\x3e\x00" + + initiator + + b"\x03" + + bytes([data[-1]]) + + b"\x03" + + bytes([data[-1]]) + ) # MCS Disconnect Provider Ultimatum PDU - self.sock.send(b'\x03\x00\x00\x09\x02\xf0\x80\x21\x80') + self.sock.send(b"\x03\x00\x00\x09\x02\xf0\x80\x21\x80") with suppress(Exception): self.sock.shutdown(SHUT_RDWR) with suppress(Exception): self.sock.close() - CreateCert('localhost', self.key, self.cert) + CreateCert("localhost", self.key, self.cert) rpdserver = socket(AF_INET, SOCK_STREAM) rpdserver.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) rpdserver.bind((self.ip, self.port)) @@ -240,7 +316,7 @@ def run(self): ConnectionHandle(client, self.key, self.cert).start() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -252,13 +328,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'rdp_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "rdp_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -267,28 +375,36 @@ def run_server(self, process=False, auto=False): self.rdp_server_main() def close_port(self): - ret = close_port_wrapper('rdp_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("rdp_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('rdp_server', self.uuid, self.process) + ret = kill_server_wrapper("rdp_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None): with suppress(Exception): from warnings import filterwarnings - filterwarnings(action='ignore', module='.*socket.*') + + filterwarnings(action="ignore", module=".*socket.*") from socket import socket, AF_INET, SOCK_STREAM _ip = ip or self.ip _port = port or self.port c = socket(AF_INET, SOCK_STREAM) - c.sendto(b'test', (_ip, _port)) + c.sendto(b"test", (_ip, _port)) c.close() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qrdpserver = QRDPServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qrdpserver = QRDPServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qrdpserver.run_server() diff --git a/honeypots/redis_server.py b/honeypots/redis_server.py index 2f36d57..4210cff 100644 --- a/honeypots/redis_server.py +++ b/honeypots/redis_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,44 +8,67 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running, set_local_vars +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, + set_local_vars, +) from uuid import uuid4 from contextlib import suppress -class QRedisServer(): +class QRedisServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 6379 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 6379 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def redis_server_main(self): _q_s = self class CustomRedisProtocol(Protocol): - def check_bytes(self, string): if isinstance(string, bytes): return string.decode() @@ -54,49 +77,72 @@ def check_bytes(self, string): def get_command(self, data): with suppress(Exception): - _data = data.decode('utf-8').split('\x0d\x0a') - if _data[0][0] == '*': + _data = data.decode("utf-8").split("\x0d\x0a") + if _data[0][0] == "*": _count = int(_data[0][1]) - 1 _data.pop(0) - if _data[0::2][0][0] == '$' and len(_data[1::2][0]) == int(_data[0::2][0][1]): + if _data[0::2][0][0] == "$" and len(_data[1::2][0]) == int( + _data[0::2][0][1] + ): return _count, _data[1::2][0] - return 0, '' + return 0, "" def parse_data(self, c, data): - _data = data.decode('utf-8').split('\r\n')[3::] - username, password = '', '' + _data = data.decode("utf-8").split("\r\n")[3::] + username, password = "", "" if c == 2: _ = 0 - if _data[0::2][_][0] == '$' and len(_data[1::2][_]) == int(_data[0::2][_][1]): - username = (_data[1::2][_]) + if _data[0::2][_][0] == "$" and len(_data[1::2][_]) == int(_data[0::2][_][1]): + username = _data[1::2][_] _ = 1 - if _data[0::2][_][0] == '$' and len(_data[1::2][_]) == int(_data[0::2][_][1]): - password = (_data[1::2][_]) + if _data[0::2][_][0] == "$" and len(_data[1::2][_]) == int(_data[0::2][_][1]): + password = _data[1::2][_] if c == 1: _ = 0 - if _data[0::2][_][0] == '$' and len(_data[1::2][_]) == int(_data[0::2][_][1]): - password = (_data[1::2][_]) + if _data[0::2][_][0] == "$" and len(_data[1::2][_]) == int(_data[0::2][_][1]): + password = _data[1::2][_] if c == 2 or c == 1: username = self.check_bytes(username) password = self.check_bytes(password) - status = 'failed' + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'redis_server', 'action': 'login', 'status': status, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + status = "success" + _q_s.logs.info( + { + "server": "redis_server", + "action": "login", + "status": status, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) def connectionMade(self): self._state = 1 self._variables = {} - _q_s.logs.info({'server': 'redis_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "redis_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def dataReceived(self, data): c, command = self.get_command(data) - if command == 'AUTH': + if command == "AUTH": self.parse_data(c, data) - self.transport.write(b'-ERR invalid password\r\n') + self.transport.write(b"-ERR invalid password\r\n") else: self.transport.write(b'-ERR unknown command "{}"\r\n'.format(command)) self.transport.loseConnection() @@ -107,7 +153,7 @@ def dataReceived(self, data): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -119,13 +165,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'redis_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "redis_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -134,27 +212,35 @@ def run_server(self, process=False, auto=False): self.redis_server_main() def close_port(self): - ret = close_port_wrapper('redis_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("redis_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('redis_server', self.uuid, self.process) + ret = kill_server_wrapper("redis_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from redis import StrictRedis + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password - r = StrictRedis.from_url('redis://{}:{}@{}:{}/1'.format(_username, _password, _ip, _port)) - for key in r.scan_iter('user:*'): + r = StrictRedis.from_url(f"redis://{_username}:{_password}@{_ip}:{_port}/1") + for key in r.scan_iter("user:*"): pass -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qredisserver = QRedisServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qredisserver = QRedisServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qredisserver.run_server() diff --git a/honeypots/sip_server.py b/honeypots/sip_server.py index 2a78db6..0ad4c6d 100644 --- a/honeypots/sip_server.py +++ b/honeypots/sip_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,38 +8,60 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.protocols.sip import Base from twisted.internet import reactor -from time import time from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QSIPServer(): +class QSIPServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 5060 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 5060 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def sip_server_main(self): @@ -49,17 +71,33 @@ class CustomSIPServer(Base): def handle_request(self, message, addr): headers = {} - _q_s.logs.info({'server': 'sip_server', 'action': 'connection', 'src_ip': addr[0], 'src_port': addr[1]}) + _q_s.logs.info( + { + "server": "sip_server", + "action": "connection", + "src_ip": addr[0], + "src_port": addr[1], + } + ) def check_bytes(string): if isinstance(string, bytes): return string.decode() else: return str(string) - for item, value in message.headers.items(): - headers.update({check_bytes(item): ','.join(map(check_bytes, value))}) - _q_s.logs.info({'server': 'sip_server', 'action': 'request', 'src_ip': addr[0], 'src_port': addr[1], 'data': headers}) + for item, value in message.headers.items(): + headers.update({check_bytes(item): ",".join(map(check_bytes, value))}) + + _q_s.logs.info( + { + "server": "sip_server", + "action": "request", + "src_ip": addr[0], + "src_port": addr[1], + "data": headers, + } + ) response = self.responseFromRequest(200, message) response.creationFinished() self.deliverResponse(response) @@ -68,7 +106,7 @@ def check_bytes(string): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -80,13 +118,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'sip_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "sip_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -95,27 +159,38 @@ def run_server(self, process=False, auto=False): self.sip_server_main() def close_port(self): - ret = close_port_wrapper('sip_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("sip_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('sip_server', self.uuid, self.process) + ret = kill_server_wrapper("sip_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from socket import socket, AF_INET, SOCK_DGRAM, IPPROTO_UDP + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) - sock.sendto(b'INVITE sip:user_1@test.test SIP/2.0\r\nTo: \r\nFrom: sip:user_3@test.test.test;tag=none\r\nCall-ID: 1@0.0.0.0\r\nCSeq: 1 INVITE\r\nContact: sip:user_3@test.test.test\r\nVia: SIP/2.0/TCP 0.0.0.0;branch=34uiddhjczqw3mq23\r\nContent-Length: 1\r\n\r\nT', (_ip, _port)) + sock.sendto( + b"INVITE sip:user_1@test.test SIP/2.0\r\nTo: \r\nFrom: sip:user_3@test.test.test;tag=none\r\nCall-ID: 1@0.0.0.0\r\nCSeq: 1 INVITE\r\nContact: sip:user_3@test.test.test\r\nVia: SIP/2.0/TCP 0.0.0.0;branch=34uiddhjczqw3mq23\r\nContent-Length: 1\r\n\r\nT", + (_ip, _port), + ) sock.close() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - QSIPServer = QSIPServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + QSIPServer = QSIPServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) QSIPServer.run_server() diff --git a/honeypots/smb_server.py b/honeypots/smb_server.py index 95ef171..a6f479a 100644 --- a/honeypots/smb_server.py +++ b/honeypots/smb_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,11 +8,12 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', category=DeprecationWarning) -filterwarnings(action='ignore', module='.*impacket.*') + +filterwarnings(action="ignore", category=DeprecationWarning) +filterwarnings(action="ignore", module=".*impacket.*") from logging import StreamHandler, getLogger, DEBUG from impacket import smbserver @@ -23,53 +24,98 @@ from logging import DEBUG, getLogger from os import path, getenv from subprocess import Popen -from six.moves import configparser, socketserver -from threading import enumerate as threading_enumerate +from six.moves import socketserver from random import randint from threading import current_thread -from honeypots.helper import check_if_server_is_running, close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, set_local_vars, setup_logger +from honeypots.helper import ( + check_if_server_is_running, + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + set_local_vars, + setup_logger, +) from uuid import uuid4 from contextlib import suppress -class QSMBServer(): +class QSMBServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.folders = '' - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.folders = "" + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 445 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 445 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) self.disable_logger() def disable_logger(self): - getLogger('impacket').propagate = False + getLogger("impacket").propagate = False def smb_server_main(self): _q_s = self - class Logger(object): + class Logger: def write(self, message): with suppress(Exception): temp = current_thread().name - if temp.startswith('thread_'): - ip = temp.split('_')[1] - port = temp.split('_')[2] - if 'Incoming connection' in message.strip() or 'AUTHENTICATE_MESSAGE' in message.strip() or 'authenticated successfully' in message.strip(): - _q_s.logs.info({'server': 'smb_server', 'action': 'connection', 'data': message.strip(), 'src_ip': ip, 'src_port': port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) - elif ':4141414141414141:' in message.strip(): - parsed = message.strip().split(':') + if temp.startswith("thread_"): + ip = temp.split("_")[1] + port = temp.split("_")[2] + if ( + "Incoming connection" in message.strip() + or "AUTHENTICATE_MESSAGE" in message.strip() + or "authenticated successfully" in message.strip() + ): + _q_s.logs.info( + { + "server": "smb_server", + "action": "connection", + "data": message.strip(), + "src_ip": ip, + "src_port": port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) + elif ":4141414141414141:" in message.strip(): + parsed = message.strip().split(":") if len(parsed) > 2: - _q_s.logs.info({'server': 'smb_server', 'action': 'login', 'workstation': parsed[0], 'test': parsed[1], 'src_ip': ip, 'src_port': port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "smb_server", + "action": "login", + "workstation": parsed[0], + "test": parsed[1], + "src_ip": ip, + "src_port": port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) class SMBSERVERHandler(smbserver.SMBSERVERHandler): def __init__(self, request, client_address, server, select_poll=False): @@ -78,7 +124,7 @@ def __init__(self, request, client_address, server, select_poll=False): self.__request = request self.__select_poll = select_poll self.__ip, self.__port = client_address[:2] - self.__connId = "thread_{}_{}_{}".format(self.__ip, self.__port, randint(1000, 9999)) + self.__connId = f"thread_{self.__ip}_{self.__port}_{randint(1000, 9999)}" current_thread().name = self.__connId socketserver.BaseRequestHandler.__init__(self, request, client_address, server) @@ -91,11 +137,13 @@ def processRequest(self, connId, data): return x class SimpleSMBServer(smbserver.SimpleSMBServer): - def __init__(self, listenAddress='0.0.0.0', listenPort=445, configFile=''): + def __init__(self, listenAddress="0.0.0.0", listenPort=445, configFile=""): super().__init__(listenAddress, listenPort, configFile) self.__server.server_close() sleep(randint(1, 2)) - self.__server = SMBSERVER((listenAddress, listenPort), config_parser=self.__smbConfig) + self.__server = SMBSERVER( + (listenAddress, listenPort), config_parser=self.__smbConfig + ) self.__server.processConfigFile() def start(self): @@ -104,28 +152,30 @@ def start(self): self.__server.serve_forever() handler = StreamHandler(Logger()) - getLogger('impacket').addHandler(handler) - getLogger('impacket').setLevel(DEBUG) + getLogger("impacket").addHandler(handler) + getLogger("impacket").setLevel(DEBUG) dirpath = mkdtemp() server = SimpleSMBServer(listenAddress=self.ip, listenPort=self.port) # server.removeShare('IPC$') - if self.folders == '' or self.folders is None: - server.addShare('C$', dirpath, '', readOnly='yes') + if self.folders == "" or self.folders is None: + server.addShare("C$", dirpath, "", readOnly="yes") else: - for folder in self.folders.split(','): - name, d = folder.split(':') + for folder in self.folders.split(","): + name, d = folder.split(":") if path.isdir(d) and len(name) > 0: - server.addShare(name, d, '', readOnly='yes') + server.addShare(name, d, "", readOnly="yes") server.setSMB2Support(True) - server.addCredential(self.username, 0, compute_lmhash(self.password), compute_nthash(self.password)) - server.setSMBChallenge('') + server.addCredential( + self.username, 0, compute_lmhash(self.password), compute_nthash(self.password) + ) + server.setSMBChallenge("") server.start() rmtree(dirpath) def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -137,13 +187,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' + status = "success" - self.logs.info({'server': 'smb_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) + self.logs.info( + { + "server": "smb_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) - if status == 'success': + if status == "success": return True else: self.kill_server() @@ -152,16 +234,17 @@ def run_server(self, process=False, auto=False): self.smb_server_main() def close_port(self): - ret = close_port_wrapper('smb_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("smb_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('smb_server', self.uuid, self.process) + ret = kill_server_wrapper("smb_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from impacket.smbconnection import SMBConnection + _ip = ip or self.ip _port = port or self.port _username = username or self.username @@ -170,9 +253,16 @@ def test_server(self, ip=None, port=None, username=None, password=None): smb_client.login(_username, _password) -if __name__ == '__main__': - +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qsmbserver = QSMBServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, folders=parsed.folders, options=parsed.options, config=parsed.config) + qsmbserver = QSMBServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + folders=parsed.folders, + options=parsed.options, + config=parsed.config, + ) qsmbserver.run_server() diff --git a/honeypots/smtp_server.py b/honeypots/smtp_server.py index bb680a7..19f27eb 100644 --- a/honeypots/smtp_server.py +++ b/honeypots/smtp_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,43 +8,64 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', category=DeprecationWarning) + +filterwarnings(action="ignore", category=DeprecationWarning) from smtpd import SMTPChannel, SMTPServer from asyncore import loop from base64 import b64decode from os import path, getenv from subprocess import Popen -from honeypots.helper import check_if_server_is_running, close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, set_local_vars, setup_logger +from honeypots.helper import ( + check_if_server_is_running, + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + set_local_vars, + setup_logger, +) from uuid import uuid4 from contextlib import suppress -class QSMTPServer(): +class QSMTPServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 25 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 25 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) def smtp_server_main(self): _q_s = self class CustomSMTPChannel(SMTPChannel): - def check_bytes(self, string): if isinstance(string, bytes): return string.decode() @@ -58,44 +79,77 @@ def found_terminator(self): command = None arg = None data = None - if line.find(' ') < 0: + if line.find(" ") < 0: command = line.upper() else: - command = line.split(' ')[0].upper() - arg = line.split(' ')[1].strip() - if len(line.split(' ')) > 2: - data = line.split(' ', 2)[2] + command = line.split(" ")[0].upper() + arg = line.split(" ")[1].strip() + if len(line.split(" ")) > 2: + data = line.split(" ", 2)[2] if command != "HELO" and command != "EHLO": - _q_s.logs.info({'server': 'smtp_server', 'action': 'connection', 'src_ip': self.addr[0], 'src_port': self.addr[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, "data": {"command": command, "arg": arg, "data": data}}) + _q_s.logs.info( + { + "server": "smtp_server", + "action": "connection", + "src_ip": self.addr[0], + "src_port": self.addr[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": {"command": command, "arg": arg, "data": data}, + } + ) super().found_terminator() def smtp_EHLO(self, arg): - _q_s.logs.info({'server': 'smtp_server', 'action': 'connection', 'src_ip': self.addr[0], 'src_port': self.addr[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "smtp_server", + "action": "connection", + "src_ip": self.addr[0], + "src_port": self.addr[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) if not arg: - self.push('501 Syntax: HELO hostname') + self.push("501 Syntax: HELO hostname") if self._SMTPChannel__greeting: - self.push('503 Duplicate HELO/EHLO') + self.push("503 Duplicate HELO/EHLO") else: self._SMTPChannel__greeting = arg - self.push('250-{0} Hello {1}'.format(self._SMTPChannel__fqdn, arg)) - self.push('250-8BITMIME') - self.push('250-AUTH LOGIN PLAIN') - self.push('250 STARTTLS') + self.push(f"250-{self._SMTPChannel__fqdn} Hello {arg}") + self.push("250-8BITMIME") + self.push("250-AUTH LOGIN PLAIN") + self.push("250 STARTTLS") def smtp_AUTH(self, arg): with suppress(Exception): - if arg.startswith('PLAIN '): - _, username, password = b64decode(arg.split(' ')[1].strip()).decode('utf-8').split('\0') + if arg.startswith("PLAIN "): + _, username, password = ( + b64decode(arg.split(" ")[1].strip()).decode("utf-8").split("\0") + ) username = self.check_bytes(username) password = self.check_bytes(password) - status = 'failed' + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'smtp_server', 'action': 'login', 'status': status, 'src_ip': self.addr[0], 'src_port': self.addr[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + status = "success" + _q_s.logs.info( + { + "server": "smtp_server", + "action": "login", + "status": status, + "src_ip": self.addr[0], + "src_port": self.addr[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) - self.push('235 Authentication successful') + self.push("235 Authentication successful") def __getattr__(self, name): self.smtp_QUIT(0) @@ -104,7 +158,9 @@ class CustomSMTPServer(SMTPServer): def __init__(self, localaddr, remoteaddr): SMTPServer.__init__(self, localaddr, remoteaddr) - def process_message(self, peer, mailfrom, rcpttos, data, mail_options=None, rcpt_options=None): + def process_message( + self, peer, mailfrom, rcpttos, data, mail_options=None, rcpt_options=None + ): return def handle_accept(self): @@ -115,7 +171,7 @@ def handle_accept(self): loop(timeout=1.1, use_poll=True) def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -127,13 +183,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' + status = "success" - self.logs.info({'server': 'smtp_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) + self.logs.info( + { + "server": "smtp_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) - if status == 'success': + if status == "success": return True else: self.kill_server() @@ -142,16 +230,17 @@ def run_server(self, process=False, auto=False): self.smtp_server_main() def close_port(self): - ret = close_port_wrapper('smtp_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("smtp_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('smtp_server', self.uuid, self.process) + ret = kill_server_wrapper("smtp_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from smtplib import SMTP + _ip = ip or self.ip _port = port or self.port _username = username or self.username @@ -159,12 +248,19 @@ def test_server(self, ip=None, port=None, username=None, password=None): s = SMTP(_ip, _port) s.ehlo() s.login(_username, _password) - s.sendmail('fromtest', 'totest', 'Nothing') + s.sendmail("fromtest", "totest", "Nothing") s.quit() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qsmtpserver = QSMTPServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qsmtpserver = QSMTPServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qsmtpserver.run_server() diff --git a/honeypots/snmp_server.py b/honeypots/snmp_server.py index c86c6c6..b47fa9a 100644 --- a/honeypots/snmp_server.py +++ b/honeypots/snmp_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,11 +8,12 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') -filterwarnings(action='ignore', module='.*scapy.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") +filterwarnings(action="ignore", module=".*scapy.*") from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor @@ -20,25 +21,43 @@ from subprocess import Popen from os import path, getenv from scapy.all import SNMP -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QSNMPServer(): +class QSNMPServer: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 161 - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 161 + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def snmp_server_main(self): @@ -46,30 +65,53 @@ def snmp_server_main(self): class CustomDatagramProtocolProtocol(DatagramProtocol): def parse_snmp(self, data): - version = 'UnKnown' - community = 'UnKnown' - oids = 'UnKnown' + version = "UnKnown" + community = "UnKnown" + oids = "UnKnown" with suppress(Exception): parsed_snmp = SNMP(data) community = parsed_snmp.community.val version = parsed_snmp.version.val - oids = ' '.join([item.oid.val for item in parsed_snmp.PDU.varbindlist]) + oids = " ".join([item.oid.val for item in parsed_snmp.PDU.varbindlist]) return version, community, oids def datagramReceived(self, data, addr): - _q_s.logs.info({'server': 'snmp_server', 'action': 'connection', 'status': 'fail', 'src_ip': addr[0], 'src_port': addr[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "snmp_server", + "action": "connection", + "status": "fail", + "src_ip": addr[0], + "src_port": addr[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) version, community, oids = self.parse_snmp(data) if version or community or oids: - _q_s.logs.info({'server': 'snmp_server', 'action': 'query', 'status': 'success', 'src_ip': addr[0], 'src_port': addr[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'data': {'version': version, 'community': community, 'oids': oids}}) - self.transport.write('Error', addr) + _q_s.logs.info( + { + "server": "snmp_server", + "action": "query", + "status": "success", + "src_ip": addr[0], + "src_port": addr[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": {"version": version, "community": community, "oids": oids}, + } + ) + self.transport.write("Error", addr) self.transport.loseConnection() - reactor.listenUDP(port=self.port, protocol=CustomDatagramProtocolProtocol(), interface=self.ip) + reactor.listenUDP( + port=self.port, protocol=CustomDatagramProtocolProtocol(), interface=self.ip + ) reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -81,13 +123,39 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'snmp_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "snmp_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -96,24 +164,41 @@ def run_server(self, process=False, auto=False): self.snmp_server_main() def close_port(self): - ret = close_port_wrapper('snmp_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("snmp_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('snmp_server', self.uuid, self.process) + ret = kill_server_wrapper("snmp_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): - from pysnmp.hlapi import (getCmd, SnmpEngine, CommunityData, UdpTransportTarget, ContextData, ObjectType, ObjectIdentity,) + from pysnmp.hlapi import ( + getCmd, + SnmpEngine, + CommunityData, + UdpTransportTarget, + ContextData, + ObjectType, + ObjectIdentity, + ) + _ip = ip or self.ip _port = port or self.port - g = getCmd(SnmpEngine(), CommunityData('public'), UdpTransportTarget((_ip, _port)), ContextData(), ObjectType(ObjectIdentity('1.3.6.1.4.1.9.9.618.1.4.1.0'))) + g = getCmd( + SnmpEngine(), + CommunityData("public"), + UdpTransportTarget((_ip, _port)), + ContextData(), + ObjectType(ObjectIdentity("1.3.6.1.4.1.9.9.618.1.4.1.0")), + ) errorIndication, errorStatus, errorIndex, varBinds = next(g) -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - QSNMPServer = QSNMPServer(ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config) + QSNMPServer = QSNMPServer( + ip=parsed.ip, port=parsed.port, options=parsed.options, config=parsed.config + ) QSNMPServer.run_server() diff --git a/honeypots/socks5_server.py b/honeypots/socks5_server.py index cd98e0e..afcc08c 100644 --- a/honeypots/socks5_server.py +++ b/honeypots/socks5_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,42 +8,63 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from socketserver import TCPServer, StreamRequestHandler, ThreadingMixIn from struct import unpack from os import path, getenv from subprocess import Popen -from honeypots.helper import check_if_server_is_running, close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, set_local_vars, setup_logger +from honeypots.helper import ( + check_if_server_is_running, + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + set_local_vars, + setup_logger, +) from uuid import uuid4 from contextlib import suppress -class QSOCKS5Server(): +class QSOCKS5Server: def __init__(self, **kwargs): self.auto_disabled = None self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 1080 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 1080 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) def socks5_server_main(self): _q_s = self class CustomStreamRequestHandler(StreamRequestHandler): - def check_bytes(self, string): if isinstance(string, bytes): return string.decode() @@ -51,24 +72,45 @@ def check_bytes(self, string): return str(string) def handle(self): - _q_s.logs.info({'server': 'socks5_server', 'action': 'connection', 'src_ip': self.client_address[0], 'src_port': self.client_address[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) - v, m = unpack('!BB', self.connection.recv(2)) + _q_s.logs.info( + { + "server": "socks5_server", + "action": "connection", + "src_ip": self.client_address[0], + "src_port": self.client_address[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) + v, m = unpack("!BB", self.connection.recv(2)) if v == 5: - if 2 in unpack('!' + 'B' * m, self.connection.recv(m)): - self.connection.sendall(b'\x05\x02') - if 1 in unpack('B', self.connection.recv(1)): + if 2 in unpack("!" + "B" * m, self.connection.recv(m)): + self.connection.sendall(b"\x05\x02") + if 1 in unpack("B", self.connection.recv(1)): _len = ord(self.connection.recv(1)) username = self.connection.recv(_len) _len = ord(self.connection.recv(1)) password = self.connection.recv(_len) username = self.check_bytes(username) password = self.check_bytes(password) - status = 'failed' + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'socks5_server', 'action': 'login', 'status': status, 'src_ip': self.client_address[0], 'src_port': self.client_address[1], 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + status = "success" + _q_s.logs.info( + { + "server": "socks5_server", + "action": "login", + "status": status, + "src_ip": self.client_address[0], + "src_port": self.client_address[1], + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) self.server.close_request(self.request) @@ -80,7 +122,7 @@ class ThreadingTCPServer(ThreadingMixIn, TCPServer): server.serve_forever() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -92,13 +134,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'socks5_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "socks5_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -107,25 +181,39 @@ def run_server(self, process=False, auto=False): self.socks5_server_main() def close_port(self): - ret = close_port_wrapper('socks5_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("socks5_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('socks5_server', self.uuid, self.process) + ret = kill_server_wrapper("socks5_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from requests import get + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password - get('https://yahoo.com', proxies=dict(http='socks5://{}:{}@{}:{}'.format(_username, _password, _ip, _port), https='socks5://{}:{}@{}:{}'.format(_username, _password, _ip, _port))) + get( + "https://yahoo.com", + proxies=dict( + http=f"socks5://{_username}:{_password}@{_ip}:{_port}", + https=f"socks5://{_username}:{_password}@{_ip}:{_port}", + ), + ) -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - QSOCKS5Server = QSOCKS5Server(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + QSOCKS5Server = QSOCKS5Server( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) QSOCKS5Server.run_server() diff --git a/honeypots/ssh_server.py b/honeypots/ssh_server.py index 689ef62..febcec1 100644 --- a/honeypots/ssh_server.py +++ b/honeypots/ssh_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,20 +8,38 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*paramiko.*') -filterwarnings(action='ignore', module='.*socket.*') -from paramiko import RSAKey, ServerInterface, Transport, OPEN_SUCCEEDED, AUTH_PARTIALLY_SUCCESSFUL, AUTH_SUCCESSFUL, OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED, OPEN_SUCCEEDED, AUTH_FAILED -from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR, getfqdn +filterwarnings(action="ignore", module=".*paramiko.*") +filterwarnings(action="ignore", module=".*socket.*") + +from paramiko import ( + RSAKey, + ServerInterface, + Transport, + OPEN_SUCCEEDED, + AUTH_SUCCESSFUL, + OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED, + OPEN_SUCCEEDED, + AUTH_FAILED, +) +from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR from _thread import start_new_thread from io import StringIO from random import choice from subprocess import Popen from os import path, getenv -from honeypots.helper import check_if_server_is_running, close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, set_local_vars, setup_logger +from honeypots.helper import ( + check_if_server_is_running, + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + set_local_vars, + setup_logger, +) from uuid import uuid4 from contextlib import suppress from re import compile as rcompile @@ -30,24 +48,39 @@ from binascii import hexlify -class QSSHServer(): +class QSSHServer: def __init__(self, **kwargs): self.auto_disabled = None - self.mocking_server = choice(['OpenSSH 7.5', 'OpenSSH 7.3', 'Serv-U SSH Server 15.1.1.108', 'OpenSSH 6.4']) + self.mocking_server = choice( + ["OpenSSH 7.5", "OpenSSH 7.3", "Serv-U SSH Server 15.1.1.108", "OpenSSH 6.4"] + ) self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 22 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' - self.ansi = rcompile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]') + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 22 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) + self.ansi = rcompile(r"(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]") def generate_pub_pri_keys(self): with suppress(Exception): @@ -61,7 +94,6 @@ def ssh_server_main(self): _q_s = self class SSHHandle(ServerInterface): - def __init__(self, ip, port): self.ip = ip self.port = port @@ -75,27 +107,61 @@ def check_bytes(self, string): return str(string) def check_channel_request(self, kind, chanid): - if kind == 'session': + if kind == "session": return OPEN_SUCCEEDED return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED def check_auth_password(self, username, password): username = self.check_bytes(username) password = self.check_bytes(password) - status = 'failed' + status = "failed" if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - if status == 'success': - _q_s.logs.info({'server': 'ssh_server', 'action': 'login', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + status = "success" + if status == "success": + _q_s.logs.info( + { + "server": "ssh_server", + "action": "login", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) return AUTH_SUCCESSFUL - _q_s.logs.info({'server': 'ssh_server', 'action': 'login', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + _q_s.logs.info( + { + "server": "ssh_server", + "action": "login", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) return AUTH_FAILED def check_channel_exec_request(self, channel, command): if "capture_commands" in _q_s.options: - _q_s.logs.info({'server': 'ssh_server', 'action': 'command', 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, "data": {"command": self.check_bytes(command)}}) + _q_s.logs.info( + { + "server": "ssh_server", + "action": "command", + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": {"command": self.check_bytes(command)}, + } + ) self.event.set() return True @@ -103,7 +169,18 @@ def get_allowed_auths(self, username): return "password,publickey" def check_auth_publickey(self, username, key): - _q_s.logs.info({'server': 'ssh_server', 'action': 'login', 'src_ip': self.ip, 'src_port': self.port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, "username": self.check_bytes(username), 'key_fingerprint': self.check_bytes(hexlify(key.get_fingerprint()))}) + _q_s.logs.info( + { + "server": "ssh_server", + "action": "login", + "src_ip": self.ip, + "src_port": self.port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": self.check_bytes(username), + "key_fingerprint": self.check_bytes(hexlify(key.get_fingerprint())), + } + ) return AUTH_SUCCESSFUL def check_channel_shell_request(self, channel): @@ -112,26 +189,43 @@ def check_channel_shell_request(self, channel): def check_channel_direct_tcpip_request(self, chanid, origin, destination): return OPEN_SUCCEEDED - def check_channel_pty_request(self, channel, term, width, height, pixelwidth, pixelheight, modes): + def check_channel_pty_request( + self, channel, term, width, height, pixelwidth, pixelheight, modes + ): return True def ConnectionHandle(client, priv): with suppress(Exception): t = Transport(client) ip, port = client.getpeername() - _q_s.logs.info({'server': 'ssh_server', 'action': 'connection', 'src_ip': ip, 'src_port': port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) - t.local_version = 'SSH-2.0-' + _q_s.mocking_server + _q_s.logs.info( + { + "server": "ssh_server", + "action": "connection", + "src_ip": ip, + "src_port": port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) + t.local_version = "SSH-2.0-" + _q_s.mocking_server t.add_server_key(RSAKey(file_obj=StringIO(priv))) sshhandle = SSHHandle(ip, port) t.start_server(server=sshhandle) conn = t.accept(30) if "interactive" in _q_s.options and conn is not None: - conn.send("Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.10.60.1-microsoft-standard-WSL2 x86_64)\r\n\r\n") + conn.send( + "Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.10.60.1-microsoft-standard-WSL2 x86_64)\r\n\r\n" + ) current_time = time() while True and time() < current_time + 10: conn.send("/$ ") line = "" - while not line.endswith("\x0d") and not line.endswith("\x0a") and time() < current_time + 10: + while ( + not line.endswith("\x0d") + and not line.endswith("\x0a") + and time() < current_time + 10 + ): conn.settimeout(10) recv = conn.recv(1).decode() conn.settimeout(None) @@ -139,9 +233,21 @@ def ConnectionHandle(client, priv): conn.send(recv) line += recv line = line.rstrip() - _q_s.logs.info({'server': 'ssh_server', 'action': 'interactive', 'src_ip': ip, 'src_port': port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, "data": {"command": line}}) + _q_s.logs.info( + { + "server": "ssh_server", + "action": "interactive", + "src_ip": ip, + "src_port": port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "data": {"command": line}, + } + ) if line == "ls": - conn.send("\r\nbin cdrom etc lib lib64 lost+found mnt proc run snap swapfile tmp var boot dev home lib32 libx32 media opt root sbin srv sys usr\r\n") + conn.send( + "\r\nbin cdrom etc lib lib64 lost+found mnt proc run snap swapfile tmp var boot dev home lib32 libx32 media opt root sbin srv sys usr\r\n" + ) elif line == "pwd": conn.send("\r\n/\r\n") elif line == "whoami": @@ -149,7 +255,7 @@ def ConnectionHandle(client, priv): elif line == "exit": break else: - conn.send("\r\n{}: command not found\r\n".format(line)) + conn.send(f"\r\n{line}: command not found\r\n") with suppress(Exception): sshhandle.event.wait(2) with suppress(Exception): @@ -165,10 +271,16 @@ def ConnectionHandle(client, priv): while True: with suppress(Exception): client, addr = sock.accept() - start_new_thread(ConnectionHandle, (client, priv,)) + start_new_thread( + ConnectionHandle, + ( + client, + priv, + ), + ) def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -180,13 +292,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' + status = "success" - self.logs.info({'server': 'ssh_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) + self.logs.info( + { + "server": "ssh_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) - if status == 'success': + if status == "success": return True else: self.kill_server() @@ -195,26 +339,36 @@ def run_server(self, process=False, auto=False): self.ssh_server_main() def close_port(self): - ret = close_port_wrapper('ssh_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("ssh_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('ssh_server', self.uuid, self.process) + ret = kill_server_wrapper("ssh_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): from paramiko import SSHClient, AutoAddPolicy + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password ssh = SSHClient() - ssh.set_missing_host_key_policy(AutoAddPolicy()) # if you have default ones, remove them before using this.. + ssh.set_missing_host_key_policy( + AutoAddPolicy() + ) # if you have default ones, remove them before using this.. ssh.connect(_ip, port=_port, username=_username, password=_password) -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qsshserver = QSSHServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qsshserver = QSSHServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qsshserver.run_server() diff --git a/honeypots/telnet_server.py b/honeypots/telnet_server.py index 1dd5a1a..16b12aa 100644 --- a/honeypots/telnet_server.py +++ b/honeypots/telnet_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.conch.telnet import TelnetProtocol, TelnetTransport from twisted.internet.protocol import Factory @@ -19,28 +20,54 @@ from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QTelnetServer(): +class QTelnetServer: def __init__(self, **kwargs): self.auto_disabled = None - self.random_servers = ['Ubuntu 18.04 LTS', 'Ubuntu 16.04.3 LTS', 'Welcome to Microsoft Telnet Server.'] + self.random_servers = [ + "Ubuntu 18.04 LTS", + "Ubuntu 16.04.3 LTS", + "Welcome to Microsoft Telnet Server.", + ] self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 23 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 23 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) def telent_server_main(self): @@ -61,26 +88,47 @@ def connectionMade(self): self._state = None self._user = None self._pass = None - self.transport.write(b'PC login: ') - self._state = b'Username' - _q_s.logs.info({'server': 'telnet_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + self.transport.write(b"PC login: ") + self._state = b"Username" + _q_s.logs.info( + { + "server": "telnet_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def dataReceived(self, data): data = data.strip() - if self._state == b'Username': + if self._state == b"Username": self._user = data - self._state = b'Password' - self.transport.write(b'Password: ') - elif self._state == b'Password': + self._state = b"Password" + self.transport.write(b"Password: ") + elif self._state == b"Password": username = self.check_bytes(self._user) password = self.check_bytes(data) - status = 'failed' + status = "failed" # may need decode if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' - _q_s.logs.info({'server': 'telnet_server', 'action': 'login', 'status': status, 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + status = "success" + _q_s.logs.info( + { + "server": "telnet_server", + "action": "login", + "status": status, + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) self.transport.loseConnection() else: self.transport.loseConnection() @@ -96,7 +144,7 @@ def connectionLost(self, reason): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -108,13 +156,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'telnet_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "telnet_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -123,31 +203,39 @@ def run_server(self, process=False, auto=False): self.telent_server_main() def close_port(self): - ret = close_port_wrapper('telnet_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("telnet_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('telnet_server', self.uuid, self.process) + ret = kill_server_wrapper("telnet_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): with suppress(Exception): from telnetlib import Telnet as TTelnet + _ip = ip or self.ip _port = port or self.port _username = username or self.username _password = password or self.password - _username = _username.encode('utf-8') - _password = _password.encode('utf-8') + _username = _username.encode("utf-8") + _password = _password.encode("utf-8") t = TTelnet(_ip, _port) - t.read_until(b'login: ') - t.write(_username + b'\n') - t.read_until(b'Password: ') - t.write(_password + b'\n') + t.read_until(b"login: ") + t.write(_username + b"\n") + t.read_until(b"Password: ") + t.write(_password + b"\n") -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qtelnetserver = QTelnetServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qtelnetserver = QTelnetServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qtelnetserver.run_server() diff --git a/honeypots/testing.py b/honeypots/testing.py index 32add94..ac362ac 100644 --- a/honeypots/testing.py +++ b/honeypots/testing.py @@ -1,10 +1,11 @@ import honeypots from time import sleep from pkg_resources import get_distribution + honeypots.clean_all() -print("Version: ", get_distribution('honeypots').version) +print("Version: ", get_distribution("honeypots").version) for server, cls in honeypots.__dict__.items(): - if server.endswith('Server'): + if server.endswith("Server"): temp_server = cls(options="capture_commands") temp_server.run_server(process=True, auto=True) sleep(2) diff --git a/honeypots/vnc_server.py b/honeypots/vnc_server.py index 0cdf611..e2cfabc 100644 --- a/honeypots/vnc_server.py +++ b/honeypots/vnc_server.py @@ -1,4 +1,4 @@ -''' +""" // ------------------------------------------------------------- // author Giga // project qeeqbox/honeypots @@ -8,10 +8,11 @@ // ------------------------------------------------------------- // contributors list qeeqbox/honeypots/graphs/contributors // ------------------------------------------------------------- -''' +""" from warnings import filterwarnings -filterwarnings(action='ignore', module='.*OpenSSL.*') + +filterwarnings(action="ignore", module=".*OpenSSL.*") from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor @@ -20,45 +21,70 @@ from twisted.python import log as tlog from subprocess import Popen from os import path, getenv -#from vncdotool import api as vncapi -from honeypots.helper import close_port_wrapper, get_free_port, kill_server_wrapper, server_arguments, setup_logger, disable_logger, set_local_vars, check_if_server_is_running + +# from vncdotool import api as vncapi +from honeypots.helper import ( + close_port_wrapper, + get_free_port, + kill_server_wrapper, + server_arguments, + setup_logger, + disable_logger, + set_local_vars, + check_if_server_is_running, +) from uuid import uuid4 from contextlib import suppress -class QVNCServer(): +class QVNCServer: def __init__(self, **kwargs): self.auto_disabled = None - self.challenge = unhexlify('00000000901234567890123456789012') - self.words = ['test'] + self.challenge = unhexlify("00000000901234567890123456789012") + self.words = ["test"] self.process = None - self.uuid = 'honeypotslogger' + '_' + __class__.__name__ + '_' + str(uuid4())[:8] - self.config = kwargs.get('config', '') + self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8] + self.config = kwargs.get("config", "") if self.config: self.logs = setup_logger(__class__.__name__, self.uuid, self.config) set_local_vars(self, self.config) else: self.logs = setup_logger(__class__.__name__, self.uuid, None) - self.ip = kwargs.get('ip', None) or (hasattr(self, 'ip') and self.ip) or '0.0.0.0' - self.port = (kwargs.get('port', None) and int(kwargs.get('port', None))) or (hasattr(self, 'port') and self.port) or 5900 - self.username = kwargs.get('username', None) or (hasattr(self, 'username') and self.username) or 'test' - self.password = kwargs.get('password', None) or (hasattr(self, 'password') and self.password) or 'test' - self.options = kwargs.get('options', '') or (hasattr(self, 'options') and self.options) or getenv('HONEYPOTS_OPTIONS', '') or '' + self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0" + self.port = ( + (kwargs.get("port", None) and int(kwargs.get("port", None))) + or (hasattr(self, "port") and self.port) + or 5900 + ) + self.username = ( + kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test" + ) + self.password = ( + kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test" + ) + self.options = ( + kwargs.get("options", "") + or (hasattr(self, "options") and self.options) + or getenv("HONEYPOTS_OPTIONS", "") + or "" + ) disable_logger(1, tlog) - def load_words(self,): - with open(self.file_name, 'r') as file: + def load_words( + self, + ): + with open(self.file_name) as file: self.words = file.read().splitlines() def decode(self, c, r): with suppress(Exception): for word in self.words: temp = word - word = word.strip('\n').ljust(8, '\00')[:8] + word = word.strip("\n").ljust(8, "\00")[:8] rev_word = [] - for i in range(0, 8): - rev_word.append(chr(int('{:08b}'.format(ord(word[i]))[::-1], 2))) - output = DES.new(''.join(rev_word).encode('utf-8'), DES.MODE_ECB).encrypt(c) + for i in range(8): + rev_word.append(chr(int(f"{ord(word[i]):08b}"[::-1], 2))) + output = DES.new("".join(rev_word).encode("utf-8"), DES.MODE_ECB).encrypt(c) if output == r: return temp return None @@ -67,7 +93,6 @@ def vnc_server_main(self): _q_s = self class CustomVNCProtocol(Protocol): - _state = None def check_bytes(self, string): @@ -77,32 +102,53 @@ def check_bytes(self, string): return str(string) def connectionMade(self): - self.transport.write(b'RFB 003.008\n') + self.transport.write(b"RFB 003.008\n") self._state = 1 - _q_s.logs.info({'server': 'vnc_server', 'action': 'connection', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port}) + _q_s.logs.info( + { + "server": "vnc_server", + "action": "connection", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + } + ) def dataReceived(self, data): if self._state == 1: - if data == b'RFB 003.008\n': + if data == b"RFB 003.008\n": self._state = 2 - self.transport.write(unhexlify('0102')) + self.transport.write(unhexlify("0102")) elif self._state == 2: - if data == b'\x02': + if data == b"\x02": self._state = 3 self.transport.write(_q_s.challenge) elif self._state == 3: with suppress(Exception): username = self.check_bytes(_q_s.decode(_q_s.challenge, data.hex())) password = self.check_bytes(data) - status = 'failed' + status = "failed" # may need decode if username == _q_s.username and password == _q_s.password: username = _q_s.username password = _q_s.password - status = 'success' + status = "success" else: password = data.hex() - _q_s.logs.info({'server': 'vnc_server', 'action': 'login', status: 'failed', 'src_ip': self.transport.getPeer().host, 'src_port': self.transport.getPeer().port, 'dest_ip': _q_s.ip, 'dest_port': _q_s.port, 'username': username, 'password': password}) + _q_s.logs.info( + { + "server": "vnc_server", + "action": "login", + status: "failed", + "src_ip": self.transport.getPeer().host, + "src_port": self.transport.getPeer().port, + "dest_ip": _q_s.ip, + "dest_port": _q_s.port, + "username": username, + "password": password, + } + ) self.transport.loseConnection() else: self.transport.loseConnection() @@ -116,7 +162,7 @@ def connectionLost(self, reason): reactor.run() def run_server(self, process=False, auto=False): - status = 'error' + status = "error" run = False if process: if auto and not self.auto_disabled: @@ -128,13 +174,45 @@ def run_server(self, process=False, auto=False): run = True if run: - self.process = Popen(['python3', path.realpath(__file__), '--custom', '--ip', str(self.ip), '--port', str(self.port), '--username', str(self.username), '--password', str(self.password), '--options', str(self.options), '--config', str(self.config), '--uuid', str(self.uuid)]) + self.process = Popen( + [ + "python3", + path.realpath(__file__), + "--custom", + "--ip", + str(self.ip), + "--port", + str(self.port), + "--username", + str(self.username), + "--password", + str(self.password), + "--options", + str(self.options), + "--config", + str(self.config), + "--uuid", + str(self.uuid), + ] + ) if self.process.poll() is None and check_if_server_is_running(self.uuid): - status = 'success' - - self.logs.info({'server': 'vnc_server', 'action': 'process', 'status': status, 'src_ip': self.ip, 'src_port': self.port, 'username': self.username, 'password': self.password, 'dest_ip': self.ip, 'dest_port': self.port}) - - if status == 'success': + status = "success" + + self.logs.info( + { + "server": "vnc_server", + "action": "process", + "status": status, + "src_ip": self.ip, + "src_port": self.port, + "username": self.username, + "password": self.password, + "dest_ip": self.ip, + "dest_port": self.port, + } + ) + + if status == "success": return True else: self.kill_server() @@ -143,11 +221,11 @@ def run_server(self, process=False, auto=False): self.vnc_server_main() def close_port(self): - ret = close_port_wrapper('vnc_server', self.ip, self.port, self.logs) + ret = close_port_wrapper("vnc_server", self.ip, self.port, self.logs) return ret def kill_server(self): - ret = kill_server_wrapper('vnc_server', self.uuid, self.process) + ret = kill_server_wrapper("vnc_server", self.uuid, self.process) return ret def test_server(self, ip=None, port=None, username=None, password=None): @@ -156,13 +234,20 @@ def test_server(self, ip=None, port=None, username=None, password=None): port or self.port username or self.username password or self.password - #client = vncapi.connect('{}::{}'.format(self.ip, self.port), password=password) + # client = vncapi.connect('{}::{}'.format(self.ip, self.port), password=password) # client.captureScreen('screenshot.png') # client.disconnect() -if __name__ == '__main__': +if __name__ == "__main__": parsed = server_arguments() if parsed.docker or parsed.aws or parsed.custom: - qvncserver = QVNCServer(ip=parsed.ip, port=parsed.port, username=parsed.username, password=parsed.password, options=parsed.options, config=parsed.config) + qvncserver = QVNCServer( + ip=parsed.ip, + port=parsed.port, + username=parsed.username, + password=parsed.password, + options=parsed.options, + config=parsed.config, + ) qvncserver.run_server() diff --git a/tests/conftest.py b/tests/conftest.py index 2358328..582981e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -27,7 +27,7 @@ def config_for_testing(custom_config: dict) -> Iterator[Path]: yield config -@pytest.fixture +@pytest.fixture() def server_logs(request): custom_config = request.param.get("custom_config", {}) with config_for_testing(custom_config) as config_file: diff --git a/tests/test_http_proxy_server.py b/tests/test_http_proxy_server.py index f968134..4310925 100644 --- a/tests/test_http_proxy_server.py +++ b/tests/test_http_proxy_server.py @@ -30,7 +30,11 @@ def test_http_proxy_server(server_logs): sleep(1) # give the server some time to start - response = requests.get("http://example.com/", proxies={"http": f"http://{IP}:{PORT}"}, timeout=2) + response = requests.get( + "http://example.com/", + proxies={"http": f"http://{IP}:{PORT}"}, + timeout=2, + ) sleep(1) # give the server process some time to write logs diff --git a/tests/test_snmp_server.py b/tests/test_snmp_server.py index 2ad05c7..72af237 100644 --- a/tests/test_snmp_server.py +++ b/tests/test_snmp_server.py @@ -1,7 +1,15 @@ from __future__ import annotations import pytest -from pysnmp.hlapi import CommunityData, ContextData, getCmd, ObjectIdentity, ObjectType, SnmpEngine, UdpTransportTarget +from pysnmp.hlapi import ( + CommunityData, + ContextData, + getCmd, + ObjectIdentity, + ObjectType, + SnmpEngine, + UdpTransportTarget, +) from honeypots import QSNMPServer from .utils import ( @@ -35,4 +43,8 @@ def test_snmp_server(server_logs): assert_connect_is_logged(connect, PORT) assert query["action"] == "query" - assert query["data"] == {"community": "public", "oids": "1.3.6.1.4.1.9.9.618.1.4.1.0", "version": "1"} + assert query["data"] == { + "community": "public", + "oids": "1.3.6.1.4.1.9.9.618.1.4.1.0", + "version": "1", + }