diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..62d1bd8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,21 @@ +dist: xenial +language: csharp +mono: none +dotnet: 2.2.402 +script: + - sudo apt update + - sudo apt install --yes libssl-dev + - sudo apt install --yes build-essential checkinstall + - sudo apt install --yes libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev + - sudo apt install --yes dos2unix + - cd /usr/src && sudo wget https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz && sudo tar xzf Python-3.7.3.tgz && cd Python-3.7.3 && sudo ./configure --enable-optimizations && sudo make altinstall + - sudo ln -s /usr/local/bin/python3.7 /usr/local/bin/python3 + - sudo ln -s /usr/local/bin/pip3.7 /usr/local/bin/pip3 + - export PATH="/usr/local/bin:$PATH" + - sudo pip3 install --upgrade pip && sudo pip3 install git+https://github.com/jtpereyda/boofuzz.git && sudo pip3 install junit-xml && sudo pip3 install virtualenv + - find ~/build/ysoftdevs/wapifuzz/ -type f -exec dos2unix {} \; + - find ~/build/ysoftdevs/wapifuzz/ -type f -name "*.sh" -exec chmod u+x {} \; + - cd ~/build/ysoftdevs/wapifuzz/parser/ && dotnet restore && dotnet test + - cd ~/build/ysoftdevs/wapifuzz/fuzzer/src/ && python3 -m unittest unit_tests.fuzzing_json_decoder_tests + - cd ~/build/ysoftdevs/wapifuzz/fuzzer/src/ && python3 -m unittest unit_tests.json_schema_parser_tests + - cd ~/build/ysoftdevs/wapifuzz/tests/ && chmod +x run_tests.sh && travis_wait ./run_tests.sh diff --git a/README.md b/README.md index 4e3e9a5..9266162 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://travis-ci.com/ysoftdevs/wapifuzz.svg?branch=master)](https://travis-ci.com/ysoftdevs/wapifuzz) + # WapiFuzz - fully autonomous web APIs fuzzer Fuzzing is popular testing technique for various error types detection. There are many fuzzing engines and fuzzers, which can help you with fuzzing itself. But there is currently no tool which can fully automate fuzzing just by providing API specification. diff --git a/fuzzer/src/fuzzer.py b/fuzzer/src/fuzzer.py index 0c31eb2..8fad5e5 100644 --- a/fuzzer/src/fuzzer.py +++ b/fuzzer/src/fuzzer.py @@ -9,9 +9,10 @@ from blocks_generator import generate_http_fuzzed_blocks, generate_url_attribute class Fuzzer: - def __init__(self, endpoints, loggers: List, protocol: str): + def __init__(self, endpoints, text_logger, junit_logger, protocol: str): self._endpoints = endpoints - self._loggers = loggers + self._text_logger = text_logger + self._junit_logger = junit_logger self._protocol = protocol self._session = None @@ -39,7 +40,7 @@ class Fuzzer: self._session = Session( target=target, - fuzz_loggers=self._loggers, + fuzz_loggers=[self._text_logger, self._junit_logger], post_test_case_callbacks=[PostTestCaseCallback.post_test_callback], restart_sleep_time=0, keep_web_open=False, @@ -67,5 +68,5 @@ class Fuzzer: self._endpoints[:] = [endpoint for endpoint in self._endpoints if keyword not in endpoint.get('Uri')] def fuzz(self): - report_progress(self._session) + report_progress(self._session, self._junit_logger) self._session.fuzz() diff --git a/fuzzer/src/progress_reporter.py b/fuzzer/src/progress_reporter.py index 6926736..2a253da 100644 --- a/fuzzer/src/progress_reporter.py +++ b/fuzzer/src/progress_reporter.py @@ -5,27 +5,34 @@ import datetime from configuration_manager import ConfigurationManager DID_FUZZING_STARTED_CHECKS_TIME_INTERVAL_IN_SECONDS = 5 +HANGED_TIMEOUT = 120 -def report_progress(session): +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): if did_fuzzing_already_started(session) > 0: if is_fuzzing_hanged(session): message = create_hanged_message(session) print(message, file=sys.stderr) - os._exit(1) + threading.Timer(HANGED_TIMEOUT, close_testing_and_kill_fuzzer, [junit_logger, session]).start() if is_fuzzing_still_in_progress(session): - plan_another_report(session, ConfigurationManager.get_reporting_interval()) + plan_another_report(session, junit_logger, ConfigurationManager.get_reporting_interval()) message = create_report_message(session) print(message, file=sys.stderr) else: - plan_another_report(session, DID_FUZZING_STARTED_CHECKS_TIME_INTERVAL_IN_SECONDS) + plan_another_report(session, junit_logger, DID_FUZZING_STARTED_CHECKS_TIME_INTERVAL_IN_SECONDS) -def plan_another_report(session, reporting_interval): - threading.Timer(reporting_interval, report_progress, [session]).start() +def plan_another_report(session, junit_logger, reporting_interval): + threading.Timer(reporting_interval, report_progress, [session, junit_logger]).start() def did_fuzzing_already_started(session): diff --git a/fuzzer/src/unit_tests/fuzzing_json_decoder_tests.py b/fuzzer/src/unit_tests/fuzzing_json_decoder_tests.py index 2938dae..5a1dffa 100644 --- a/fuzzer/src/unit_tests/fuzzing_json_decoder_tests.py +++ b/fuzzer/src/unit_tests/fuzzing_json_decoder_tests.py @@ -3,6 +3,7 @@ import json from boofuzz import * from fuzzing_json_decoder import FuzzingJsonDecoder from fuzz_payloads import FuzzPayloads +from configuration_manager import ConfigurationManager class FuzzingJsonDecoderTests(unittest.TestCase): @@ -14,6 +15,9 @@ class FuzzingJsonDecoderTests(unittest.TestCase): FuzzPayloads.add_payload_to_list("payload 1", FuzzPayloads.CUSTOM_PAYLOADS_KEY) FuzzPayloads.add_payload_to_list("payload 2", FuzzPayloads.CUSTOM_PAYLOADS_KEY) + # Generate fake configuration + ConfigurationManager.config = [] + def __json_equality_assertion(self, original_json, generated_json): self.assertDictEqual(json.loads(original_json), json.loads(generated_json)) diff --git a/fuzzer/src/wapifuzz.py b/fuzzer/src/wapifuzz.py index dbcc6b6..7284033 100644 --- a/fuzzer/src/wapifuzz.py +++ b/fuzzer/src/wapifuzz.py @@ -34,7 +34,7 @@ def main(): with open(endpoints_description, 'r') as endpoints_description_file_pointer: endpoints = json.loads(endpoints_description_file_pointer.read()) - fuzzer = Fuzzer(endpoints, [text_logger, junit_logger], protocol) + fuzzer = Fuzzer(endpoints, text_logger, junit_logger, protocol) fuzzer.fuzz() diff --git a/parser/Parser.Tests/EndpointParserTests.cs b/parser/Parser.Tests/EndpointParserTests.cs index cf4daf5..58dad05 100644 --- a/parser/Parser.Tests/EndpointParserTests.cs +++ b/parser/Parser.Tests/EndpointParserTests.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using System.Globalization; +using System.Threading; using Microsoft.OpenApi.Models; using NUnit.Framework; using Models; @@ -7,6 +9,12 @@ namespace Parser.Tests { public class EndpointParserTests { + [SetUp] + public void SetUp() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); + } + readonly OpenApiDocument _document = new OpenApiDocument {Paths = new OpenApiPaths()}; private void AddTwoTestingPaths() { diff --git a/parser/Parser.Tests/OpenApiAnyConvertorTests.cs b/parser/Parser.Tests/OpenApiAnyConvertorTests.cs index b90a998..c31b060 100644 --- a/parser/Parser.Tests/OpenApiAnyConvertorTests.cs +++ b/parser/Parser.Tests/OpenApiAnyConvertorTests.cs @@ -1,4 +1,6 @@ using System; +using System.Globalization; +using System.Threading; using Microsoft.OpenApi.Any; using NUnit.Framework; @@ -6,6 +8,12 @@ namespace Parser.Tests { public class OpenApiAnyConvertorTests { + [SetUp] + public void SetUp() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); + } + [Test] public void ConvertStringPrimitiveShouldReturnCorrectValue() { @@ -51,7 +59,7 @@ namespace Parser.Tests public void ConvertDateTimePrimitiveShouldReturnCorrectValue() { var primitiveValue = OpenApiAnyConvertor.GetPrimitiveValue(new OpenApiDateTime(DateTime.UnixEpoch)); - Assert.AreEqual("1/1/1970 12:00:00 AM +00:00", primitiveValue); + Assert.AreEqual("01/01/1970 00:00:00 +00:00", primitiveValue); } [Test] diff --git a/parser/Parser/OpenApiAnyConvertor.cs b/parser/Parser/OpenApiAnyConvertor.cs index 9b23a33..42defa1 100644 --- a/parser/Parser/OpenApiAnyConvertor.cs +++ b/parser/Parser/OpenApiAnyConvertor.cs @@ -49,7 +49,7 @@ namespace Parser return dateValue.Value.ToString(CultureInfo.InvariantCulture); case PrimitiveType.DateTime: OpenApiDateTime dateTimeValue = (OpenApiDateTime) primitive; - return dateTimeValue.Value.ToString(); + return dateTimeValue.Value.ToString(CultureInfo.InvariantCulture); case PrimitiveType.Password: OpenApiPassword passwordValue = (OpenApiPassword) primitive; return passwordValue.Value; diff --git a/run.sh b/run.sh index cf629a2..2cb993b 100644 --- a/run.sh +++ b/run.sh @@ -77,7 +77,7 @@ ${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. HTML report will not be produced.' ; exit 1; } ; deactivate +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 echo "Fuzzing finished" echo "Starting generating HTML test report"