Test and Custom Plugins
  • 07 Oct 2024
  • 23 Minutes to read
  • PDF

Test and Custom Plugins

  • PDF

Article summary

Plugins facilitate the testing of APIs used by your application. Using these plugins you can validate the effectiveness of security configurations and policies under various scenarios. Traceable provides you two types of plugins:

  • Test (Traceable) Plugin — Traceable provides these plugins out-of-the-box. These plugins are pre-designed to assess and validate the security of your APIs against the most common vulnerabilities. Test plugins are part of the scan policy, and you can use them to perform security checks, identify vulnerabilities, and potential security weaknesses. You can view these test plugins by navigating to TestingTest PluginsTraceable.

  • Custom Plugin — Traceable provides you the option to create plugins according to your requirements. These plugins enable you to implement specific security rules or logic, such as enforcing particular security policies, etc. You can configure these plugins either from the Traceable platform or using the config.yaml file. You can view your created plugins by navigating to Testing Test Plugins Custom tab.

You can use these plugins for regular security assessments, compliance checks, custom compliance reporting, and advanced threat detection. By using these plugins together, you can ensure that your application security is efficient and robust.

traceable_ast_testing_plugins(1)

The Test Plugins page also contains the Overrides tab that lists the assertion and mutation overrides configured for a quick scan or suite. You can navigate to the tab and view, edit, or delete these overrides according to your requirements. For more information on overrides, see Mutation and Assertion Overrides.


Custom Plugins

You can configure custom plugins in Traceable using either of the following options:

This section explains the various components of a custom plugin along with the description of the attributes and operators that are required to create this plugin.

Using the Traceable platform

To create a custom plugin using the Traceable platform, navigate to Testing Test Plugins and click Create Plugin in the page’s top right corner. Creating a custom plugin is a 3 step process:

  1. Selecting the vulnerability type you want to detect using the plugin.

  2. Configuring the custom plugin labels.

  3. Specifying the plugin definition according to your requirements.

Step 1 — Vulnerability Types

This step requires you to select the desired custom vulnerability you want Traceable to detect. To do this, you can use the Configure Vulnerability Types drop-down. The drop-down lists the custom vulnerability types you may have created in the Vulnerability Types page.

traceable_ast_test_plugins_custom_plugin_vulnerability_types


You can also click + Create New to create a new custom vulnerability. Once you have selected a vulnerability type, click Next.

Step 2 — Custom Plugin

This step requires you to specify the custom plugin labels that are required to describe the plugin in the Traceable platform. Following is the list of labels that you need to configure:

  • Safe from Production Environment — If disabled, Traceable does not use the custom plugin on your production environment, minimizing risks of impact on live data. If enabled, Traceable uses the custom plugin on your production environment.

  • Plugin name — The name of the custom plugin.

  • Description — Some basic information about the plugin, for example, the vulnerability it is detecting, any references.

  • Attack Methodology — A description of the attack methodology that you are going to use in the plugin, for example, how it detects a vulnerability, tests the APIs.

  • Category — The category of the plugin:

    • Active — This category of plugins actively interact with your application by making API calls to your application environment.

    • Passive — This category of plugins do not actively interacting with your application and observe the calls made to your application environment.

  • Tags — The metadata (key-value pairs) you want to apply to the plugin. For example, if the plugin detects vulnerabilities related to PCI DSS data, you can specify the key as Compliance with the value PCI DSS.
    To add multiple tags, click + Add Tag.

Once you have specified the above configurations, click Next.

Step 3 — Plugin Definition

This step requires you to either upload the custom plugin code file or specify its code snippet. To upload the custom plugin file, click Import from file. For more information on the attributes, functions, and operators you can use in a custom plugin, see Writing a custom plugin.


After you have specified the custom plugin code, you can  test the plugin using the Test Plugin widget. To do so, you must complete the following configurations:

  • Endpoint selection — You can do the following to use an endpoint for testing:

    • Select an endpoint from the drop-down.

    • Click Advanced Search and select an API endpoint.

    • Specify the Endpoint URL.

    Traceable populates the Request Headers and Request Body sections based on your selection. The selected endpoint acts as a reference. You can add Request Headers by clicking + Add Headers and Request Body according to your requirements. Traceable uses this request header and body for testing the plugin.

  • Runner selection — You can select a specific runner or allow Traceable to select one automatically. This runner is used for testing the plugin.

  • Run the scan — After you have completed the above step, click Run from the widget’s top right corner. Traceable displays the result below the Request Body section.

Once you have tested the plugin, click Submit. Traceable displays the plugin in the Custom tab. You can also click the Ellipse (traceable_ellipse_icon) icon corresponding to a plugin to edit or delete it.

Using config.yaml

This method enables you to create custom plugins using the config.yaml file (plugins section) on your local machine. Following are configurations that you can use while creating the plugin:

Default Location — TRACEABLE_HOME

CLI — $HOME/.traceable

Docker — /app/userdata

File Directory

Default Location

Description

config.yaml

$TRACEABLE_HOME`

Contains the configuration for AST, such as pre-hooks, post-hooks, and custom plugin definitions.

custom

$TRACEABLE_HOME/plugins/custom

Contains the custom plugin implementations.

hooks

$TRACEABLE_HOME/hooks

Contains the pre and post-hooks.

testsuite (per API)

$TRACEABLE_HOME/data/<scan_id>/*.json

Contains the JSON files that represent test suites. Each file is a suite of tests generated at the moment for a specific API.

Configuring custom plugins

The following section in the config.yaml file defines the custom plugins to load during the test runs:

custom:
   sample_plugin: {}

In the above code snippet, the plugin name is sample_plugin which should match the name of the plugin defined in the custom plugin code placed in the $TRACEABLE_HOME/plugins/custom directory.


Writing a custom plugin

The custom plugin is written in Python and should define some of the mandatory fields for identifying the test case to be performed and the name of the plugin. The following is a sample code snippet for writing a custom plugin:

from traceable.ast.testsuite.assertion import Assertion
from traceable.ast.testsuite.mutation import Mutation
from traceable.ast.testsuite.plugin import Plugin
from traceable.config import logger
from traceable.ast.context import ScanContext
import re


class CustomSamplePlugin(Plugin):
   # Required fields - See table below for description of the fields.
   ###############################################################################
   # This is the category of the plugin and is used to group plugins
   category = "custom"  # Can't be changed
   name = "SamplePlugin"  # Name of the plugin
   title = "Custom Sample Plugin"  # Title of the plugin used to display in the vulnerability
   # Description about what the plugin does.
   description = "This is a description text for vulnerability generated by sample plugin"
   # Mitigation for the vulnerability this plugin finds
   mitigation = "This is a mitigation text for vulnerability generated by sample plugin"
   # Severity of the vulnerability this plugin finds
   severity = "CRITICAL"
   # CVSS vector string for the vulnerability this plugin finds. Score is calculated automatically
   # https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?version=3.1&vector=AV:A/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L
   cvssVectorString = "AV:A/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L"


   # Optional Fields - See table below for description of the fields.
   ###############################################################################
   displayName = "Broken Object Level Authorization Plugin"  # Display name for plugin in UI
   affectedEntityType = "API"  # API/SERVICE/CUSTOM
   impact = "This is a impact text for vulnerability generated by sample plugin" # Describes the impact of the issue.
   references = "This is a references text for vulnerability generated by sample plugin" # Additional references or information regarding the issue.
   estimatedFixTime = 1.0 # Estimated time, in hours, to fix the issue.
   estimatedBountyValue = 100 # Estimated bounty value for fixing the issue, if applicable
   tags = {
       "author": "Tester",  #Custom tags; Can include metadata like author name
   }


   def __init__(self, scanctx: ScanContext):
       super().__init__(scanctx)   # Initialize the superclass (CustomPlugin) with the provided scan context


   def generate_test_cases(self) -> [TestCase]:
       self.scanctx[self.name + self.api_name] = False   # Initialize the scan context with a flag (set to False) for tracking if this plugin has run for a specific API
       test = self.create_test_case(vector="Unvalidated Scopes Test")   # Create a test case with a specific vector description
       test.mutations = []   # Initialize an empty list for mutations, which can be populated later based on the specific requirements of the test case
       assertions_or_group = Assertion.create_logical_assertion(
           "LOGICAL_OPERATOR_AND",   # Create a logical assertion group using AND logic to combine multiple conditions.
           [
               Assertion.create(   # First assertion: Check that the response code is NOT 200 (which indicates success)
                   "mutated.http.response.code",
                   "MATCH_OPERATOR_NOT_EQUALS",   # Match operator that checks inequality
                   "200",   # The actual value being compared
                   "401",   # The expected value that should not match
               ),
               Assertion.create(
                   "mutated.http.response.code",
                   "MATCH_OPERATOR_NOT_EQUALS",
                   "201",
                   "403",
               ),
           ],
       )
       test.assertions = [assertions_or_group]   # Assign the assertions to the test case
       return [test]   # Return the list of test cases; here, only one test case

The following sections specify the description of various fields present in the above code, along with the operators that you can use in them:

Required fields

Field

Description

category

For a custom plugin, the value of this field should always be “custom”.

name

The name of the custom plugin. The name you specify here should match the one in the config.yaml file.

For example, in the above code:

name = "SamplePlugin"

Similarly, in the config.yaml file:

name = "SamplePlugin"
scan:
   plugins:
.....
      custom:
         SamplePlugin: {}

title

The plugin title you want to display in the vulnerability.

description

The description of the vulnerability identified using the plugin.

mitigation

The steps for mitigating the vulnerability that the plugin finds.

severity

The severity of the vulnerability that the plugin finds. The severity can be either Unspecified, Critical, High, Medium, or Low.

cvss_vector_string

The string specifies the attributes of the vulnerability, along with the attack vector, complexity, privileges required, and impact. These values are used to calculate the severity score. For more information, see CVSS Vector Strings.

Optional fields

Field

Description

displayName

The name of the plugin should be visible in the Traceable platform user interface.

affectedEntityType

This field should have the value “Custom”.

impact

A description of the impact of the vulnerability that the plugin finds.

references

The list of references for the vulnerability generated by the plugin.

estimated_fix_time

The estimated fix time for the vulnerability that the plugin finds.

estimated_bounty_value

The estimated bounty value in case the vulnerability is exploited.

tags

The tags associated with the plugin.

Attributes convention

Attributes in a custom plugin are the configurable parameters that determine how the plugin should operate and process API requests and responses.

While the attributes starting with original. correspond to the requests Traceable is receiving from you or that are being generated from other sources, the attributes starting with mutated. represent the modified traffic from Traceable.

All attributes are stored in the form of their fully qualified name. For example, the authorization header is represented as original.http.request.header.authorization in the original request and mutated.http.request.header.authorization in the mutated request.

The following is the common list of attributes that you can use while writing a custom plugin:

Common list of attributes

  • (original/mutated).http.request.method: "POST"

  • (original/mutated).http.request.url: "http://example.com?arg=val1&arg2=val2"

  • (original/mutated).net.host.scheme: https

  • (original/mutated).net.host.name: "example.com"

  • (original/mutated).net.host.port: 443

  • (original/mutated).http.request.header.*: <All header keys are in lowercase>

  • (original/mutated).http.request.header.user-agent: "curl/1.1"

  • (original/mutated).http.request.header.accept: "application/json"

  • (original/mutated).http.request.header.content-type: "application/json"

  • (original/mutated).http.request.cookie.PHPSESSID: "064d213baaef028e724b06042a69561dceb256f3119721b846234d72dcc35134"

  • (original/mutated).http.request.query.param.limit: 100

  • (original/mutated).http.request.body: '{"username": "user1", "password": "p4s1d135DDg4"}'

  • (original/mutated).http.request.body.username: "user1"

  • (original/mutated).http.request.body.password: "user1"

  • (original/mutated).http.response.code'

  • (original/mutated).http.response.duration

  • (original/mutated).http.response.header.*: <All header keys are in lowercase>

  • (original/mutated).http.request.header.content-type: "application/json"

  • (original/mutated).http.response.cookie.PHPSESSID: "064d213baaef028e724b06042a69561dceb256f3119721b846234d72dcc35134"

  • (original/mutated).http.response.body: '{"token": "jshdlahflafnfbdfbkfnalfja", "msg": "Success"}'

  • (original/mutated).http.response.token: "jshdlahflafnfbdfbkfnalfja"

  • (original/mutated).http.response.msg: "Success"

Attribute operators

The following are the supported operators and their descriptions that you can use while writing a custom plugin:

Operator

Description

attributes.add_attributes(attributeList, prefix: str = "")

This operator is used to add attributes from another attribute list. It adds new values without modifying the existing ones.

attributes.set_attributes(attributeList, prefix: str = "")

This operator is used to set attributes from another attribute list. It modifies any existing values or creates them if they don’t exist.

attributes.get_one(key, , default: any = None, use_prefix: bool = False, regex: bool = False)

This operator is used to fetch one value from the attribute.

attributes.get(key, : str, default: any = None, use_prefix: bool = False, regex: bool = False)

This operator is used to fetch values from the attribute.

attributes.get_one_attr(key, , default: any = None, use_prefix: bool = False, regex: bool = False)

This operator is used to fetch one attribute.

attributes.get_original(key, , default: any = None, use_prefix: bool = False, regex: bool = False)

This operator is used to fetch the original value from the attribute.

attributes.items(self)

This operator is used to fetch the attribute list iterator.

attributes.add(key, : str, value: any, original_and_mutated: bool = False, is_dirty: bool = False, force: bool = False)

This operator is used to add attributes to the list. If original_and_mutated is True, both original and mutated keys are added; otherwise, only one copy without a prefix is added.

attributes.modify(key, : str, value: any, first_only: bool = False, regex: bool = False)

This operator is used to update all attributes with the specified key. If first_only is True, only the first attribute is updated. If the key is not found, the instruction is ignored.

attributes.set(key, : str, value: any, original_and_mutated: bool = False, regex: bool = False, is_dirty: bool = False, force: bool = True)

This operator is used to set attributes to the list. If original_and_mutated is True, both original and mutated keys are modified or are created if they don’t exist; otherwise, only one copy without a prefix is modified or created.

attributes.expand_attributes(self, data, regex: bool = False, user_prefix: bool = False)

This operator is used to expand templated variables to fetch the attribute value.

attributes.expand(self, data, regex: bool = False, use_prefix: bool = False)

This operator is used to expand templated variables to fetch the attribute value. For example, if the input is mutated.${authorization_header} and the authorization_header is request.header.jwt, then the output is mutated.request.header.jwt.

attributes.delete(key, value, regex: bool = False)

This operator is used to delete attributes from the attribute list.

Mutation function

The mutation function adds, modifies, and deletes specific parameters within API requests.

SyntaxMutation.create(operator: str, key: str, value: any = ””)

The function contains the following parameters:

  • operator (String) — The type of operation to be performed.

  • key (String) — The key or attribute to be mutated.

  • value (Any) — The new value to replace the existing value. This parameter can contain any value, for example, none or an empty string (““).

Mutation operators

The following are the supported operators that you can use along with the mutation function while writing a custom plugin:

Operator

Description

MUTATION_ADD

This operator adds a new key attribute with the specified value. If the key attribute already exists, it duplicates it.

Example:

test.mutaions = [
  Mutation.create("MUTATION_ADD", “mutated.http.query.param.id”, "100”)
  Mutation.create("MUTATION_ADD", “mutated.http.query.param.id”, "50”)
]

This adds two query params in the url resulting in ?id=100&id=50. This is typically used to test parameter pollution.

MUTATION_DELETE

This operator deletes an existing key attribute.

Example:

test.mutaions = [
  Mutation.create("MUTATION_DELETE", “mutated.http.query.param.id”, "”)
]

This removes the query param id from the API request.

MUTATION_MODIFY

This operator modifies a key attribute if it exists; otherwise, it does nothing.

Example:

test.mutaions = [
  Mutation.create("MUTATION_MODIFY", “mutated.http.query.param.id”, "100”)
]

This updates the query param id with value 100 if it exists; otherwise, it ignores the instruction.

MUTATION_SET

This operator sets the value of an existing key attribute or adds it if it does not exist.

Example:

test.mutaions = [
  Mutation.create("MUTATION_SET", “mutated.http.query.param.id”, "100”)
]

This sets the query param id to 100 if it already exists; otherwise, it creates a query param id with the same value.

MUTATION_REGEX_DELETE

This operator deletes all attributes that match the key/regular expression with value.

Example:

test.mutaions = [
  Mutation.create("MUTATION_REGEX_DELETE", r“mutated\.http\.query\.param.*amount”, "”)
]

This deletes all query params ending with the string “amount”.

MUTATION_REGEX_MODIFY

This operator modifies all attributes that match the key/regular expression with value.

Example:

test.mutaions = [
  Mutation.create("MUTATION_REGEX_MODIFY", r“mutated\.http\.query\.param.*amount”, "100”)
]

This modifies the query param ending with the string “amount” with value 100, if it exists; otherwise, it ignores the instruction.

MUTATION_REGEX_SET

This operator sets all attributes that match the key/regular expression with value.

Example:

test.mutaions = [
  Mutation.create("MUTATION_REGEX_SET", r“mutated\.http\.query\.param.*amount”, "100”)
]

This sets the query param ending with the string “amount” with a value of 100, if it exists; otherwise, it ignores the instruction.

Logical assertion function

The logical assertion function is used to apply conditional operators (AND/OR) to a list of assertions.

Syntaxcreate_logical_assertion(operator: str = "OR|AND", assertions: List[Assertion]): VULN(True)/NOT_VULN(False)

The function contains the following parameters:

  • operator (String) — The logical operator used to combine multiple assertions. The default operator is OR; however, it can be set to AND.

  • assertions (List[Assertion]) — A list of assertion objects to be combined using the logical operator.

Vulnerable logical assertion operators

The following are the supported operators that you can use along with the logical assertion function while writing a custom plugin:

Operator

Description

LOGICAL_OPERATOR_AND

All assertion items in the assertion list need to be VULN(True) for the return value to be VULN(True).

LOGICAL_OPERATOR_OR

Any assertion item in the assertion list needs to be VULN(True) for the return value to be VULN(True).

Assertion create function

Assertions are used to evaluate the scans’ responses for vulnerabilities.

Syntax Assertion.create(key: str, operator: str, mutated: str, original: str, **kwargs)

The function contains the following parameters:

  • key (String) — Used for display purposes as part of visualization on the UI. It is not used for any processing.

  • operator (String) — The match operator used for comparison.

  • mutated (String) — The mutated value for comparison.

  • original (String) — The original value for comparison.

  • **kwargs (optional) — Additional parameters used to provide metadata for the assertion. These parameters can vary depending on the match operator used.

Assertion operators

The following are the supported operators that you can use along with the assertion create function while writing a custom plugin:

Operator

Description

MATCH_OPERATOR_EQUALS

This operator checks whether the mutated value matches the original value. If it does, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.code", “MATCH_OPERATOR_EQUALS”, "${mutated.http.response.code}", “${original.http.response.code}”)

This evaluates to True if the response code received from the mutated request matches the response code received from the original request.

MATCH_OPERATOR_NOT_EQUALS

This operator checks whether the mutated value does not match the original value. If it does not, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body.param1", “MATCH_OPERATOR_NOT_EQUALS”, "${mutated.http.response.body.param1}", “${original.http.response.body.param1}”)

This evaluates to True if param1 received in the body of the response received for the mutated request does not match param1 in the body of the response received from the original request.

MATCH_OPERATOR_MATCHES_REGEX

This operator checks whether the mutated value matches the regex. If it does, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.duration", “MATCH_OPERATOR_MATCHES_REGEX”, "${mutated.http.response.code}", r"^5\d\d")

This evaluates to True if the response code received for the mutated request matches the specified regular expression.

MATCH_OPERATOR_NOT_MATCHES_REGEX

This operator checks whether the mutated value does not match the regex. If it does not, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.duration", “MATCH_OPERATOR_NOT_MATCHES_REGEX”, "${mutated.http.response.code}", r"^4\d\d")

This evaluates to True if the response code received for the mutated request does not match the specified regular expression.

MATCH_OPERATOR_GREATER_THAN

This operator checks whether the mutated value is greater than the original value. If it is, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.duration", “MATCH_OPERATOR_GREATER_THAN”, "${mutated.http.response.duration}", "100")

This evaluates to True if the time taken to receive a response to the mutated request takes longer than 100 ms.

MATCH_OPERATOR_GREATER_THAN_EQUALS

This operator checks whether the mutated value is greater than or equal to the original value. If it is, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body.param1", "MATCH_OPERATOR_GREATER_THAN_EQUALS", "${mutated.http.response.body.param1}", "100")

This evaluates to True if param1 in the body of the response received for the mutated request has a value greater than or equal to 100.

MATCH_OPERATOR_LESS_THAN

This operator checks whether the mutated value is less than the original value. If it is, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body.param1", "MATCH_OPERATOR_LESS_THAN", "${mutated.http.response.body.param1}", "100")

This evaluates to True if param1 in the body of the response received for the mutated request has a value less than 100.

MATCH_OPERATOR_LESS_THAN_EQUALS

This operator checks whether the mutated value is less than or equal to the original value. If it is, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body.param1", "MATCH_OPERATOR_LESS_THAN_EQUALS", "${mutated.http.response.body.param1}", "100")

This evaluates to True if param1 in the body of the response received for the mutated request has a value less than or equal to 100.

MATCH_OPERATOR_CONTAINS

This operator checks whether the mutated value contains the original value. If it does, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.
It also supports various python data structures, such as list, set, and string.

Example:

Assertion.create("http.response.body.param1", "MATCH_OPERATOR_NOT_CONTAINS", "${mutated.http.response.body.param1}", "Unauthorized")

This evaluates to True if param1 in the body of the response received for the mutated request contains the key word “Unauthorized”.

MATCH_OPERATOR_NOT_CONTAINS

This operator checks whether the mutated value does not contain the original value. If it does not, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

It also supports various python data structures, such as list, set, and string.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_NOT_CONTAINS", "${mutated.http.response.body}", "Bad request")

This evaluates to True if the body of the response received for the mutated request does not contain the key word “Bad request”.

MATCH_OPERATOR_IN

This operator checks whether the mutated value is present in the original value. If it is, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_IN", "${mutated.http.response.body.message}", "[\”FAILED\”,\”ERRORED\”]")

This evaluates to True if the message in the body of the response received for the mutated request includes either “Failed” or “Errored”.

MATCH_OPERATOR_NOT_IN

This operator checks whether the mutated value is not present in the original value. If it is not, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_NOT_IN",  "${mutated.http.response.body.message}", "[\”FAILED\”,\”ERRORED\”]")

This evaluates to True if the message in the body of the response received for the mutated request does not include either “Failed” or “Errored”.

MATCH_OPERATOR_KEYS_EQUALS

This operator checks whether the mutated and original values are JSON/URL-encoded parseable and have the same keys. If they do, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_KEYS_EQUALS",  "${mutated.http.response.body}", "${original.http.response.body}",  data={“level”:5,“content-type”: “application/json”})

This evaluates to True if the keys in the body of the response received for the mutated request has the same set of keys in the body of the response received for the original request - up to a depth of 5 for the JSON encoded tree.

MATCH_OPERATOR_KEYS_NOT_EQUALS

This operator checks whether the mutated and original values are JSON/URL-encoded parseable and have the same keys. If they do, the assertion evaluates to False/Not Vulnerable; otherwise, it evaluates to True/Vulnerable.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_KEYS_NOT_EQUALS",  "${mutated.http.response.body}", "${original.http.response.body}",  data={“level”:5,“content-type”: “application/json”})

This evaluates to True if the keys in the body of the response received for the mutated request does not have the same set of keys in the body of the response received for the original request - up to a depth of 5 for the JSON encoded tree.

MATCH_OPERATOR_FUZZY_EQUALS

This operator checks whether the mutated and original values match up to the specified threshold. If they do, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_FUZZY_EQUALS",  "${mutated.http.response.body}", "${original.http.response.body}",  data={“level”:5,“content-type”: “application/json”, “threshold”: 0.8})

This evaluates to True if the body of the response received for the mutated request matches (at least up to the threshold value of 80%) with the response received for the original request - up to a depth of 5 for the JSON encoded tree.

MATCH_OPERATOR_FUZZY_NOT_EQUALS

This operator checks whether the mutated and original values do not match up to the specified threshold. If they do not, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_FUZZY_NOT_EQUALS",  "${mutated.http.response.body}", "${original.http.response.body}",  data={“level”:5,“content-type”: “application/json”, “threshold”: 0.8})

This evaluates to True if the body of the response received for the mutated request does not match (at least up to the threshold value of 80%) with the response received for the original request - up to a depth of 5 for the JSON encoded tree.

MATCH_OPERATOR_FUZZY_KEYS_EQUALS

This operator checks whether the mutated and original values are JSON/URL-encoded parseable and the keys match up to the specified threshold. If they do, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_FUZZY_KEYS_EQUALS",  "${mutated.http.response.body}", "${original.http.response.body}",  data={“level”:5,“content-type”: “application/json”, “threshold”: 0.8})

This evaluates to True if the keys in the body of the response received for the mutated request matches (at least up to the threshold value of 80%) with the keys in the body of the response received for the original request - up to a depth of 5 for the JSON encoded tree.

MATCH_OPERATOR_FUZZY_KEYS_NOT_EQUALS

This operator checks whether the mutated and original values are JSON/URL-encoded parseable and the keys match up to the specified threshold. If they do, the assertion evaluates to False/Not Vulnerable; otherwise, it evaluates to True/Vulnerable.

Example:

Assertion.create("http.response.body",  "MATCH_OPERATOR_FUZZY_KEYS_NOT_EQUALS", "${mutated.http.response.body}",  "${original.http.response.body}", data={“level”:5,“content-type”: “application/json”, “threshold”: 0.8})

This evaluates to True if the keys in the body of the response received for the mutated request does not match (at least up to the threshold value of 80%) with the keys in the body of the response received for the original request - up to a depth of 5 for the JSON encoded tree.

MATCH_OPERATOR_VALUES_DIFFERENCE

This operator checks if the absolute difference between the mutated and original value is a certain amount.

Example:

Assertion.create("http.request.query.param.id",  "MATCH_OPERATOR_VALUES_DIFFERENCE", "${mutated.http.request.query.param.id}",  "${mutated.http.respose.param.id}", data={“level”:5,“content-type”: “application/json”, “amount”: 100})

This evaluates to True if the query param id of the mutated request differs from the response parameter id by a value of 100.

MATCH_OPERATOR_VALUES_SEARCH

This operator searches for the original value in the mutated value. The mutated value can be a dictionary or a URL-encoded payload. The level specified in this operator signifies the max depth till which Traceable should look at in the tree structure like JSON. If the original value is found in the mutated one, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.request.query.param.id",  "MATCH_OPERATOR_VALUES_SEARCH", "${mutated.http.response.body}", "15",  data={“level”:5,“content-type”: “application/json”})

This evaluates to True if the body of the response received for the mutated request contains the value 15 - up to the depth 5 for the JSON encoded tree.

MATCH_OPERATOR_VALUES_NOT_SEARCH

This operator searches for the original value in the mutated value. The mutated value can be a dictionary or a URL-encoded payload. The level specified in this operator signifies the max depth till which Traceable should look at in the tree structure like JSON. If the original value is not found in the mutated one, the assertion evaluates to True/Vulnerable; otherwise, it evaluates to False/Not Vulnerable.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_VALUES_NOT_SEARCH",  "${mutated.http.response.body}", "${mutated.http.request.query.param.id}",  data={“level”:5,“content-type”: “application/json”})

This evaluates to True if the body of the response received for the mutated request does not contain the query param id of the original request - up to a depth of 5 for the JSON encoded tree.

MATCH_OPERATOR_REGEXLOOKUP_EQUALS

This operator works in two steps:

  1. Lookup for all attributes matching the mutated regex and use them in step 2.

  2. If all attributes matched in step 1, match the original value, return True/Vulnerable; otherwise, return False/Not Vulnerable.

Example:

Assertion.create("http.response.body", "MATCH_OPERATOR_REGEXLOOKUP_EQUALS",  "mutated.http.response.body.*.carid", "15")

This evaluates to True if all parameters that match the specified regex in response to the mutated request contains the value 15.

MATCH_OPERATOR_REGEXLOOKUP_NOT_EQUALS

This operator works in two steps:

  1. Lookup for all attributes matching the mutated regex and use them in step 2.

  2. If all attributes matched in step 1, do not match the original value, return True/Vulnerable; otherwise, return False/Not Vulnerable.

Example:

Assertion.create("http.response.body",  "MATCH_OPERATOR_REGEXLOOKUP_NOT_EQUALS",  "mutated.http.response.body.*.carid", "15")

This evaluates to True if all parameters that match the specified regex in response to the mutated request does not contain the value 15.

MATCH_OPERATOR_REGEXLOOKUP_MATCHES_REGEX

This operator works in two steps:

  1. Lookup for all attributes matching the mutated regex and use them in step 2.

  2. If all attributes matched in step 1, match the original regex, return True/Vulnerable; otherwise, return False/Not Vulnerable.

Example:

Assertion.create("http.response.body",  "MATCH_OPERATOR_REGEXLOOKUP_MATCHES_REGEX",  "mutated.http.response.body.*.carid", "141[a-z0-9]{1,10}411")

This evaluates to True if all parameters that match the specified regex in response to the mutated request contains a value of that matches the regex ("141[a-z0-9]{1,10}411").

MATCH_OPERATOR_REGEXLOOKUP_NOT_MATCHES_REGEX

This operator works in two steps:

  1. Lookup for all attributes matching the mutated regex and use them in step 2.

  2. If all attributes matched in step 1, do not match the original regex, return True/Vulnerable; otherwise, return False/Not Vulnerable.

Example:

Assertion.create("http.response.body",  "MATCH_OPERATOR_REGEXLOOKUP_NOT_MATCHES_REGEX",  "mutated.http.response.body.*.carid", "141[a-z0-9]{1,10}411")

This evaluates to True if all parameters that match the specified regex in response to the mutated request does not contain a value of that matches the regex ("141[a-z0-9]{1,10}411").

MATCH_OPERATOR_ALWAYS_TRUE

This operator always returns True/Vulnerable. It is mostly useful when you are writing plugins and want to test dummy assertions.

Example:

Assertion.create("test.true", "MATCH_OPERATOR_ALWAYS_TRUE", "xyz", "abc")

MATCH_OPERATOR_ALWAYS_FALSE

This operator always returns False/Not Vulnerable. It is mostly useful when you are writing plugins and want to test dummy assertions.

Example:

Assertion.create("test.false", "MATCH_OPERATOR_ALWAYS_FALSE", "xyz", "abc")

MATCH_OPERATOR_COLLABORATOR_LOOKUP_CONTAINS

This operator is used for SSRF-based scans, where if the application reaches out to Traceable collaborator, it looks out for the presence of test id in the payload received by the collaborator.

Example:

Assertion.create("http.response.body",  "MATCH_OPERATOR_COLLABORATOR_LOOKUP_CONTAINS", "${mutated.test.id}", "${mutated.test.id}")

This evaluates to True if the payload (from the application) received by the collaborator contains the test id.

MATCH_OPERATOR_RAW

This operator executes raw lambda code supplying it with mutated and original values. If lambda returns True, it is marked as Vulnerable, else Not Vulnerable.

Example:

Assertion.create("tls.protocol.ciphers", "MATCH_OPERATOR_RAW", "${mutated.tls.protocol.ciphers}", "RSA", data={ "code": 'lambda x,y: any([y in n for n in x.split(" ")])' })


Was this article helpful?

What's Next