microsoft / restler-fuzzer

RESTler is the first stateful REST API fuzzing tool for automatically testing cloud services through their REST APIs and finding security and reliability bugs in these services.
MIT License
2.52k stars 283 forks source link

Added additional check to avoid IndexError #900

Open Cokun01 opened 2 weeks ago

Cokun01 commented 2 weeks ago

Summary of the Pull Request

This PR aims to fix, that the check_type_mismatch(self, check_value) method of the ParamArray(ParamBase) class can cause a IndexError.

PR Checklist

Info on Pull Request

While testing restlers fuzzing mode I ran into an IndexError caused by the previously mentioned method. To fix this, I added an additional check to test if self._values has a first element in case it is of type list. If not the self.tag is returend. I'm not quite sure if the tool should react this way if the self._values is a list but empty. Might be a sign of another bug if this scenario shouldn't happen at all. For me, it allowed the tool to run in fuzzing mode.

EngineStdOut.txt of the error run:

2024-06-10 15:31:02.567: Initializing: Garbage collection every 30 seconds.
2024-06-10 15:31:02.678: Generation: 1 
Invalid value generator random seed: 1718026263.7919257
Setting invalid value generator random seed: 12345
...
Invalid value generator random seed: 1718026555.0672019
Setting invalid value generator random seed: 12345
Exception list index out of range applying checker <checkers.payload_body_checker.PayloadBodyChecker object at 0x000001C83488DF10>
2024-06-10 15:36:19.457: Terminating garbage collection. Waiting for max 300 seconds. 
Traceback (most recent call last):
  File "C:\restler_bin\engine\engine\core\fuzzer.py", line 43, in run
    self._num_total_sequences = driver.generate_sequences(
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\restler_bin\engine\engine\core\driver.py", line 835, in generate_sequences
    seq_collection = render(seq_collection, fuzzing_pool, checkers, generation, global_lock,
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\restler_bin\engine\engine\core\driver.py", line 331, in render_sequential
    valid_renderings = render_one(seq_collection[ith], ith, checkers, generation, global_lock, garbage_collector)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\restler_bin\engine\engine\core\driver.py", line 225, in render_one
    apply_checkers(checkers, renderings, global_lock)
  File "C:\restler_bin\engine\engine\core\driver.py", line 156, in apply_checkers
    checker.apply(renderings, global_lock)
  File "C:\restler_bin\engine\checkers\payload_body_checker.py", line 188, in apply
    self._run_feedback_fuzzing(last_request, body_schema_list)
  File "C:\restler_bin\engine\checkers\payload_body_checker.py", line 641, in _run_feedback_fuzzing
    self._run_invalid_json_task(
  File "C:\restler_bin\engine\checkers\payload_body_checker.py", line 743, in _run_invalid_json_task
    self._run_body_value_fuzzing(
  File "C:\restler_bin\engine\checkers\payload_body_checker.py", line 849, in _run_body_value_fuzzing
    self._exec_request_with_new_body(request, body_blocks, tracker)
  File "C:\restler_bin\engine\checkers\payload_body_checker.py", line 1239, in _exec_request_with_new_body
    bug_info = self._buckets.add_bug(request, rendered_data)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\restler_bin\engine\checkers\payload_body_bucketing.py", line 39, in add_bug
    error_str = self._get_error_str(request, new_body) or 'Other'
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\restler_bin\engine\checkers\payload_body_bucketing.py", line 64, in _get_error_str
    mismatch = request.body_schema.has_type_mismatch(new_body)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\restler_bin\engine\engine\fuzzing_parameters\body_schema.py", line 263, in has_type_mismatch
    return self._schema.check_type_mismatch(new_body)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\restler_bin\engine\engine\fuzzing_parameters\request_params.py", line 663, in check_type_mismatch
    tag = member.check_type_mismatch(check_value)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\restler_bin\engine\engine\fuzzing_parameters\request_params.py", line 1725, in check_type_mismatch
    return self.value.check_type_mismatch(check_value[self.name])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\restler_bin\engine\engine\fuzzing_parameters\request_params.py", line 858, in check_type_mismatch
    return self._values[0].check_type_mismatch(new_check)
           ~~~~~~~~~~~~^^^
IndexError: list index out of range

Validation Steps Performed

Run the tool with the modified code in fuzzing mode without encountering the IndexError.