API Selection Filters
This section describes the conditions
that act as selection criteria for choosing APIs that are eligible for a particular test. It also filters out APIs that are not eligible.
Example:
# THIS IS API SELECTION FILTER
api_selection_filters:
response_code:
gte: 200
lt: 300
url:
belongs_to_collections:
- payment
- checkout
- juiceshop.akto.io
contains_either:
- login
- signin
- sign-in
- log-in
request_payload:
for_one:
key:
contains_either:
- password
- pwd
- pass
- passwd
request_headers:
for_one:
key:
contains_either: cookie
extract: header_key
Syntax
Parent Operators
Data Operators
Collection Operators
Combining Conditions using Boolean Operators
Parent Operators
Each condition
block begins with a parent operator. Parent Operators indicate the property of the API
you are testing. All the conditions will apply to these parent operators. Parent Operators can have the following values:
response_code
This denotes that the conditions will be applied on response code of the api
method
This denotes that the conditions will be applied on http method of the api
url
This denotes that the conditions will be applied on http url of the api
request_payload
This denotes that the conditions will be applied on request payload of the api
response_payload
This denotes that the conditions will be applied on response payload of the api
request_headers
This denotes that the condition will be applied on request headers of the api
response_headers
This denotes that the condition will be applied on response headers of the api
query_param
This denotes that the condition will be applied on query params of the api
Data Operators
Each Parent Operator should contain one or more Data Operators
that describe the exact condition to be applied to the Parent Property. Data Operators can have the following values:
belongs_to_collections
List
Checks whether the parent property belongs to one of the specified collections in the list. The API must be part of at least one of the collections specified to satisfy this condition.
contains_either
List/Non List
Checks whether the parent property contains the specified input. If input is an array, any one of the input element should satisfy this condition.
contains_all
List/Non List
Checks whether the parent property contains the specified input. If input is an array, all of the input element should satisfy this condition.
regex
List/Non List
Checks whether the parent property contains a match for the regex specified in the specified input. If input is an array, one of the regex input should have a match
eq
Non List
Checks whether the parent property is equal to the specified input.
neq
Non List
Checks whether the parent property is not equal equal to the specified input.
gt
Non List
Checks whether the parent property is greater than to the specified input.
gte
Non List
Checks whether the parent property is greater than equal to the specified input.
lt
Non List
Checks whether the parent property is lesser than the specified input.
lte
Non List
Checks whether the parent property is lesser than equal to to the specified input.
not_contains
List/Non List
Checks whether the parent property does not contain the specified input. If input is an array, all of the input element should satisfy this condition.
not_contains_either
List/Non List
Checks whether the parent property does not contain the specified input. If input is an array, any one of the input element should satisfy this condition.
contains_jwt
boolean
Checks whether the parent property contains/not contains a jwt token
cookie_expire_filter
boolean
Checks if the cookie expires in next 30 days
belongs_to_collections
belongs_to_collections
Checks whether the parent property belongs to one of the specified collections in the list. The API must be part of at least one of the collections specified to satisfy this condition.
Example 1
url:
belongs_to_collections:
- payment
- checkout
# APIs that belong to either the payment or checkout collection would match the above condition.
# Match Example - An API categorized as part of the payment collection
# Invalid Example - An API that belongs only to the auth collection
contains_either
contains_either
Checks whether the parent property contains the specified input. If input is an array, any one
of the input element should satisfy this condition.
Example 1
url:
contains_either: login
# Endpoints that contain login substring would match the above condition.
# Match Example - https://xyz.com/user/login
# Invalid Example - https://xyz.com/user/register
Example 2
url:
contains_either:
- https
- login
# Endpoints that contain either https or login substring would match the above condition.
# Match Examples - https://xyz.com/user/login | https://xyz.com/user/register
# Invalid Example - http://xyz.com/user/data
contains_all
contains_all
Checks whether the parent property contains the specified input. If input is an array, all
of the input mlelement should satisfy this condition.
Example 1
url:
contains_all: login
# Endpoints that contain login substring would match the above condition.
# Match Example - https://xyz.com/user/login
# Invalid Example - https://xyz.com/user/register
Example 2
url:
contains_all:
- https
- login
# Endpoints that contain both https and login substring would match the above condition.
# Match Example - https://xyz.com/user/login
# Invalid Example - http://xyz.com/user/login | https://xyz.com/user/register
regex
regex
Checks whether the parent property contains a match for the regex
specified in the specified input. If input is an array, one of the regex input should have a match.
Example 1
request_payload:
contains_either: .*user*.
# If any part of request payload matches the above regex, it would be considered a match.
# Match Example - {”id”: 123, “data”:{”userName”: “abc”}} - userName is a valid match for above regex
# Invalid Example - {”id”: 123, “data”:{”name”: “abc”}} - no part of the request payload matches the above regex
eq
eq
Checks whether the parent property is equal to the specified input.
Example 1
method:
eq: POST
# All the Post Endpoints will match the above condition.
# Match Example - POST https://xyz.com/getById
# Invalid Example - GET https://xyz.com/getById
gt
gt
Checks whether the parent property is greater than the specified input.
Example 1
response_code:
gt: 204
# Endpoints with response greater than 204 will match the above condition.
# Match Example - Response codes like 205, 302
# Invalid Example - Response codes like 200, 201
gte
gte
Checks whether the parent property is greater than or equal to the specified input.
Example 1
response_code:
gte: 204
# Endpoints with response greater than or equal to 204 will match the above condition.
# Match Example - Response codes like 204, 302
# Invalid Example - Response codes like 200, 201
lt
lt
Checks whether the parent property is lesser than the specified input.
Example 1
response_code:
lt: 204
# Endpoints with response less than 204 will match the above condition.
# Match Example - Response codes like 200, 201
# Invalid Example - Response codes like 204, 205
lte
lte
Checks whether the parent property is lesser than or equal to the specified input.
Example 1
response_code:
lte: 204
# Endpoints with response less than or equal to 204 will match the above condition.
# Match Example - Response codes like 200, 204
# Invalid Example - Response codes like 205, 302
not_contains
not_contains
Checks whether the parent property does not contain the specified input. If input is an array, all of the input element should satisfy this condition.
Example 1
response_payload:
not_contains:
- "normal_user"
- "new"
# Response Payloads not containing strings ("normal_user", "new") will match the above condition.
Match Example for above
{"id": 100, "userdata": {"name": "xyz", "status": "admin", "identifier": "old"}}
Invalid Example for above
1. {"id": 100, "userdata": {"name": "xyz", "status": "normal_user", "identifier": "old"}}
2. {"id": 100, "userdata": {"name": "xyz", "status": "admin", "identifier": "new"}}
3. {"id": 100, "userdata": {"name": "xyz", "status": "normal_user", "identifier": "new"}}
not_contains_either
not_contains_either
Checks whether the parent property does not contain the specified input. If input is an array, any one of the input element should satisfy this condition.
Example 1
response_payload:
not_contains_either:
- "normal_user"
- "new"
# Response Payloads which does not contain either ("normal_user") or ("new") will match the above condition.
# Match Example -
1. {"id": 100, "userdata": {"name": "xyz", "status": "admin",
"identifier": "old"}}
2. {"id": 100, "userdata": {"name": "xyz", "status": "normal_user",
"identifier": "old"}}
3. {"id": 100, "userdata": {"name": "xyz", "status": "admin",
"identifier": "new"}}
# Invalid Example -
1. {"id": 100, "userdata": {"name": "xyz", "status": "normal_user",
"identifier": "new"}}
contains_jwt
contains_jwt
Checks whether the parent property contains/not contains a JWT token.
Example 1
request_headers:
for_one:
value:
contains_jwt: true
# Request Headers which contain jwt token will match the above condition.
# Match Example -
1. Headers -
Content-Type: application/json
Authorization: <Bearer-Token>
# Invalid Example -
1. Headers -
Content-Type: application/json
Authorization: 23sdf234r3aaa
Collection Operators
These operators are useful for queries that involve individual keys and values in payloads and headers, rather than applying the condition to the entire payload as a string. To achieve the desired result, they must be combined with a data operator.
for_one
for_one
This collection operator is used to imply that either of key
or value
in the entire payload should satisfy the condition.
Example 1
Request Payload {”id”: 123, “data”:{”Username”: “abc”}}
Let’s say we want to check if there is a key present in request payload which contains name. We can represent that in the following yaml syntax -
api_selection_filters:
request_payload:
for_one:
key:
contains_either: name
# ”for_one” here specified that the condition is applied on key.
# Data operand 'contains_either' checks whether any key in the request payload contains string (”name”)
Example 2
Request Payload {”id”: 123, ”status”: “admin”, “createdAt”: 1688364964}
Let’s say we want to check if there is a key
present in request payload which is equal to status
, and contains a value
like (admin
). We can represent that in the following yaml syntax -
api_selection_filters:
request_payload:
for_one:
key:
eq: status
value:
regex: .*admin.*
# ”for_one” here specified that the condition is applied on both key and value.
# Data operand 'eq' checks whether any key in the request payload is exactly equalt to (”status”).
# Data operand 'regex' checks whether any value in the status key matches the provided regex.
Matching Payloads
{”id”: 123, ”status”: “admin”, “createdAt”: 1688364964}
{”status”: “administrator”, “active”: true}
{”userInfo”: {”name”: “testUser”, “status”: “admin”}, “lastLoginTs”: 1688364964}
Invalid Examples
{”id”: 123, “createdAt”: 1688364964}
{”id”: 123, ”status”: “normal”, “createdAt”: 1688364964}
{”id”: 123, ”access”: “admin”, “status”: “active”}
Here key is named status, and a value matches regex .*admin*., but there is no single key value pair which satisfies both conditions.
Body Operators
These operators are useful for applying conditions specifically on request payload, response payload strings. To achieve the desired result, they must be combined with a data operator. Currently there are 2 types of body operators -
length
length
Length operator is used for applying conditions on the request/response payload length. Let’s explore this more through the below example
#Example 1
request_payload:
length:
gt: 0
# Here we want to apply a condition, where api's should have a non-empty request payload.
# We use length operator, and combine it with data operator(gt), where we specify length to be greater than 0
#Example 2
response_payload:
length:
gte: 10
# Here we want to apply a condition, where api's should have a non-empty response payload.
# We use length operator, and combine it with data operator(gt), where we specify length to be greater than equal to 10
Extract Operators
extract
extract
These operators can be used to save parent entity’s value into a variable at any point during the api_selection_filters phase, which can be used later on in the test template yaml using ${}
notation. Let’s see it in action in the below example -
#Example 1
url:
contains_either: https
extract: urlVar
# Here we have defined an extract operator, which will copy the complete url into a new variable named urlVar, in case the contains_either operand satisfies the condition
#Example 2
method:
extract: methodVar
# Here we have defined an extract operator, which will copy the http method values into a new variable named methodVar
We can also extract an individual key/value inside the parent entities like (request_payload, response_payload, request_headers, response_headers, query_params).
Request Payload** {”id”: 123, “data”:{”Username”: “abc”, "userStatus": "admin"}}
#request_payload:
for_one;
key:
contains_either: status
extract: keyVar
# Here we have defined an extract operator, which will copy the key("userStatus") into a new variable named keyVar, since ("userStatus") satisfies the contains_either operand. In simple words - keyVar = userStatus
Request Payload** {”id”: 123, “data”:{”Username”: “abc”, "userStatus": "admin"}}
request_payload:
for_one;
key:
contains_either: status
extract: keyVar
value:
extract: valVar
# Here we have defined an extract operator, which will copy the key("userStatus") into a new variable named keyVar, since ("userStatus") satisfies the contains_either operand.
# We also defined a second extract operator inside value operand, which will copy the value associated with the matching key("userStatus") into the variable, i.e. ("admin").
# In other words - keyVar = userStatus, valVar = admin
How to use extracted variables in YAML
You can use ${<VAR_NAME>}
to refer the extracted value. Eg. you can use extracted urlVar
do the following -
#Here we append /debug/vars to the URL to check if debug variables are exposed.
api_selection_filters:
url:
extract: urlVar
execute:
type: single
requests:
- req:
- modify_url: ${urlVar}/debug/vars
validate:
...
extractMultiple
extractMultiple
This is similar to extract
, except it can extract a list of values. For example, if you need a list of all keys in the API request JSON, you can use extractMultiple
operator. Using extract
will just extract the first key. #Example 1
#Example of extractMultiple
api_selection_filters:
request_payload:
for_one:
key:
regex: .*
extractMultiple: payloadKeys # Here we extract list of all keys in the payload
execute:
type: single
requests:
- req:
- add_body_param:
${payloadKeys}: '\0' #Here we replace all values by null terminated string
Combining conditions using Boolean Operators
Security tests can be complex in nature. Often, a specific test requires multiple filter conditions to evaluate whether a given endpoint is eligible for the test.
Default Behavior
For a test to consider an endpoint valid, all conditions
specified in the YAML template must be satisfied. By default, yaml considers and
operator for all conditions. However, you can easily override this behavior using other boolean operators.
Boolean Operators
Boolean operators are of 2 types:
and
and
The and
operator requires all of the specified conditions to be satisfied, which is also the default
behavior. It can be applied on top of any operator, including data
, collection
, and parent
operands.
Example 1
#Test Description -
# condition 1: Consider only post endpoints.
# condition 2: Status code must be between 200-205(including both)
# condition 3: Request Headers should contain a header named origin.
# All conditions are mandatory.
api_selection_filters:
and:
- method:
eq: POST
- response_code:
and:
- gte: 200
- lte: 205
- request_headers:
for_one:
key:
eq: origin
Since applying and
operator is default behaviour, we don’t need to explicitly write and
operator. See below
# removed 'AND' as it is default behavior
api_selection_filters:
method:
eq: POST
response_code:
gte: 200
lte: 205
request_headers:
for_one:
key:
eq: origin
or
or
The OR operator requires that at least one of the specified conditions is satisfied. It can be applied to any operator, including data, collection, and parent operands.
Example 1
# Test Description
# condition 1: Status code must be equal to either 200 or 302
# condition 2: Request Headers should contain a header named origin.
# An endpoint should either satisfy either of the above two conditions
api_selection_filters:
or:
- response_code:
or:
- eq: 200
- eq: 302
- request_headers:
for_one:
key:
eq: origin
Last updated
Was this helpful?