mirror of
https://github.com/ysoftdevs/wapifuzz.git
synced 2026-01-11 22:30:35 +01:00
Merge pull request #7 from ysoftdevs/support_query_attributes
Support all query attributes
This commit is contained in:
@@ -18,4 +18,5 @@ script:
|
||||
- cd ~/build/ysoftdevs/wapifuzz/parser/ && dotnet restore && dotnet test
|
||||
- cd ~/build/ysoftdevs/wapifuzz/fuzzer/src/ && python3 -m unittest unit_tests.fuzzing_json_decoder_tests
|
||||
- cd ~/build/ysoftdevs/wapifuzz/fuzzer/src/ && python3 -m unittest unit_tests.json_schema_parser_tests
|
||||
- cd ~/build/ysoftdevs/wapifuzz/fuzzer/src/ && python3 -m unittest unit_tests.request_build_helper_tests
|
||||
- cd ~/build/ysoftdevs/wapifuzz/tests/ && chmod +x run_tests.sh && travis_wait ./run_tests.sh
|
||||
|
||||
@@ -89,7 +89,7 @@ def _generate_content_body(is_body_json, json_decoder, body_string_example, fuzz
|
||||
|
||||
def _generate_http_header(request, endpoint, fuzzable):
|
||||
s_static(request["Method"].upper() + " ")
|
||||
RequestBuildHelper.generate_uri(endpoint["Uri"], request["UriAttributes"], ConfigurationManager.config, fuzzable)
|
||||
RequestBuildHelper.generate_uri(endpoint["Uri"], request["UriAttributes"], fuzzable)
|
||||
s_static(" HTTP/1.1\r\n")
|
||||
RequestBuildHelper.generate_headers(ConfigurationManager.config)
|
||||
s_static("\r\n\r\n")
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import json
|
||||
from boofuzz import s_static, s_size
|
||||
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):
|
||||
@@ -34,10 +35,7 @@ class RequestBuildHelper(object):
|
||||
return headers is not None and header_name in headers
|
||||
|
||||
@staticmethod
|
||||
def generate_uri(uri, uri_parameters, config, fuzzable=False):
|
||||
fixed_attributes = config["fixed_url_attributes"] if "fixed_url_attributes" in config else None
|
||||
id_generator = _unique_uri_attribute_id()
|
||||
|
||||
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
|
||||
@@ -48,24 +46,49 @@ class RequestBuildHelper(object):
|
||||
index = uri.index("}")
|
||||
parameter_name = uri[0:index]
|
||||
|
||||
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)
|
||||
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:
|
||||
parameter_name = uri_parameter["Name"]
|
||||
if parameter_name not in already_used_parameters and uri_parameter["Location"] == "Query":
|
||||
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
|
||||
|
||||
86
fuzzer/src/unit_tests/request_build_helper_tests.py
Normal file
86
fuzzer/src/unit_tests/request_build_helper_tests.py
Normal file
@@ -0,0 +1,86 @@
|
||||
import unittest
|
||||
from request_build_helper import RequestBuildHelper
|
||||
from boofuzz import *
|
||||
from configuration_manager import ConfigurationManager
|
||||
|
||||
|
||||
class RequestBuilderHelperTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# Just init block for boofuzz
|
||||
s_initialize(self.id())
|
||||
|
||||
ConfigurationManager.config = []
|
||||
|
||||
def test_generate_simple_uri_without_parameters(self):
|
||||
uri_parameters = []
|
||||
base_uri = '/api/endpoint'
|
||||
|
||||
RequestBuildHelper.generate_uri(base_uri, uri_parameters)
|
||||
|
||||
uri = s_render().decode('utf8', 'ignore')
|
||||
self.assertEqual(base_uri, uri)
|
||||
|
||||
def test_generate_uri_path_parameter_without_documentation(self):
|
||||
uri_parameters = []
|
||||
|
||||
RequestBuildHelper.generate_uri('/api/endpoint/{id}', uri_parameters)
|
||||
|
||||
uri = s_render().decode('utf8', 'ignore')
|
||||
self.assertEqual('/api/endpoint/attribute', uri)
|
||||
|
||||
def test_generate_uri_path_parameter_with_fixed_config_value(self):
|
||||
uri_parameters = []
|
||||
ConfigurationManager.config = {
|
||||
"fixed_url_attributes": {
|
||||
"id": "20"
|
||||
}
|
||||
}
|
||||
|
||||
RequestBuildHelper.generate_uri('/api/endpoint/{id}', uri_parameters)
|
||||
|
||||
uri = s_render().decode('utf8', 'ignore')
|
||||
self.assertEqual('/api/endpoint/20', uri)
|
||||
|
||||
def test_generate_uri_path_parameter_with_documented_example(self):
|
||||
uri_parameters = [{'Name': 'id', 'Required': True, 'ExampleValue': '1', 'Type': 'string', 'Format': None, 'Location': 'Path'}]
|
||||
|
||||
RequestBuildHelper.generate_uri('/api/endpoint/{id}', uri_parameters)
|
||||
|
||||
uri = s_render().decode('utf8', 'ignore')
|
||||
self.assertEqual('/api/endpoint/1', uri)
|
||||
|
||||
def test_generate_uri_single_query_parameter_with_documented_example(self):
|
||||
uri_parameters = [{'Name': 'id', 'Required': True, 'ExampleValue': '1', 'Type': 'string', 'Format': None, 'Location': 'Query'}]
|
||||
|
||||
RequestBuildHelper.generate_uri('/api/endpoint', uri_parameters)
|
||||
|
||||
uri = s_render().decode('utf8', 'ignore')
|
||||
self.assertEqual('/api/endpoint?id=1', uri)
|
||||
|
||||
def test_generate_uri_single_query_parameter_with_multiple_documented_examples(self):
|
||||
uri_parameters = [
|
||||
{'Name': 'id', 'Required': True, 'ExampleValue': '1', 'Type': 'string', 'Format': None, 'Location': 'Query'},
|
||||
{'Name': 'attr', 'Required': True, 'ExampleValue': '2', 'Type': 'string', 'Format': None, 'Location': 'Query'}
|
||||
]
|
||||
|
||||
RequestBuildHelper.generate_uri('/api/endpoint', uri_parameters)
|
||||
|
||||
uri = s_render().decode('utf8', 'ignore')
|
||||
self.assertEqual('/api/endpoint?id=1&attr=2', uri)
|
||||
|
||||
def test_generate_uri_combined_parameters(self):
|
||||
ConfigurationManager.config = {
|
||||
"fixed_url_attributes": {
|
||||
"attr2": "20"
|
||||
}
|
||||
}
|
||||
uri_parameters = [
|
||||
{'Name': 'id', 'Required': True, 'ExampleValue': '1', 'Type': 'string', 'Format': None, 'Location': 'Path'},
|
||||
{'Name': 'attr1', 'Required': True, 'ExampleValue': '2', 'Type': 'string', 'Format': None, 'Location': 'Query'},
|
||||
{'Name': 'attr2', 'Required': True, 'ExampleValue': '3', 'Type': 'integer', 'Format': 'int32', 'Location': 'Query'}
|
||||
]
|
||||
|
||||
RequestBuildHelper.generate_uri('/api/endpoint/{id}', uri_parameters)
|
||||
|
||||
uri = s_render().decode('utf8', 'ignore')
|
||||
self.assertEqual('/api/endpoint/1?attr1=2&attr2=20', uri)
|
||||
@@ -10,6 +10,7 @@ namespace Models
|
||||
|
||||
public string Type { get; set; }
|
||||
public string Format { get; set; }
|
||||
public string Location { get; set; }
|
||||
|
||||
public UriAttribute(string name, bool required)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,34 @@ namespace Parser.Tests
|
||||
Assert.IsNull(parsedAttribute);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingPathAttributeWithPathLocation()
|
||||
{
|
||||
OpenApiParameter parameter = new OpenApiParameter
|
||||
{
|
||||
Schema = new OpenApiSchema { Type = "string", Format = null },
|
||||
In = ParameterLocation.Path
|
||||
};
|
||||
|
||||
var parsedAttribute = AttributeParser.ParseAttribute(parameter);
|
||||
|
||||
Assert.AreEqual("Path", parsedAttribute.Location);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingPathAttributeWithQueryLocation()
|
||||
{
|
||||
OpenApiParameter parameter = new OpenApiParameter
|
||||
{
|
||||
Schema = new OpenApiSchema { Type = "string", Format = null },
|
||||
In = ParameterLocation.Query
|
||||
};
|
||||
|
||||
var parsedAttribute = AttributeParser.ParseAttribute(parameter);
|
||||
|
||||
Assert.AreEqual("Query", parsedAttribute.Location);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingAttributeWithNoTypeOrFormatShouldReturnNull()
|
||||
{
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace Parser
|
||||
ContentParser.GetSingleExample(parameter.Schema?.Example) ??
|
||||
PrimitiveDataTypeExampleGenerator.GenerateExampleValueByType(parameter.Schema.Type, parameter.Schema.Format),
|
||||
Type = parameter.Schema.Type,
|
||||
Format = parameter.Schema.Format
|
||||
Format = parameter.Schema.Format,
|
||||
Location = parameter.In == ParameterLocation.Path ? "Path" : "Query"
|
||||
};
|
||||
return attribute;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user