import json import tempfile from ruamel.yaml import YAML from ruamel.yaml.scanner import ScannerError from apifuzzer.custom_fuzzers import RandomBitsField, Utf8Chars, UnicodeStrings from apifuzzer.exceptions import FailedToParseFileException from apifuzzer.utils import download_file, secure_randint def get_sample_data_by_type(param_type): types = { u'name': '012', u'string': 'asd', u'integer': 1, u'number': 667.5, u'boolean': False, u'array': [1, 2, 3] # transform_data_to_bytes complains when this array contains strings. } return types.get(param_type, b'\x00') def get_field_type_by_method(http_method): fields = { 'GET': 'params', 'POST': 'data', 'PUT': 'data' } return fields.get(http_method, 'data') def get_fuzz_type_by_param_type(fuzz_type): # https://kitty.readthedocs.io/en/latest/data_model/big_list_of_fields.html#atomic-fields # https://swagger.io/docs/specification/data-models/data-types/ string_types = [UnicodeStrings, RandomBitsField, Utf8Chars] number_types = [UnicodeStrings, RandomBitsField] types = { 'integer': number_types, 'float': number_types, 'double': number_types, 'int32': number_types, 'int64': number_types, 'number': number_types, 'string': string_types, 'email': string_types, 'uuid': string_types, 'uri': string_types, 'hostname': string_types, 'ipv4': string_types, 'ipv6': string_types, 'boolean': string_types } fuzzer_list = types.get(fuzz_type, string_types) return fuzzer_list[secure_randint(0, max(len(fuzzer_list) - 1, 1))] def container_name_to_param(container_name): return container_name.split('|')[-1] def get_api_definition_from_file(src_file): try: with open(src_file, mode='rb') as f: api_definition = f.read() try: return json.loads(api_definition.decode('utf-8')) except ValueError as e: print('Failed to load input as JSON, maybe YAML?') try: yaml = YAML(typ='safe') return yaml.load(api_definition) except (TypeError, ScannerError) as e: print('Failed to load input as YAML:{}'.format(e)) raise e except (Exception, FileNotFoundError): print('Failed to parse input file, exit') raise FailedToParseFileException def get_api_definition_from_url(url, temp_file=None): if temp_file is None: temp_file = tempfile.NamedTemporaryFile().name download_file(url, temp_file) return get_api_definition_from_file(temp_file) def get_base_url_form_api_src(url): """ provides base url from api definition source url. :param url: url like https://example.com/api/v1/api.json :return: url like https://example.com/api/v1 """ splited_url = url.split('/') return "/".join(splited_url[:len(splited_url) - 1])