예제 #1
0
    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)
예제 #2
0
 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
예제 #3
0
 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
예제 #4
0
 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
예제 #5
0
 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
예제 #6
0
    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)
예제 #7
0
 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)