def process_api_resources(self): self.logger.info('Start preparation') for resource in self.api_resources['paths'].keys(): normalized_url = self.normalize_url(resource) for method in self.api_resources['paths'][resource].keys(): self.logger.info('Resource: {} Method: {}'.format( resource, method)) for param in self.api_resources['paths'][resource][method].get( 'parameters', {}): template_container_name = '{}|{}|{}'.format( normalized_url, method, param.get('name')) template = BaseTemplate(name=template_container_name) template.url = normalized_url template.method = method.upper() fuzz_type = get_fuzz_type_by_param_type( transform_data_to_bytes(param.get( 'type'))) # gives RandomBitsField at the moment sample_data = get_sample_data_by_type(param.get('type')) # get parameter placement(in): path, query, header, cookie # get parameter type: integer, string # get format if present param_type = param.get('in') param_name = template_container_name self.logger.debug( 'Resource: {} Method: {} Parameter: {}, Parameter type: {}, Sample data: {},' 'Param name: {}'.format(resource, method, param, param_type, sample_data, param_name)) if param_type == ParamTypes.PATH: template.path_variables.append( fuzz_type(name=param_name, value=str(sample_data))) elif param_type == ParamTypes.HEADER: template.headers.append( fuzz_type( name=param_name, value=transform_data_to_bytes(sample_data))) elif param_type == ParamTypes.COOKIE: template.cookies.append( fuzz_type(name=param_name, value=sample_data)) elif param_type == ParamTypes.QUERY: template.params.append( fuzz_type(name=param_name, value=str(sample_data))) elif param_type in [ParamTypes.BODY, ParamTypes.FORM_DATA]: template.data.append( fuzz_type( name=param_name, value=transform_data_to_bytes(sample_data))) else: self.logger.error( 'Can not parse a definition from swagger.json: %s', param) self.templates.append(template)
def _transmit(self, node): payload = {} for key in ['url', 'method']: payload[key] = transform_data_to_bytes( node.get_field_by_name(key).render()) fuzz_places = ['params', 'headers', 'data', 'path_variables'] for place in fuzz_places: # self.logger.info('Transmit place: {}'.format(place)) try: if place in node._fields_dict: param = node.get_field_by_name(place) # if isinstance(param, Container): _result = self._recurse_params(param) # self.logger.info('Process param recursively: {} gives: {}'.format(param, _result)) payload[place] = _result # elif hasattr(param, 'render'): # payload[place] = param.render() except KittyException as e: self.logger.warning( 'Exception occurred while processing {}: {}'.format( place, e.__str__())) # self.logger.info('Payload: {}'.format(payload)) self._last_payload = payload try: return self.target.transmit(**payload) except Exception as e: self.logger.error('Error in transmit: %s', e) raise
def _transmit(self, node): """ Where the magic happens. This function prepares the request :param node: Kitty template :type node: object """ payload = {'content_type': self.model.content_type} for key in ['url', 'method']: payload[key] = transform_data_to_bytes( node.get_field_by_name(key).render()) fuzz_places = ['params', 'headers', 'data', 'path_variables'] for place in fuzz_places: try: if place in node._fields_dict: param = node.get_field_by_name(place) _result = self._recurse_params(param) payload[place] = _result except KittyException as e: self.logger.warning( f'Exception occurred while processing {place}: {e}') self._last_payload = payload try: return self.target.transmit(**payload) except Exception as e: self.logger.error(f'Error in transmit: {e}') raise e
def _recurse_params(param): _return = dict() if isinstance(param, Container): for field in param._fields: _return[field.get_name( )] = OpenApiServerFuzzer._recurse_params(field) elif hasattr(param, 'render'): _return = transform_data_to_bytes( param.render()).decode(errors='ignore') return _return
def _recurse_params(param): """ Iterates trough parameters recursively :param param: param to process :type param: object :rtype: dict """ _return = dict() if isinstance(param, Container): for field in param._fields: _return[field.get_name( )] = OpenApiServerFuzzer._recurse_params(field) elif hasattr(param, 'render'): _return = transform_data_to_bytes( param.render()).decode(errors='ignore') return _return
def _process_api_resources(self, paths=None, existing_template=None): if paths is None: paths = self.api_resources.get('paths') for resource in paths.keys(): normalized_url = self._normalize_url(resource) for method in paths[resource].keys(): self.logger.info('Resource: {} Method: {}'.format( resource, method)) if existing_template: template = existing_template template_name = existing_template.name else: template_name = '{}|{}'.format(normalized_url, method) template = self._get_template(template_name) template.url = normalized_url template.method = method.upper() # Version 2: Set content type (POST, PUT method) if len(paths[resource][method].get('consumes', [])): template.content_type = paths[resource][method][ 'consumes'][0] for param in list(paths[resource][method].get( 'parameters', {})): if not isinstance(param, dict): self.logger.warning( '{} type mismatch, dict expected, got: {}'.format( param, type(param))) param = json.loads(param) if param.get('type'): parameter_data_type = param.get('type') else: parameter_data_type = 'string' param_format = param.get('format') if param.get('example'): sample_data = param.get('example') else: sample_data = get_sample_data_by_type( param.get('type')) parameter_place_in_request = param.get('in') parameters = list() if param.get("name"): param_name = f'{template_name}|{param.get("name")}' parameters.append({ 'name': param_name, 'type': parameter_data_type }) for _param in param.get('properties', []): param_name = f'{template_name}|{_param}' parameter_data_type = param.get('properties', {}).get(_param).get( 'type', 'string') self.logger.debug( f'Adding property: {param_name} with type: {parameter_data_type}' ) parameters.append({ 'name': param_name, 'type': parameter_data_type }) for _parameter in parameters: param_name = _parameter.get('name') parameter_data_type = _parameter.get('type') if param_format is not None: fuzzer_type = param_format.lower() elif parameter_data_type is not None: fuzzer_type = parameter_data_type.lower() else: fuzzer_type = None fuzz_type = get_fuzz_type_by_param_type(fuzzer_type) self.logger.info( f'Resource: {resource} Method: {method} Parameter: {param}, Parameter place: ' f'{parameter_place_in_request}, Sample data: {sample_data}, Param name: ' f'{param_name}, fuzzer: {fuzz_type.__name__}') if parameter_place_in_request == ParamTypes.PATH: template.path_variables.add( fuzz_type(name=param_name, value=str(sample_data))) elif parameter_place_in_request == ParamTypes.HEADER: template.headers.add( fuzz_type(name=param_name, value=transform_data_to_bytes( sample_data))) elif parameter_place_in_request == ParamTypes.COOKIE: template.cookies.add( fuzz_type(name=param_name, value=sample_data)) elif parameter_place_in_request == ParamTypes.QUERY: template.params.add( fuzz_type(name=param_name, value=str(sample_data))) elif parameter_place_in_request == ParamTypes.BODY: template.data.add( fuzz_type(name=param_name, value=transform_data_to_bytes( sample_data))) elif parameter_place_in_request == ParamTypes.FORM_DATA: template.params.add( fuzz_type(name=param_name, value=str(sample_data))) else: self.logger.warning( f'Can not parse a definition ({parameter_place_in_request}): ' f'{pretty_print(param)}') if template.get_stat() > 0: self._save_template(template)
def process_api_resources(self, paths=None): self.logger.info('Start preparation') tmp_api_resource = dict() if not paths: paths = self.api_resources['paths'] else: self.logger.info('Processing extra parameter: {}'.format( pretty_print(paths, limit=300))) for resource in paths.keys(): normalized_url = self.normalize_url(resource) for method in paths[resource].keys(): self.logger.info('Resource: {} Method: {}'.format( resource, method)) template_container_name = '{}|{}'.format( normalized_url, method) template = BaseTemplate(name=template_container_name) template.url = normalized_url template.method = method.upper() params_to_process = list(paths[resource][method].get( 'parameters', {})) params_to_process.append(paths[resource][method].get( 'requestBody', {})) for param in params_to_process: self.logger.info('Processing parameter: {}'.format(param)) if not isinstance(param, dict): self.logger.warning( '{} type mismatch, dict expected, got: {}'.format( param, type(param))) param = json.loads(param) if param.get('type'): parameter_data_type = param.get('type') elif param.get('schema', {}).get('type'): parameter_data_type = param.get('schema', {}).get('type') else: parameter_data_type = 'string' param_format = param.get('format') if param_format is not None: fuzzer_type = param_format.lower() elif parameter_data_type is not None: fuzzer_type = parameter_data_type.lower() else: fuzzer_type = None fuzz_type = get_fuzz_type_by_param_type(fuzzer_type) if param.get('example'): sample_data = param.get('example') elif param.get('schema', {}).get('example'): sample_data = param.get('schema', {}).get('example') else: sample_data = get_sample_data_by_type( param.get('type')) # get parameter placement(in): path, query, header, cookie # get parameter type: integer, string # get format if present parameter_place_in_request = param.get('in') param_name = '{}|{}'.format(template_container_name, param.get('name')) self.logger.debug( 'Resource: {} Method: {} Parameter: {}, Parameter type: {}, Sample data: {},' 'Param name: {}, fuzzer: {}'.format( resource, method, param, parameter_place_in_request, sample_data, param_name, fuzz_type.__name__)) if parameter_place_in_request == ParamTypes.PATH: template.path_variables.append( fuzz_type(name=param_name, value=str(sample_data))) elif parameter_place_in_request == ParamTypes.HEADER: template.headers.append( fuzz_type( name=param_name, value=transform_data_to_bytes(sample_data))) elif parameter_place_in_request == ParamTypes.COOKIE: template.cookies.append( fuzz_type(name=param_name, value=sample_data)) elif parameter_place_in_request == ParamTypes.QUERY: template.params.append( fuzz_type(name=param_name, value=str(sample_data))) elif parameter_place_in_request == ParamTypes.BODY: template.data.append( fuzz_type( name=param_name, value=transform_data_to_bytes(sample_data))) elif parameter_place_in_request == ParamTypes.FORM_DATA: template.params.append( fuzz_type(name=param_name, value=str(sample_data))) elif len(param.get('$ref', "")): self.logger.info( 'Only schema reference found in the parameter description: {}' .format(param)) tweaked_param = {'schema': param} tmp_api_resource = self.process_schema( resource, method, tweaked_param, tmp_api_resource) else: self.logger.error('Can not parse a definition: %s', param) if param.get('schema'): tmp_api_resource = self.process_schema( resource, method, param, tmp_api_resource) self.logger.info( 'Adding template to list: {}, templates list: {}'.format( template.name, len(self.templates) + 1)) self.templates.append(template) if len(tmp_api_resource) > 0: self.logger.info( 'Additional resources were found, processing these: {}'.format( pretty_print(tmp_api_resource))) self.process_api_resources(paths=tmp_api_resource)