diff --git a/fuzzer/src/configuration_manager.py b/fuzzer/src/configuration_manager.py index cde6cb4..1944be5 100644 --- a/fuzzer/src/configuration_manager.py +++ b/fuzzer/src/configuration_manager.py @@ -1,76 +1,76 @@ -import sys -import json -from typing import Union, List - - -class ConfigurationManager: - config = None - - def __init__(self, config_file_pointer): - ConfigurationManager.config = json.load(config_file_pointer) - self._config_validation() - - @staticmethod - def get_startup_command(): - return ConfigurationManager.config["startup_command"] if "startup_command" in ConfigurationManager.config else None - - @staticmethod - def get_payloads_folders_for_boolean_json_primitive() -> Union[List, None]: - return ConfigurationManager._get_payloads_folders_for_specific_json_primitive("boolean") - - @staticmethod - def get_payloads_folders_for_number_json_primitive() -> Union[List, None]: - return ConfigurationManager._get_payloads_folders_for_specific_json_primitive("number") - - @staticmethod - def get_payloads_folders_for_string_json_primitive() -> Union[List, None]: - return ConfigurationManager._get_payloads_folders_for_specific_json_primitive("string") - - @staticmethod - def _get_payloads_folders_for_specific_json_primitive(json_type: str) -> Union[List, None]: - mapping = ConfigurationManager._get_payloads_to_json_primitives_mapping() - if mapping: - return mapping[json_type] if json_type in mapping else None - else: - return None - - @staticmethod - 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"] - - @staticmethod - def get_keywords_for_endpoints_skipping() -> List: - return ConfigurationManager.config["skipping_endpoints_keywords"] - - @staticmethod - def get_target(): - return ConfigurationManager.config["target"] - - @staticmethod - def is_http_fuzzing_allowed(): - return ConfigurationManager.config["http_fuzzing"] - - def _config_validation(self): - reporting_interval: Union[int, float] = self.config["reporting_interval"] - receive_timeout: Union[int, float] = self.config["receive_timeout"] - http_fuzzing: bool = self.config["http_fuzzing"] - - if reporting_interval <= 0 or reporting_interval < receive_timeout: - print("Wrong reporting interval. Should be smaller than receive_timeout.") - sys.exit(-1) - - if "target" not in ConfigurationManager.config: - print("Missing configuration of target.") - sys.exit(-1) - - if http_fuzzing is None: - print("Missing flag for enabling / disabling HTTP fuzzing.") - sys.exit(-1) +import sys +import json +from typing import Union, List + + +class ConfigurationManager: + config = None + + def __init__(self, config_file_pointer): + ConfigurationManager.config = json.load(config_file_pointer) + self._config_validation() + + @staticmethod + def get_startup_command(): + return ConfigurationManager.config["startup_command"] if "startup_command" in ConfigurationManager.config else None + + @staticmethod + def get_payloads_folders_for_boolean_json_primitive() -> Union[List, None]: + return ConfigurationManager._get_payloads_folders_for_specific_json_primitive("boolean") + + @staticmethod + def get_payloads_folders_for_number_json_primitive() -> Union[List, None]: + return ConfigurationManager._get_payloads_folders_for_specific_json_primitive("number") + + @staticmethod + def get_payloads_folders_for_string_json_primitive() -> Union[List, None]: + return ConfigurationManager._get_payloads_folders_for_specific_json_primitive("string") + + @staticmethod + def _get_payloads_folders_for_specific_json_primitive(json_type: str) -> Union[List, None]: + mapping = ConfigurationManager._get_payloads_to_json_primitives_mapping() + if mapping: + return mapping[json_type] if json_type in mapping else None + else: + return None + + @staticmethod + 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"] + + @staticmethod + def get_keywords_for_endpoints_skipping() -> List: + return ConfigurationManager.config["skipping_endpoints_keywords"] + + @staticmethod + def get_target(): + return ConfigurationManager.config["target"] + + @staticmethod + def is_http_fuzzing_allowed(): + return ConfigurationManager.config["http_fuzzing"] + + def _config_validation(self): + reporting_interval: Union[int, float] = self.config["reporting_interval"] + receive_timeout: Union[int, float] = self.config["receive_timeout"] + http_fuzzing: bool = self.config["http_fuzzing"] + + if reporting_interval <= 0 or reporting_interval < receive_timeout: + print("Wrong reporting interval. Should be smaller than receive_timeout.") + sys.exit(2) + + if "target" not in ConfigurationManager.config: + print("Missing configuration of target.") + sys.exit(2) + + if http_fuzzing is None: + print("Missing flag for enabling / disabling HTTP fuzzing.") + sys.exit(2) diff --git a/fuzzer/src/fuzzer.py b/fuzzer/src/fuzzer.py index de283dd..72ce5a9 100644 --- a/fuzzer/src/fuzzer.py +++ b/fuzzer/src/fuzzer.py @@ -85,3 +85,6 @@ class Fuzzer: def fuzz(self): report_progress(self._session, self._junit_logger) self._session.fuzz() + + def was_there_any_failure(self): + return self._junit_logger.was_there_any_failure diff --git a/fuzzer/src/junit_logger.py b/fuzzer/src/junit_logger.py index 6366e2a..f23d12c 100644 --- a/fuzzer/src/junit_logger.py +++ b/fuzzer/src/junit_logger.py @@ -31,6 +31,8 @@ class JUnitLogger(ifuzz_logger_backend.IFuzzLoggerBackend): self._default_value = None self._mutant_value = None + self.was_there_any_failure: bool = False + def open_test_step(self, description): skipped_count = 0 for skipped_test_case_message_regex in self.SKIPPED_TEST_CASE_MESSAGES_REGEX: @@ -48,6 +50,7 @@ class JUnitLogger(ifuzz_logger_backend.IFuzzLoggerBackend): def log_error(self, description): self._error = description + self.was_there_any_failure = True def log_recv(self, data): self._received_bytes = helpers.hex_str(data) @@ -71,6 +74,7 @@ class JUnitLogger(ifuzz_logger_backend.IFuzzLoggerBackend): def log_fail(self, description=""): self._failure = description + self.was_there_any_failure = True def log_pass(self, description=""): pass diff --git a/fuzzer/src/progress_reporter.py b/fuzzer/src/progress_reporter.py index 05f5a8e..454b9bf 100644 --- a/fuzzer/src/progress_reporter.py +++ b/fuzzer/src/progress_reporter.py @@ -18,7 +18,7 @@ def report_progress(session, junit_logger): except: pass finally: - os._exit(1) + os._exit(2) if is_fuzzing_still_in_progress(session): plan_another_report(session, junit_logger, ConfigurationManager.get_reporting_interval()) diff --git a/fuzzer/src/wapifuzz.py b/fuzzer/src/wapifuzz.py index 7284033..9558e09 100644 --- a/fuzzer/src/wapifuzz.py +++ b/fuzzer/src/wapifuzz.py @@ -36,7 +36,12 @@ def main(): fuzzer = Fuzzer(endpoints, text_logger, junit_logger, protocol) fuzzer.fuzz() + return fuzzer.was_there_any_failure() if __name__ == '__main__': - main() + was_there_any_failure: bool = main() + if was_there_any_failure: + exit(1) + else: + exit(0) diff --git a/run.ps1 b/run.ps1 index 3b56d68..55a0975 100644 --- a/run.ps1 +++ b/run.ps1 @@ -66,10 +66,10 @@ pip install --upgrade pip Write-Host "Installing specific dependencies" pip install git+https://github.com/jtpereyda/boofuzz.git pip install junit-xml - Write-Host "Starting fuzz testing" python ./fuzzer/src/wapifuzz.py ${config} ${API_REQUESTS_JSON} ${JUNIT_TEST_REPORT} ${payloads} > $FUZZER_LOG -if(-Not ($?)) +$FUZZER_ERROR_CODE=$LASTEXITCODE +if ($FUZZER_ERROR_CODE -eq 2) { Write-Host "Fuzzing failed. HTML report will not be produced." exit 1 @@ -112,3 +112,9 @@ else exit 1 } Write-Host "--- Ending generating HTML test report ---" + +if ($FUZZER_ERROR_CODE -eq 1) +{ + Write-Host "There were some failures! Returning non-zero return value." + exit 1 +} diff --git a/run.sh b/run.sh index 2cb993b..73c32ca 100644 --- a/run.sh +++ b/run.sh @@ -77,7 +77,12 @@ ${PYTHON3_BIN} -m virtualenv env echo "Started fuzzing" . ./env/bin/activate ; \ pip install --upgrade pip ; pip install git+https://github.com/jtpereyda/boofuzz.git ; pip install junit-xml ; \ -python fuzzer/src/wapifuzz.py ${WAPIFUZZ_CONFIG} ${API_REQUESTS_JSON} ${JUNIT_TEST_REPORT} ${CUSTOM_PAYLOADS_FILE} > ${FUZZER_LOG} || { echo 'Fuzzing failed. Trying to generate HTML result of procceeded test cases.' ; } ; deactivate +python fuzzer/src/wapifuzz.py ${WAPIFUZZ_CONFIG} ${API_REQUESTS_JSON} ${JUNIT_TEST_REPORT} ${CUSTOM_PAYLOADS_FILE} > ${FUZZER_LOG} +FUZZER_ERROR_CODE=$? +if [ "$FUZZER_ERROR_CODE" -eq "2" ]; then + echo "Fuzzing failed. Trying to generate HTML result of procceeded test cases."; +fi +deactivate echo "Fuzzing finished" echo "Starting generating HTML test report" @@ -91,3 +96,8 @@ else exit 1 fi echo "Ending generating HTML test report" + +if [ "$FUZZER_ERROR_CODE" -eq "1" ]; then + echo "There were some failures! Returning non-zero return value."; + exit -1; +fi