diff --git a/README.md b/README.md index 9266162..a0c9b27 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,7 @@ The only thing you need to do is create config file. You can find template in ro In config file you are able to specify following options: - **fixed_url_attributes** -> if you want to set some attributes to static values - **headers** -> headers which are sent by each request (useful for AUTH token insertion) -- **polling_interval** -> interval between checks for response (in seconds) -- **response_timeout** -> maximum amount of time waiting for response (in seconds) +- **receive_timeout** -> maximum amount of time waiting for response (in seconds) - **reporting_interval** -> progress reporting interval (in seconds) - **http_fuzzing** -> boolean value for enabling / disabling fuzzing of HTTP protocol - **skipping_endpoints_keywords** [list of string keywords] -> endpoints containing any keyword in it from this list will be skipped (can be used for skipping auth/logout endpoints) diff --git a/config_example.json b/config_example.json index 7856d1f..599eacc 100644 --- a/config_example.json +++ b/config_example.json @@ -10,8 +10,7 @@ "reporting_interval": 60, "http_fuzzing": true, "skipping_endpoints_keywords": ["logout", "auth"], - "polling_interval": 0.005, - "response_timeout": 2, + "receive_timeout": 2, "startup_command": ["python", "C:\\server\\httpd.py"], "target": { "hostname": "target_hostname", diff --git a/fuzzer/src/configuration_manager.py b/fuzzer/src/configuration_manager.py index 48df146..a5c7256 100644 --- a/fuzzer/src/configuration_manager.py +++ b/fuzzer/src/configuration_manager.py @@ -38,6 +38,10 @@ class ConfigurationManager: def _get_payloads_to_json_primitives_mapping(): return ConfigurationManager.config["payloads_to_json_primitives_mapping"] if "payloads_to_json_primitives_mapping" in ConfigurationManager.config else None + @staticmethod + def get_receive_timeout(): + return ConfigurationManager.config["receive_timeout"] + @staticmethod def get_reporting_interval(): return ConfigurationManager.config["reporting_interval"] @@ -56,16 +60,10 @@ class ConfigurationManager: def _config_validation(self): reporting_interval: Union[int, float] = self.config["reporting_interval"] - response_timeout: Union[int, float] = self.config["response_timeout"] - polling_interval: Union[int, float] = self.config["polling_interval"] + receive_timeout: Union[int, float] = self.config["receive_timeout"] http_fuzzing: bool = self.config["http_fuzzing"] - if response_timeout <= polling_interval or polling_interval <= 0: - print("Wrong timeout and polling interval. Timeout has to be greater than polling interval" + - " and polling interval has to be greater than zero.") - sys.exit(-1) - - if reporting_interval <= 0 or reporting_interval < response_timeout: + if reporting_interval <= 0 or reporting_interval < receive_timeout: print("Wrong reporting interval. Should be smaller than response_timeout.") sys.exit(-1) diff --git a/fuzzer/src/fuzzer.py b/fuzzer/src/fuzzer.py index d980641..de283dd 100644 --- a/fuzzer/src/fuzzer.py +++ b/fuzzer/src/fuzzer.py @@ -1,6 +1,5 @@ import sys import ssl -import os from typing import List from boofuzz import Session, Target, SocketConnection, s_get, pedrpc from progress_reporter import report_progress @@ -38,19 +37,14 @@ class Fuzzer: ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE - # Workaround for issue with TLS with Boofuzz on Windows - # https://github.com/jtpereyda/boofuzz/pull/300#issuecomment-548108378 - send_and_rcv_timeout = 5.0 - if os.name == 'nt': - send_and_rcv_timeout = 5000.0 + recv_timeout = ConfigurationManager.get_receive_timeout() remote_connection = SocketConnection( target_config["hostname"], target_config["port"], proto=self._protocol, sslcontext=ssl_context, - send_timeout=send_and_rcv_timeout, - recv_timeout=send_and_rcv_timeout + recv_timeout=recv_timeout ) if startup_command: process_monitor = pedrpc.Client(target_config["hostname"], 26002) diff --git a/fuzzer/src/post_test_case_callback.py b/fuzzer/src/post_test_case_callback.py index 02794f6..202e134 100644 --- a/fuzzer/src/post_test_case_callback.py +++ b/fuzzer/src/post_test_case_callback.py @@ -1,43 +1,25 @@ -import time -import threading import json from http.client import HTTPResponse from boofuzz import exception -from configuration_manager import ConfigurationManager from fake_socket import get_response_object class PostTestCaseCallback(object): - timeout_flag: bool = False - - @staticmethod - def set_timeout(): - PostTestCaseCallback.timeout_flag = True + timeout_message = "Timeout or closed connection" @staticmethod def post_test_callback(target, fuzz_data_logger, session, sock, *args, **kwargs): fuzz_data_logger.log_info("Mutation: " + session.fuzz_node.mutant._rendered.decode('utf-8', errors='ignore')) fuzz_data_logger.log_info("Original value: " + session.fuzz_node.mutant.original_value.decode('utf-8', errors='ignore')) - response_timeout = ConfigurationManager.config["response_timeout"] - polling_interval = ConfigurationManager.config["polling_interval"] - - timer = threading.Timer(response_timeout, PostTestCaseCallback.set_timeout) - - response_string = None - PostTestCaseCallback.timeout_flag = False - timer.start() - while not PostTestCaseCallback.timeout_flag: - try: - response_string = target.recv() - timer.cancel() - break - except exception.BoofuzzTargetConnectionReset: - time.sleep(polling_interval) - continue + try: + response_string = target.recv() + except exception.BoofuzzTargetConnectionReset: + fuzz_data_logger.log_fail(PostTestCaseCallback.timeout_message) + return if not response_string: - fuzz_data_logger.log_fail("Timeout or closed connection") + fuzz_data_logger.log_fail(PostTestCaseCallback.timeout_message) return response = get_response_object(response_string) diff --git a/fuzzer/src/progress_reporter.py b/fuzzer/src/progress_reporter.py index 2a253da..05f5a8e 100644 --- a/fuzzer/src/progress_reporter.py +++ b/fuzzer/src/progress_reporter.py @@ -5,13 +5,6 @@ import datetime from configuration_manager import ConfigurationManager DID_FUZZING_STARTED_CHECKS_TIME_INTERVAL_IN_SECONDS = 5 -HANGED_TIMEOUT = 120 - - -def close_testing_and_kill_fuzzer(junit_logger, session): - if is_fuzzing_hanged(session): - junit_logger.close_test() - os._exit(1) def report_progress(session, junit_logger): @@ -20,7 +13,12 @@ def report_progress(session, junit_logger): if is_fuzzing_hanged(session): message = create_hanged_message(session) print(message, file=sys.stderr) - threading.Timer(HANGED_TIMEOUT, close_testing_and_kill_fuzzer, [junit_logger, session]).start() + try: + junit_logger.close_test() + except: + pass + finally: + os._exit(1) if is_fuzzing_still_in_progress(session): plan_another_report(session, junit_logger, ConfigurationManager.get_reporting_interval()) diff --git a/tests/localhost_config.json b/tests/localhost_config.json index 8ec82ad..d98ba57 100644 --- a/tests/localhost_config.json +++ b/tests/localhost_config.json @@ -1,8 +1,7 @@ { "fixed_url_attributes": {}, "headers": {}, - "polling_interval": 0.05, - "response_timeout": 1, + "receive_timeout": 1, "reporting_interval": 10, "skipping_endpoints_keywords": [], "http_fuzzing": false,