mirror of
https://github.com/ysoftdevs/wapifuzz.git
synced 2026-01-14 07:33:29 +01:00
130 lines
6.2 KiB
Python
130 lines
6.2 KiB
Python
import json
|
|
from typing import List
|
|
from boofuzz import s_static, s_size, s_render
|
|
from fuzz_payloads import s_http_string, s_http_number, s_http_boolean
|
|
from encodings_helper import EncodingTypes
|
|
from parameter import Parameter
|
|
from configuration_manager import ConfigurationManager
|
|
|
|
|
|
class RequestBuildHelper(object):
|
|
# Content-length and Host are mandatory
|
|
@staticmethod
|
|
def generate_headers(config):
|
|
# Append headers from config
|
|
headers = config["headers"]
|
|
if headers is not None:
|
|
for key, value in headers.items():
|
|
s_static(key + ": " + value)
|
|
s_static("\r\n")
|
|
|
|
# Append host, if it is not provided in config
|
|
if not RequestBuildHelper._is_header_in_config(headers, "Host"):
|
|
s_static("Host: " + config["target"]["hostname"])
|
|
s_static("\r\n")
|
|
|
|
# Append content-length, if it is not provided in config
|
|
if not RequestBuildHelper._is_header_in_config(headers, "Content-Length"):
|
|
s_static('Content-Length: ')
|
|
# s_size calculates the byte length of Boofuzz block with name "body",
|
|
# which contains whole HTTP request content part. with actual mutation.
|
|
s_size("body", output_format="ascii", fuzzable=False)
|
|
|
|
@staticmethod
|
|
def _is_header_in_config(headers, header_name):
|
|
return headers is not None and header_name in headers
|
|
|
|
@staticmethod
|
|
def _generate_base_uri_path(uri, uri_parameters, id_generator, fuzzable, already_used_parameters):
|
|
while True:
|
|
try:
|
|
# Find first not yet found parameter, if there is one
|
|
index = uri.index("{")
|
|
prefix = uri[0:index]
|
|
s_http_string(prefix, fuzzable=False, encoding=EncodingTypes.ascii)
|
|
uri = uri[index + 1:]
|
|
index = uri.index("}")
|
|
parameter_name = uri[0:index]
|
|
|
|
RequestBuildHelper._append_parameter(parameter_name, id_generator, uri_parameters, fuzzable)
|
|
|
|
uri = uri[index + 1:]
|
|
already_used_parameters.append(parameter_name)
|
|
except ValueError:
|
|
if len(uri) > 0:
|
|
name = "URI attribute, default value: " + uri + ", id: " + next(id_generator)
|
|
s_http_string(uri, fuzzable=False, encoding=EncodingTypes.ascii, name=name)
|
|
break
|
|
|
|
@staticmethod
|
|
def _generate_additional_query_parameters(uri_parameters, already_used_parameters, id_generator, fuzzable):
|
|
for uri_parameter in uri_parameters:
|
|
if uri_parameter["Name"] not in already_used_parameters and uri_parameter["Location"] == "Query":
|
|
RequestBuildHelper._generate_single_query_additional_parameter(id_generator, uri_parameters, fuzzable, uri_parameter["Name"], uri_parameter["Required"])
|
|
|
|
@staticmethod
|
|
def _generate_single_query_additional_parameter(id_generator, uri_parameters, fuzzable, parameter_name, required):
|
|
are_non_required_attributes_in_requests = ConfigurationManager.are_non_required_attributes_in_requests()
|
|
if required or are_non_required_attributes_in_requests:
|
|
prefix = "?" if "?" not in s_render().decode('ascii', 'ignore') else "&"
|
|
name = "URI attribute, default value: " + parameter_name + ", id: " + next(id_generator)
|
|
s_http_string(prefix + parameter_name + "=", fuzzable=False, encoding=EncodingTypes.ascii, name=name)
|
|
RequestBuildHelper._append_parameter(parameter_name, id_generator, uri_parameters, fuzzable)
|
|
|
|
@staticmethod
|
|
def generate_uri(uri, uri_parameters, fuzzable=False):
|
|
id_generator = _unique_uri_attribute_id()
|
|
already_used_parameters: List[str] = []
|
|
|
|
RequestBuildHelper._generate_base_uri_path(uri, uri_parameters, id_generator, fuzzable, already_used_parameters)
|
|
RequestBuildHelper._generate_additional_query_parameters(uri_parameters, already_used_parameters, id_generator, fuzzable)
|
|
|
|
@staticmethod
|
|
def _append_parameter(parameter_name, id_generator, uri_parameters, fuzzable):
|
|
fixed_attributes = ConfigurationManager.config["fixed_url_attributes"] if "fixed_url_attributes" in ConfigurationManager.config else None
|
|
|
|
parameter: Parameter = RequestBuildHelper._get_parameter(parameter_name, fixed_attributes, uri_parameters)
|
|
name = "URI attribute, default value: " + parameter.value + ", id: " + next(id_generator)
|
|
is_part_fuzzable = fuzzable and not parameter.is_from_config
|
|
|
|
if parameter.data_type and (parameter.data_type == 'integer' or parameter.data_type == 'number'):
|
|
s_http_number(parameter.value, fuzzable=is_part_fuzzable, encoding=EncodingTypes.urlencoded, name=name)
|
|
elif parameter.data_type and parameter.data_type == 'string':
|
|
s_http_boolean(parameter.value, fuzzable=is_part_fuzzable, encoding=EncodingTypes.urlencoded, name=name)
|
|
else:
|
|
s_http_string(parameter.value, fuzzable=is_part_fuzzable, encoding=EncodingTypes.urlencoded, name=name)
|
|
|
|
# Getting parameter value from these sources (ordered):
|
|
# 1] Fixed attributes from config
|
|
# 2] Example value from documentation
|
|
# 3] Placeholder 'attribute'
|
|
@staticmethod
|
|
def _get_parameter(parameter_name, fixed_attributes, uri_parameters) -> Parameter:
|
|
if fixed_attributes is not None and parameter_name in fixed_attributes:
|
|
return Parameter(parameter_name, fixed_attributes[parameter_name], None, None, True)
|
|
elif any(parameter["Name"] == parameter_name for parameter in uri_parameters):
|
|
for parameter in uri_parameters:
|
|
if parameter["Name"] == parameter_name:
|
|
return Parameter(parameter_name, parameter["ExampleValue"], parameter["Type"], parameter["Format"], False)
|
|
else:
|
|
return Parameter(parameter_name, 'attribute', None, None, False)
|
|
|
|
@staticmethod
|
|
def is_string_valid_json(input_string: str) -> bool:
|
|
try:
|
|
json.loads(input_string)
|
|
return True
|
|
except ValueError:
|
|
return False
|
|
|
|
@staticmethod
|
|
def get_request_name(uri, method_type) -> str:
|
|
return uri + ", " + method_type
|
|
|
|
|
|
def _unique_uri_attribute_id():
|
|
sequence = 0
|
|
while True:
|
|
yield str(sequence)
|
|
sequence += 1
|