Ejemplo n.º 1
0
    def to_dict(self, encoding='base64'):
        """
        Return a dictionary version of the report

        :param encoding: required encoding for the string values (default: 'base64')
        :rtype: dictionary
        :return: dictionary representation of the report
        """
        res = {}
        for k, v in self._data_fields.items():
            if isinstance(v, (bytes, bytearray, six.string_types)):
                v = try_b64encode(v)
            res[k] = v
        for k, v in self._sub_reports.items():
            res[k] = v.to_dict(encoding)
        return res
Ejemplo n.º 2
0
    def transmit(self, **kwargs):
        """
        Prepares fuzz HTTP request, sends and processes the response
        :param kwargs: url, method, params, querystring, etc
        :return:
        """
        self.logger.debug('Transmit: {}'.format(kwargs))
        try:
            _req_url = list()
            for url_part in self.base_url, kwargs['url']:
                if isinstance(url_part, Bits):
                    url_part = url_part.tobytes()
                if isinstance(url_part, bytes):
                    url_part = url_part.decode()
                _req_url.append(url_part.strip('/'))
            kwargs.pop('url')
            # Replace back the placeholder for '/'
            # (this happens in expand_path_variables,
            # but if we don't have any path_variables, it won't)
            request_url = '/'.join(_req_url).replace('+', '/')
            query_params = None

            if kwargs.get('params') is not None:
                self.logger.debug(
                    ('Adding query params: {}'.format(kwargs.get('params',
                                                                 {}))))
                query_params = self.format_pycurl_query_param(
                    request_url, kwargs.get('params', {}))
                kwargs.pop('params')
            if kwargs.get('path_variables') is not None:
                request_url = self.expand_path_variables(
                    request_url, kwargs.get('path_variables'))
                kwargs.pop('path_variables')
            if kwargs.get('data') is not None:
                kwargs['data'] = self.fix_data(kwargs.get('data'))
            if query_params is not None:
                request_url = '{}{}'.format(request_url, query_params)
            method = kwargs['method']
            self.logger.info('Request URL : {} {}'.format(method, request_url))
            if kwargs.get('data') is not None:
                self.logger.info('Request data:{}'.format(
                    json.dumps(dict(kwargs.get('data')))))
            if isinstance(method, Bits):
                method = method.tobytes()
            if isinstance(method, bytes):
                method = method.decode()
            kwargs.pop('method')
            kwargs['headers'] = self.compile_headers(kwargs.get('headers'))
            self.logger.debug(
                'Request url:{}\nRequest method: {}\nRequest headers: {}\nRequest body: {}'
                .format(request_url, method,
                        json.dumps(dict(kwargs.get('headers', {})), indent=2),
                        kwargs.get('data')))
            self.report.set_status(Report.PASSED)
            self.report.add('request_url', request_url)
            self.report.add('request_method', method)
            self.report.add('request_headers',
                            json.dumps(dict(kwargs.get('headers', {}))))
            try:
                resp_buff_hdrs = BytesIO()
                resp_buff_body = BytesIO()
                buffer = BytesIO()
                _curl = init_pycurl()
                _curl.setopt(pycurl.URL, self.format_pycurl_url(request_url))
                _curl.setopt(pycurl.HEADERFUNCTION, self.header_function)
                _curl.setopt(
                    pycurl.HTTPHEADER,
                    self.format_pycurl_header(kwargs.get('headers', {})))
                _curl.setopt(pycurl.POST, len(kwargs.get('data', {}).items()))
                _curl.setopt(pycurl.CUSTOMREQUEST, method)
                _curl.setopt(pycurl.POSTFIELDS,
                             urllib.parse.urlencode(kwargs.get('data', {})))
                _curl.setopt(pycurl.HEADERFUNCTION, resp_buff_hdrs.write)
                _curl.setopt(pycurl.WRITEFUNCTION, resp_buff_body.write)
                for retries in reversed(range(0, 3)):
                    try:
                        _curl.perform()
                    except Exception as e:
                        if retries:
                            self.logger.error(
                                'Retrying... ({}) because {}'.format(
                                    retries, e))
                        else:
                            raise e
                _return = Return()
                _return.status_code = _curl.getinfo(pycurl.RESPONSE_CODE)
                _return.headers = self.resp_headers
                _return.content = buffer.getvalue()
                _return.request = Return()
                _return.request.headers = kwargs.get('headers', {})
                _return.request.body = kwargs.get('data', {})
                _curl.close()
            except Exception as e:
                self.logger.exception(e)
                self.report.set_status(Report.FAILED)
                self.logger.error('Request failed, reason: {}'.format(e))
                # self.report.add('request_sending_failed', e.msg if hasattr(e, 'msg') else e)
                self.report.add('request_method', method)
                return
            # overwrite request headers in report, add auto generated ones
            self.report.add(
                'request_headers',
                try_b64encode(json.dumps(dict(_return.request.headers))))
            self.logger.debug(
                'Response code:{}\nResponse headers: {}\nResponse body: {}'.
                format(_return.status_code,
                       json.dumps(dict(_return.headers), indent=2),
                       _return.content))
            self.report.add('request_body', _return.request.body)
            self.report.add('response', _return.content.decode())
            status_code = _return.status_code
            if not status_code:
                self.report_add_basic_msg('Failed to parse http response code')
            elif status_code not in self.accepted_status_codes:
                self.report.add('parsed_status_code', status_code)
                self.report_add_basic_msg(
                    ('Return code %s is not in the expected list:',
                     status_code))
            return _return
        except (UnicodeDecodeError, UnicodeEncodeError
                ) as e:  # request failure such as InvalidHeader
            self.report_add_basic_msg(
                ('Failed to parse http response code, exception occurred: %s',
                 e))
Ejemplo n.º 3
0
 def transmit(self, **kwargs):
     self.logger.debug('Transmit: {}'.format(kwargs))
     try:
         _req_url = list()
         for url_part in self.base_url, kwargs['url']:
             if isinstance(url_part, Bits):
                 url_part = url_part.tobytes()
             if isinstance(url_part, bytes):
                 url_part = url_part.decode()
             _req_url.append(url_part.strip('/'))
         kwargs.pop('url')
         request_url = '/'.join(_req_url)
         for param in ['path_variables', 'params']:
             if kwargs.get(param) is not None:
                 request_url = self.expand_path_variables(
                     request_url, kwargs.get(param))
                 kwargs.pop(param)
         self.logger.info('Request URL : {}'.format(request_url))
         method = kwargs['method']
         if isinstance(method, Bits):
             method = method.tobytes()
         if isinstance(method, bytes):
             method = method.decode()
         kwargs.pop('method')
         kwargs['headers'] = self.compile_headers(kwargs.get('headers'))
         self.logger.debug(
             'Request url:{}\nRequest method: {}\nRequest headers: {}\nRequest body: {}'
             .format(request_url, method,
                     json.dumps(dict(kwargs.get('headers', {})), indent=2),
                     kwargs.get('params')))
         self.report.set_status(Report.PASSED)
         self.report.add('request_url', request_url)
         self.report.add('request_method', method)
         self.report.add('request_headers',
                         json.dumps(dict(kwargs.get('headers', {}))))
         try:
             _return = requests.request(method=method,
                                        url=request_url,
                                        verify=False,
                                        timeout=10,
                                        **kwargs)
         except Exception as e:
             self.report.set_status(Report.FAILED)
             self.logger.error('Request failed, reason: {}'.format(e))
             self.report.add('request_sending_failed',
                             e.reason if hasattr(e, 'reason') else e)
             self.report.add('request_method', method)
             return
         # overwrite request headers in report, add auto generated ones
         self.report.add(
             'request_headers',
             try_b64encode(json.dumps(dict(_return.request.headers))))
         self.logger.debug(
             'Response code:{}\nResponse headers: {}\nResponse body: {}'.
             format(_return.status_code,
                    json.dumps(dict(_return.headers), indent=2),
                    _return.content))
         self.report.add('request_body', _return.request.body)
         self.report.add('response', _return.content.decode())
         status_code = _return.status_code
         if not status_code:
             self.report_add_basic_msg('Failed to parse http response code')
         elif status_code not in self.accepted_status_codes:
             self.report.add('parsed_status_code', status_code)
             self.report_add_basic_msg(
                 ('Return code %s is not in the expected list:',
                  status_code))
         return _return
     except (RequestException, UnicodeDecodeError, UnicodeEncodeError
             ) as e:  # request failure such as InvalidHeader
         self.report_add_basic_msg(
             ('Failed to parse http response code, exception occurred: %s',
              e))