def check(language): """ check if framework compatible with the OS Args: language: language Returns: True if compatible otherwise None """ # from core.color import finish from core.alert import messages if "linux" in os_name() or "darwin" in os_name(): pass # os.system("clear") elif "win32" == os_name() or "win64" == os_name(): # if language != "en": # from core.color import finish # from core.alert import error # error("please use english language on windows!") # finish() # sys.exit(1) # os.system("cls") pass else: exit_failure(messages(language, "error_platform")) if version() is 2 or version() is 3: pass else: exit_failure(messages(language, "python_version_error")) logo() return True
def update_language(argv_options): """ Update language for messages Args: argv_options """ if argv_options.language not in load_messages().languages_list: exit_failure("Invalid language code. Available options are " + ", ".join(load_messages().languages_list))
def check(language): """ check if framework compatible with the OS Args: language: language Returns: True if compatible otherwise None """ from core.alert import messages if os_name() not in ["linux", "darwin", "win32", "win64"]: exit_failure(messages(language, "error_platform")) if version() == 2 or version() == 3: pass else: exit_failure(messages(language, "python_version_error")) logo() return True
def check_for_requirements(start_api_server): """ check if requirements exist Returns: True if exist otherwise False """ # TODO : Fix the cyclic dependency later from config import api_configuration from core.messages import load_messages messages = load_messages().message_contents # check external required modules api_config = api_configuration() external_modules = open(os.path.join(os.getcwd(), 'requirements.txt'), 'r').read().split('\n') for module_name in external_modules: try: __import__( module_name.split('==')[0] if 'library_name=' not in module_name else module_name.split('library_name=')[1].split( )[0]) except Exception: exit_failure("pip3 install -r requirements.txt ---> " + module_name + " not installed!") # check elasticsearch try: connection = elasticsearch.Elasticsearch( api_config["api_database"], http_auth=api_config["api_database"]) connection.indices.get_alias("*") except Exception: exit_failure(messages["elasticsearch_not_found"]) # check if its honeypot server not api server if not start_api_server: # check docker try: subprocess.check_output(["docker", "--help"], stderr=subprocess.PIPE) except Exception: exit_failure(messages["cannot_communicate_with_docker"]) # check for commandline requirements commands = { 'tshark': which('tshark'), 'ps': which('ps'), 'grep': which('grep'), 'kill': which('kill') } for command in commands: if commands[command] is None: exit_failure(messages["install_tools"] + "{0}".format(json.dumps(commands, indent=4))) return True
def start_api_server(): """ start API server Returns: True """ # Starting the API my_api_configuration = api_configuration() api_access_key = my_api_configuration["api_access_key"] api_access_without_key = my_api_configuration["api_access_without_key"] write_to_api_console(" * API access key: {0}\n".format( api_access_key if not api_access_without_key else "NOT REQUIRED!")) app.config["OWASP_HONEYPOT_CONFIG"] = { "api_access_key": api_access_key, "api_client_white_list": my_api_configuration["api_client_white_list"]["enabled"], "api_client_white_list_ips": my_api_configuration["api_client_white_list"]["ips"], "api_access_log": my_api_configuration["api_access_log"]["enabled"], "api_access_log_filename": my_api_configuration["api_access_log"]["filename"], "api_access_without_key": api_access_without_key, **user_configuration() } app.register_blueprint(documentation_settings) try: app.run(host=my_api_configuration["api_host"], port=my_api_configuration["api_port"], debug=my_api_configuration["api_debug_mode"], threaded=True) except Exception as e: exit_failure(str(e)) return True
def check_for_requirements(start_api_server): """ check if requirements exist Returns: True if exist otherwise False """ from config import api_configuration # check external required modules api_config = api_configuration() connection_timeout = api_config["api_database_connection_timeout"] try: import pymongo import netaddr import flask del netaddr del flask except Exception: exit_failure("pip install -r requirements.txt") # check mongodb try: connection = pymongo.MongoClient( api_config["api_database"], serverSelectionTimeoutMS=connection_timeout) connection.list_database_names() except Exception: exit_failure("cannot connect to mongodb") # check if its honeypot server not api server if not start_api_server: # check docker try: subprocess.check_output(["docker", "--help"], stderr=subprocess.PIPE) except Exception: exit_failure( "cannot communicate with docker, please install and start the docker service!" ) # check tshark try: subprocess.check_output(["tshark", "--help"], stderr=subprocess.PIPE) except Exception: exit_failure("please install tshark first!") return True
def load_honeypot_engine(): """ load OHP Engine Returns: True """ # print logo logo() # parse argv parser, argv_options = argv_parser() ######################################### # argv rules apply ######################################### # check help menu if argv_options.show_help_menu: parser.print_help() exit_success() # check for requirements before start check_for_requirements(argv_options.start_api_server) # check api server flag if argv_options.start_api_server: start_api_server() exit_success() # check selected modules if argv_options.selected_modules: selected_modules = list(set(argv_options.selected_modules.rsplit(","))) if "all" in selected_modules: selected_modules = load_all_modules() if "" in selected_modules: selected_modules.remove("") # if selected modules are zero if not len(selected_modules): exit_failure(messages("en", "zero_module_selected")) # if module not found for module in selected_modules: if module not in load_all_modules(): exit_failure(messages("en", "module_not_found").format(module)) # check excluded modules if argv_options.excluded_modules: excluded_modules = list(set(argv_options.excluded_modules.rsplit(","))) if "all" in excluded_modules: exit_failure("you cannot exclude all modules") if "" in excluded_modules: excluded_modules.remove("") # remove excluded modules for module in excluded_modules: if module not in load_all_modules(): exit_failure(messages("en", "module_not_found").format(module)) # ignore if module not selected, it will remove anyway try: selected_modules.remove(module) except Exception as _: del _ # if selected modules are zero if not len(selected_modules): exit_failure(messages("en", "zero_module_selected")) virtual_machine_container_reset_factory_time_seconds = argv_options. \ virtual_machine_container_reset_factory_time_seconds run_as_test = argv_options.run_as_test ######################################### # argv rules apply ######################################### # build configuration based on selected modules configuration = honeypot_configuration_builder(selected_modules) info(messages("en", "honeypot_started")) info(messages("en", "loading_modules").format(", ".join(selected_modules))) # check for conflict in real machine ports and pick new ports info("checking for conflicts in ports") configuration = conflict_ports(configuration) # stop old containers (in case they are not stopped) stop_containers(configuration) # remove old containers (in case they are not updated) remove_old_containers(configuration) # remove old images (in case they are not updated) remove_old_images(configuration) # create new images based on selected modules create_new_images(configuration) # create OWASP Honeypot networks in case not exist create_ohp_networks() # start containers based on selected modules configuration = start_containers(configuration) # start network monitoring thread new_network_events_thread = Thread(target=new_network_events, args=(configuration, ), name="new_network_events_thread") new_network_events_thread.start() info("all selected modules started: {0}".format( ", ".join(selected_modules))) bulk_events_thread = Thread(target=insert_bulk_events_from_thread, args=(), name="insert_events_in_bulk_thread") bulk_events_thread.start() # run module processors run_modules_processors(configuration) # check if it's not a test if not run_as_test: # wait forever! in case user can send ctrl + c to interrupt wait_until_interrupt( virtual_machine_container_reset_factory_time_seconds, configuration, new_network_events_thread) # kill the network events thread terminate_thread(new_network_events_thread) terminate_thread(bulk_events_thread) insert_events_in_bulk( ) # if in case any events that were not inserted from thread # stop created containers stop_containers(configuration) # stop module processor stop_modules_processors(configuration) # remove created containers remove_old_containers(configuration) # remove created images remove_old_images(configuration) # remove_tmp_directories() error: access denied! # kill all missed threads for thread in threading.enumerate()[1:]: terminate_thread(thread, False) info("finished.") # reset cmd/terminal color finish() return True
def new_network_events(configuration): """ get and submit new network events Args: configuration: user final configuration Returns: True """ info("new_network_events thread started") # honeypot ports honeypot_ports = [] for selected_module in configuration: honeypot_ports.append( configuration[selected_module]["real_machine_port_number"]) # set machine name machine_name = network_configuration()["real_machine_identifier_name"] # get ip addresses virtual_machine_ip_addresses = [ configuration[selected_module]["ip_address"] for selected_module in configuration ] # ignore vm ips + ips in config.py ignore_ip_addresses = network_configuration()["ignore_real_machine_ip_addresses"] \ if network_configuration()["ignore_real_machine_ip_address"] else [] + virtual_machine_ip_addresses ignore_ip_addresses.extend(get_gateway_ip_addresses(configuration)) # ignore ports ignore_ports = network_configuration()["ignore_real_machine_ports"] # start tshark to capture network # tshark -Y "ip.dst != 192.168.1.1" -T fields -e ip.dst -e tcp.srcport run_tshark = ["tshark", "-l", "-V"] run_tshark.extend(ignore_ip_addresses_rule_generator(ignore_ip_addresses)) run_tshark.extend( ["-T", "fields", "-e", "ip.dst", "-e", "tcp.srcport", "-ni", "any"]) process = subprocess.Popen(run_tshark, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait 3 seconds if process terminated? time.sleep(3) if process.poll() is not None: exit_failure("tshark couldn't capture network, maybe run as root!") # todo: replace tshark with python port sniffing - e.g https://www.binarytides.com/python-packet-sniffer-code-linux/ # it will be easier to apply filters and analysis packets with python # if it requires to be run as root, please add a uid checker in framework startup # readline timeout bug fix: https://stackoverflow.com/a/10759061 pull_object = select.poll() pull_object.register(process.stdout, select.POLLIN) # while True, read tshark output try: while True: if pull_object.poll(0): line = process.stdout.readline() # check if new IP and Port printed if len(line) > 0: # split the IP and Port try: ip, port = str(line.rsplit()[0].decode()), int( line.rsplit()[1]) except Exception as _: ip, port = None, None # check if event shows an IP if (netaddr.valid_ipv4(ip) or netaddr.valid_ipv6(ip)) \ and ip not in ignore_ip_addresses \ and port not in ignore_ports: # ignored ip addresses and ports in python - fix later # check if the port is in selected module if port in honeypot_ports: insert_selected_modules_network_event( ip, port, selected_module, machine_name) else: insert_other_network_event(ip, port, machine_name) time.sleep(0.001) # todo: is sleep(0.001) fastest/best? it means it could get 1000 packets per second (maximum) from tshark # how could we prevent the DDoS attacks in here and avoid submitting in MongoDB? should we? except Exception as _: del _ return True
def load_honeypot_engine(): """ load OHP Engine Returns: True """ # print logo logo() # parse argv parser, argv_options = argv_parser() # check the language if argv_options.language: update_language(argv_options) ######################################### # argv rules apply ######################################### # check help menu if argv_options.show_help_menu: parser.print_help() exit_success() # check for requirements before start check_for_requirements(argv_options.start_api_server) # create indices before server start create_indices() # check api server flag if argv_options.start_api_server: start_api_server() exit_success() # Check if the script is running with sudo if not os.geteuid() == 0: exit_failure(messages['script_must_run_as_root']) # Check timeout value if provided if argv_options.timeout_value < 1: exit_failure(messages["timeout_error"]) # check selected modules if argv_options.selected_modules: selected_modules = list(set(argv_options.selected_modules.rsplit(","))) if "all" in selected_modules: selected_modules = load_all_modules() if "" in selected_modules: selected_modules.remove("") # if selected modules are zero if not len(selected_modules): exit_failure(messages["no_module_selected_error"]) # if module not found for module in selected_modules: if module not in load_all_modules(): exit_failure("module {0} not found!".format(module)) # check excluded modules if argv_options.excluded_modules: excluded_modules = list(set(argv_options.excluded_modules.rsplit(","))) if "all" in excluded_modules: exit_failure(messages["all_modules_excluded_error"]) if "" in excluded_modules: excluded_modules.remove("") # remove excluded modules for module in excluded_modules: if module not in load_all_modules(): exit_failure("module {0} not found!".format(module)) # ignore if module not selected, it will remove anyway try: selected_modules.remove(module) except Exception: pass # if selected modules are zero if not len(selected_modules): exit_failure(messages["no_module_selected_error"]) virtual_machine_container_reset_factory_time_seconds = argv_options. \ virtual_machine_container_reset_factory_time_seconds run_as_test = argv_options.run_as_test ######################################### # argv rules apply ######################################### # build configuration based on selected modules configuration = honeypot_configuration_builder(selected_modules) # Set network configuration network_config = set_network_configuration(argv_options) info(messages["start_message"]) info(messages["loading_modules"].format(", ".join(selected_modules))) # check for conflict in real machine ports and pick new ports info(messages["check_for_port_conflicts"]) configuration = conflict_ports(configuration) # stop old containers (in case they are not stopped) stop_containers(configuration) # remove old containers (in case they are not updated) remove_old_containers(configuration) # remove old images (in case they are not updated) remove_old_images(configuration) # create new images based on selected modules create_new_images(configuration) # create OWASP Honeypot networks in case not exist create_ohp_networks() # start containers based on selected modules configuration = start_containers(configuration) # network capture process mp.set_start_method('spawn') # Event queues honeypot_events_queue = mp.Queue() network_events_queue = mp.Queue() # start a new process for network capture network_traffic_capture_process = mp.Process( target=network_traffic_capture, args=( configuration, honeypot_events_queue, network_events_queue, network_config, ), name="network_traffic_capture_process") network_traffic_capture_process.start() info(messages["selected_modules_started"].format( ", ".join(selected_modules))) # start a thread to push events to database regularly bulk_events_thread = Thread(target=push_events_to_database_from_thread, args=( honeypot_events_queue, network_events_queue, ), name="insert_events_in_bulk_thread") bulk_events_thread.start() # run module processors run_modules_processors(configuration) # wait forever! in case user can send ctrl + c to interrupt exit_flag = wait_until_interrupt( virtual_machine_container_reset_factory_time_seconds, configuration, network_traffic_capture_process, run_as_test) # killed the network traffic capture process by ctrl + c... waiting to end. info(messages["killing_capture_process"]) if run_as_test: network_traffic_capture_process.terminate() # without ci it will be terminate after a few seconds, it needs to kill the tshark and update pcap file collection network_traffic_capture_process.join() # if in case any events that were not inserted from thread push_events_queues_to_database(honeypot_events_queue, network_events_queue) # Kill bulk events thread terminate_thread(bulk_events_thread) # stop created containers stop_containers(configuration) # stop module processor stop_modules_processors(configuration) # remove created containers remove_old_containers(configuration) # remove created images remove_old_images(configuration) # remove_tmp_directories() error: access denied! # kill all missed threads for thread in threading.enumerate()[1:]: terminate_thread(thread, False) info(messages["finished"]) # reset cmd/terminal color reset_cmd_color() return exit_flag