Syntribos Code Documentation¶
Configuration¶
This section describes the configuration specified in the second argument to the runner, your configuration file.
-
syntribos.config.
handle_config_exception
(exc)¶
-
syntribos.config.
list_cli_opts
()¶
-
syntribos.config.
list_logger_opts
()¶
-
syntribos.config.
list_opts
()¶
-
syntribos.config.
list_payment_system_opts
()¶
-
syntribos.config.
list_remote_opts
()¶ Method defining remote URIs for payloads and templates.
-
syntribos.config.
list_syntribos_opts
()¶
-
syntribos.config.
list_test_opts
()¶
-
syntribos.config.
list_user_opts
()¶
-
syntribos.config.
register_opts
()¶
-
syntribos.config.
sub_commands
(sub_parser)¶
Signals¶
This section describes Signals (syntribos.signal.SynSignal
) and
SignalHolders (syntribos.signal.SignalHolder
).
-
class
syntribos.signal.
SynSignal
(text='', slug='', strength=0.0, tags=None, data=None, check_name=None)¶ SynSignal represents a piece of information raised by a ‘check’
Variables: - text (str) – A message describing the signal
- slug (str) – A unique slug that identifies the signal
- strength (float) – A number from 0 to 1 representing confidence
- tags (list) – Collection of tags associated with the signal
- data (dict) – Information about the results of the check
-
matches_slug
(slug)¶ Checks if a Signal has a given slug
Parameters: slug (str) – Slug to search for Return type: bool Returns: True if fuzzy match, else False
-
matches_tag
(tag)¶ Checks if a Signal has a given tag
Parameters: tag (str) – Tag to search for Return type: bool Returns: True if fuzzy match, else False
-
class
syntribos.signal.
SignalHolder
(signals=None)¶ SignalHolder represents a ‘set’ of SynSignals.
Variables: - signals (list) – Collection of
SynSignal
- all_slugs (list) – Collection of slugs in signals for fast search
-
__contains__
(item)¶ This is used to search for signals in the ‘if __ in __’ pattern.
-
__init__
(signals=None)¶ The SignalHolder can be initialized with a set of signals
Parameters: signals ( SynSignal
ORSignalHolder
OR list) – Collection of signals (added with self.register())
-
compare
(other)¶ Returns a dict with details of diff between 2 SignalHolders.
Param: signal_holder1
Ptype: class: Syntribos.signal.SignalHolder Param: signal_holder2
Ptype: class: Syntribos.signal.SignalHolder Returns: data
Return type: dict:
-
find
(slugs=None, tags=None)¶ Get the signals that are matched by slugs and/or tags
Parameters: - slugs (list) – A list of slugs to search for
- tags (list) – A list of tags to search for
Return type: class
Returns: A
SignalHolder
of matchedSynSignal
- signals (list) – Collection of
Checks¶
This section describes the checks, which analyze the HTTP response and returns a signal if it detects something that it knows about. It’s intended to make it easier to inspect HTTP responses.
-
syntribos.checks.content_validity.
valid_content
(test)¶ Checks if the response.content is valid.
Checks if the response.content is either xml or json and returns a signal based on if the content is valid or not.
Returns: SynSignal
-
syntribos.checks.fingerprint.
remote_os
(test)¶ Returns remote OS info.
Tries to identity which OS is running on the remote server
Returns: SynSignal
-
syntribos.checks.fingerprint.
server_software
(test)¶ Fingerprints the server and possible version.
Reads response headers and if server software information is present, returns a signal with server software slug.
Returns: SynSignal
-
syntribos.checks.http.
check_content_type
(response)¶ Returns a signal with info about a response’s content type
Parameters: response ( requests.Response
) –Returns: Signal with content type info Return type: syntribos.signal.SynSignal
-
syntribos.checks.http.
check_fail
(exception)¶ Checks for a requestslib exception, returns a signal if found.
If this Exception is an instance of
requests.exceptions.RequestException
, determine what kind of exception was raised. If not, return the results of from_generic_exception.Parameters: exception (Exception) – An Exception object Returns: Signal with exception details Return type: syntribos.signal.SynSignal
-
syntribos.checks.http.
check_status_code
(response)¶ Returns a signal with info about a response’s HTTP status code
Parameters: response ( requests.Response
) – A Response objectReturns: Signal with status code details Return type: syntribos.signal.SynSignal
-
syntribos.checks.length.
max_body_length
(test)¶ Checks if the response body length is more than max size in the config.
- Checks the response body to see if the length is more than the given length
- in the config. If it is, returns a Signal.
Returns: SynSignal or None
-
syntribos.checks.length.
percentage_difference
(test)¶ Validates length of two responses
Compares the length of a fuzzed response with a response to the baseline request. If the response is longer than expected, returns a LengthPercentageDiffSignal
Returns: SynSignal or None
-
syntribos.checks.ssl.
https_check
(test)¶ Checks if the returned response consists of non-secure endpoint URIs
Returns: syntribos.signal.SynSignal
-
syntribos.checks.stacktrace.
stacktrace
(test)¶ Checks if a stacktrace is returned by the response.
If a stacktrace is returned, attempts to identity if it was an application failure or a server failure and return appropriate tags.
returns a signal with the stacktrace slug.
Returns: SynSignal
-
syntribos.checks.string.
has_string
(test)¶ Checks if the response consists of any failure strings
Returns: syntribos.signal.SynSignal
-
syntribos.checks.time.
absolute_time
(test)¶ Checks response takes less than config.max_time seconds
Returns: SynSignal or None
-
syntribos.checks.time.
percentage_difference
(test)¶ Validates time taken for two responses
Compares the elapsed time of a fuzzed response with a response to the baseline request. If the response takes longer than expected, returns a TimePercentageDiffSignal
Returns: SynSignal or None
Tests¶
This section describes the components involved with writing your own tests with syntribos.
All syntribos tests inherit from syntribos.tests.base.BaseTestCase
,
either directly, or through a subclass such as
syntribos.tests.fuzz.base_fuzz.BaseFuzzTestCase
.
All tests are aggregated in the syntribos.tests.base.test_table
variable.
-
syntribos.tests.base.
ALLOWED_CHARS
= '().-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'¶ test_table is the master list of tests to be run by the runner
-
class
syntribos.tests.base.
BaseTestCase
(methodName='runTest')¶ Bases:
unittest.case.TestCase
Base class for building new tests
Attribute str test_name: A name like XML_EXTERNAL_ENTITY_BODY
, containing the test type and the portion of the request template being testedAttribute list failures: A collection of “failures” raised by tests Attribute bool dead: Flip this if one of the requests doesn’t return a response object Attribute client: HTTP client to be used by the test Attribute init_req: Initial request (loaded from request template) Attribute init_resp: Response to the initial request Attribute test_req: Request sent by the test for analysis Attribute test_resp: Response to the test request Attribute init_signals: Holder for signals on init_req Attribute test_signals: Holder for signals on test_req Attribute diff_signals: Holder for signals between init_req and test_req -
client
= <syntribos.clients.http.client.SynHTTPClient object>¶
-
classmethod
create_init_request
(filename, file_content, meta_vars)¶ Parses template and creates init request object
This method does not send the initial request, instead, it only creates the object for use in the debug test
Parameters: - filename (str) – name of template file
- file_content (str) – content of template file as string
-
dead
= False¶
-
diff_signals
= [""]¶
-
errors
= []¶
-
classmethod
extend_class
(new_name, kwargs)¶ Creates an extension for the class
Each TestCase class created is added to the test_table, which is then read in by the test runner as the master list of tests to be run.
Parameters: - new_name (str) – Name of new class to be created
- kwargs (dict) – Keyword arguments to pass to the new class
Return type: class
Returns: A TestCase class extending
BaseTestCase
-
failures
= []¶
-
classmethod
get_test_cases
(filename, file_content, meta_vars)¶ Returns tests for given TestCase class (overwritten by children).
-
init_req
= None¶
-
init_resp
= None¶
-
init_signals
= [""]¶
-
register_issue
(defect_type, severity, confidence, description)¶ Adds an issue to the test’s list of issues
Creates a
syntribos.issue.Issue
object, with given function parameters as instances variables, and registers the issue as a failure and associates the test’s metadata to it.Parameters: defect_type – The type of vulnerability that Syntribos believes it has found. This may be something like 500 error or DoS, regardless tof whathe Test Type is. :param severity: “Low”, “Medium”, or “High”, depending on the defect :param description: Description of the defect :param confidence: The confidence of the defect :returns: new issue object with metadata associated :rtype: Issue
-
classmethod
register_opts
()¶
-
run_test_case
()¶ This kicks off the test(s) for a given TestCase class
After running the tests, an AssertionError is raised if any tests were added to self.failures.
Raises: AssertionError
-
classmethod
send_init_request
(filename, file_content, meta_vars)¶ Parses template, creates init request object, and sends init request
This method sends the initial request, which is the request created after parsing the template file. This request will not be modified any further by the test cases themselves.
Parameters: - filename (str) – name of template file
- file_content (str) – content of template file as string
-
classmethod
tearDown
()¶ Hook method for deconstructing the test fixture after testing it.
-
classmethod
tearDownClass
()¶ Hook method for deconstructing the class fixture after running all tests in the class.
-
test_case
()¶ This method is overwritten by individual TestCase classes
It represents the actual test that is called in
run_test_case()
, and handles populating self.failures
-
test_name
= None¶
-
test_req
= None¶
-
test_resp
= None¶
-
test_signals
= [""]¶
-
-
exception
syntribos.tests.base.
FatalHTTPError
¶ Bases:
Exception
-
class
syntribos.tests.base.
TestType
¶ Bases:
type
This is the metaclass for each class extending
BaseTestCase
.
-
syntribos.tests.base.
replace_invalid_characters
(string, new_char='_')¶ Replace invalid characters in test names
This function corrects string so the following is true.
Identifiers (also referred to as names) are described by the following lexical definitions:
identifier ::= (letter|"_") (letter | digit | "_")*
letter ::= lowercase | uppercase
lowercase ::= "a"..."z"
uppercase ::= "A"..."Z"
digit ::= "0"..."9"
Parameters: - string (str) – Test name
- new_char (str) – The character to replace invalid characters with
Returns: The test name, with invalid characters replaced with new_char
Return type: str
-
syntribos.tests.fuzz.datagen.
fuzz_request
(req, strings, fuzz_type, name_prefix)¶ Creates the fuzzed RequestObject
Gets the name and the fuzzed request model from _fuzz_data, and creates a RequestObject from the parameters of the model.
Parameters: - req (
syntribos.clients.http.parser.RequestObject
) – The RequestObject to be fuzzed - strings (list) – List of strings to fuzz with
- fuzz_type (str) – What attribute of the RequestObject to fuzz
- name_prefix – (Used for ImpactedParameter)
Returns: Generator of tuples: (name, request, fuzzstring, ImpactedParameter name)
Return type: tuple
- req (
Issues¶
This section describes the representation of issues that are uncovered by syntribos.
-
class
syntribos.issue.
Issue
(defect_type, severity, description, confidence, request=None, response=None, impacted_parameter=None, init_signals=[], test_signals=[], diff_signals=[])¶ Bases:
object
Object that encapsulates a security vulnerability
This object is designed to hold the metadata associated with a vulnerability.
Variables: - defect_type – The type of vulnerability that Syntribos believes it has found. This may be something like 500 error or DoS, regardless of what the Test Type is.
- severity – “Low”, “Medium”, or “High”, depending on the defect
- description – Description of the defect
- confidence – The confidence of the defect
- request – The request object sent that generated this defect
- response – The response object returned after sending the request
- target – A hostname/IP/etc. to be tested
- path – A specific REST API method, i.e. a URL path associated with a Target.
- test_type – The type of vulnerability that is being tested for. This is not necessarily the same as the Defect Type, which may be something like 500 error or DoS.
- content_type – The content-type of the unmodified request
- impacted_parameter – For fuzz tests only, a
syntribos.tests.fuzz.base_fuzz.ImpactedParameter
that holds data about what part of the request was affected by the fuzz test.
-
as_dict
()¶ Convert the issue to a dict of values for outputting.
Return type: dict Returns: dictionary of issue data
-
get_details
()¶ Returns the most relevant information needed for output.
Return type: dict Returns: dictionary of issue details
-
request_as_dict
(req)¶ Convert the request object to a dict of values for outputting.
Parameters: req – The request object Return type: dict Returns: dictionary of HTTP request data
-
response_as_dict
(res)¶ Convert the response object to a dict of values for outputting.
Parameters: res – The result object Return type: dict Returns: dictionary of HTTP response data
Results¶
This section describes the representation of results (collections of issues) from a given syntribos run.
-
class
syntribos.result.
IssueTestResult
(stream, descriptions, verbosity)¶ Bases:
unittest.runner.TextTestResult
Custom unnittest results holder class
This class aggregates
syntribos.issue.Issue
objects from all the tests as they run-
addError
(test, err)¶ Duplicates parent class addError functionality.
Parameters: - test (
syntribos.tests.base.BaseTestCase
) – The test that encountered an error - err –
- test (
-
addFailure
(test, err)¶ Adds issues to data structures
Appends issues to the result’s list of failures, as well as updates the stats for the result. Each failure in the list of failures takes the form:
{ "url": "host.com/blah", "type": "500_error", "description": "500 errors r bad, mkay?", "failure_id": 1234, "instances": [ { "confidence": "HIGH", "param": { "location": "headers", "method": "POST", "variables": [ "Content-Type" ] }, "strings": [ "derp" ], "severity": "LOW", "signals": { "diff_signals": [], "init_signals": [], "test_signals": [] } } ] }
Parameters: - test (
syntribos.tests.base.BaseTestCase
) – The test that has failed - err (tuple) – Tuple of format
(type, value, traceback)
- test (
-
addSuccess
(test)¶ Duplicates parent class addSuccess functionality.
Parameters: test ( syntribos.tests.base.BaseTestCase
) – The test that was run
-
failure_id
= 0¶
-
output
= {'errors': [], 'failures': {}, 'stats': {'severity': {'HIGH': 0, 'LOW': 0, 'MEDIUM': 0, 'UNDEFINED': 0}}}¶
-
printErrors
(output_format)¶ Print out each
syntribos.issue.Issue
that was encounteredParameters: output_format (str) – “json”
-
print_log_path_and_stats
(start_time, log_path)¶ Print the path to the log folder for this run.
-
print_result
(start_time)¶ Prints test summary/stats (e.g. # failures) to stdout.
-
raw_issues
= []¶
-
severity_counter_dict
= {}¶
-
stats
= {'errors': 0, 'successes': 0, 'unique_failures': 0}¶
-
testsRunSinceLastPrint
= 0¶
-
HTTP Requests¶
This section describes the components related to generating, fuzzing, and making HTTP requests.
-
class
syntribos.clients.http.client.
SynHTTPClient
¶ Bases:
syntribos.clients.http.base_http_client.HTTPClient
This is the basic HTTP client used by Syntribos.
It aliases send_request to request so logging/exception handling is done in one place, for all requests. Also checks for bad HTTP status codes and adds a signal if one is found.
-
request
(method, url, headers=None, params=None, data=None, sanitize=False, requestslib_kwargs=None)¶ Sends a request (passes to requests.request)
Parameters: - method (str) – Request method
- url (str) – URL to request
- headers (dict) – Dictionary of headers in name:value format
- params (dict) – Dictionary of params in name:value format
- data (dict) – Data to send as part of request body
- requestslib_kwargs (dict) – Keyword arguments to pass to requests
Returns: tuple of (response, signals)
-
send_request
(request_obj)¶ This sends a request based on a RequestObject.
RequestObjects are generated by a parser (e.g.
syntribos.clients.http.parser.RequestCreator
) from request template files, and passed to this method to send the request.Parameters: request_obj ( syntribos.clients.http.parser.RequestObject
) – A RequestObject generated by a parserReturns: tuple of (response, signals)
-
-
class
syntribos.clients.http.parser.
RequestCreator
¶ Bases:
object
-
ACTION_FIELD
= 'ACTION_FIELD:'¶
-
EXTERNAL
= 'CALL_EXTERNAL\\|([^:]+?):([^:]+?)(?::([^|]+?))?\\|'¶
-
FUNC_NO_ARGS
= '([^:]+):([^:]+)'¶
-
FUNC_WITH_ARGS
= '([^:]+):([^:]+):(\\[.+\\])'¶
-
METAVAR
= '(\\|[^\\|]*\\|)'¶
-
classmethod
call_external_functions
(string)¶ Parse external function calls in the body of request templates
Parameters: string (str) – full HTTP request template as a string Return type: str Returns: the request, with EXTERNAL calls filled in with their values or UUIDs
-
classmethod
call_one_external_function
(string, args)¶ Calls one function read in from templates and returns the result.
-
classmethod
create_request
(string, endpoint, meta_vars=None)¶ Parse the HTTP request template into its components
Parameters: - string (str) – HTTP request template
- endpoint (str) – URL of the target to be tested
- meta_vars (dict) – Default None, dict parsed from meta.json
Return type: Returns: RequestObject with method, url, params, etc. for use by runner
-
classmethod
replace_one_variable
(var_obj)¶ Evaluate a VariableObject according to its type
A meta variable’s type is optional. If a type is given, the parser will interpret the variable in one of 3 ways according to its type, and returns that value.
- Type config: The parser will attempt to read the config value specified by the “val” attribute and returns that value.
- Type function: The parser will call the function named in the “val” attribute with arguments given in the “args” attribute, and returns the value from calling the function. This value is cached, and will be returned on subsequent calls.
- Type generator: works the same way as the function type, but its results are not cached and the function will be called every time.
Otherwise, the parser will interpret the variable as a static variable, and will return whatever is in the “val” attribute.
Parameters: var_obj – A syntribos.clients.http.parser.VariableObject
Returns: The evaluated value according to its meta variable type
-
-
class
syntribos.clients.http.parser.
RequestHelperMixin
¶ Bases:
object
Class that helps with fuzzing requests.
-
get_copy
()¶
-
get_prepared_copy
()¶ Create a copy of self, and prepare it for use by a fuzzer
Returns: Copy of request object that has been prepared for sending Return type: RequestHelperMixin
-
prepare_request
()¶ Prepare a request for sending off
It should be noted this function does not make a request copy, destroying iterators in request. A copy should be made if making multiple requests.
-
-
class
syntribos.clients.http.parser.
RequestObject
(method, url, action_field=None, headers=None, params=None, data=None, sanitize=False, data_type=None)¶ Bases:
syntribos.clients.http.parser.RequestHelperMixin
An object that holds information about an HTTP request.
Variables: - method (str) – Request method
- url (str) – URL to request
- action_field (dict) – Action Fields
- headers (dict) – Dictionary of headers in name:value format
- params (dict) – Dictionary of params in name:value format
- data – Data to send as part of request body
- sanitize (bool) – Boolean variable used to filter secrets
-
exception
syntribos.clients.http.parser.
TemplateParseException
¶ Bases:
Exception
-
class
syntribos.clients.http.parser.
VariableObject
(name, var_type='', args=[], val='', fuzz=True, fuzz_types=[], min_length=0, max_length=9223372036854775807, url_encode=False, prefix='', suffix='', **kwargs)¶ Bases:
object
-
FUZZ_TYPES
= ['int', 'ascii', 'url']¶
-
VAR_TYPES
= ['function', 'generator', 'config']¶
-
Extensions¶
This section describes syntribos extensions, which are called by the
CALL_EXTERNAL
field in the request template.
-
class
syntribos.extensions.identity.models.base.
BaseIdentityModel
(kwargs)¶ Bases:
object
-
static
_build_list
(items, element=None)¶ Builds json object or xml element from model
Calls either
item._obj_to_dict()
oritem.obj_to_xml_ele()
on all objects in items, and either returns the dict objects as a list or appends items to elementParameters: - items – list of objects for conversion
- element – The element to be appended, or None if json
Returns: list of dicts if element is None or element otherwise.
-
static
_build_list_model
(data, field_name, model)¶ Builds list of python objects from XML or json data
If data type is json, will find all json objects with field_name as key, and convert them into python objects of type model. If XML, will find all
xml.etree.ElementTree.Element
with field_name as tag, and convert them into python objects of type modelParameters: - data – Either json or XML object
- field_name (str) – json key or XML tag
- model – Class of objects to be returned
Returns: list of model objects
Return type: list
-
static
_create_text_element
(name, text)¶ Creates element with text data
Returns: new element with name name and text text Return type: xml.etree.ElementTree.Element
-
static
_find
(element, tag)¶ Finds element with tag
Parameters: - element –
xml.etree.ElementTree.Element
, the element through which to start searching - tag – the tag to search for
Returns: The element with tag tag if found, or a new element with tag None if not found
Return type: xml.etree.ElementTree.Element
- element –
-
static
_get_sub_model
(model, json=True)¶ Converts object to json or XML
Parameters: - model – Object to convert
- json (boolean) – True if converting to json, false if XML
-
classmethod
_json_to_obj
(serialized_str)¶
-
_namespaces
¶ alias of
Namespaces
-
_obj_to_dict
()¶
-
_obj_to_json
()¶
-
_obj_to_xml
()¶
-
_obj_to_xml_ele
()¶
-
classmethod
_remove_empty_values
(data)¶ Remove empty values
Returns a new dictionary based on ‘dictionary’, minus any keys with values that evaluate to False.
Parameters: data (dict) – Dictionary to be pruned Returns: dictionary without empty values Return type: dict
-
classmethod
_remove_xml_namespaces
(element)¶ Prunes namespaces from XML element
Parameters: element – element to be trimmed Returns: element with namespaces trimmed Return type: xml.etree.ElementTree.Element
-
classmethod
_xml_to_obj
(serialized_str, encoding='iso-8859-2')¶
-
classmethod
deserialize
(serialized_str, format_type)¶
-
serialize
(format_type)¶
-
static