Custom Rules
As you already know, Escape's built-in tests are pretty extensive and cover a lot of security vulnerabilities and concerns. But we know that you might have very specific use-cases, and that's why we've made it possible for you to create your own custom rules.
These will enable you to build your own governance and apply it at scale, in a simple language that is powerful thanks to Escape's inference engine.
Format¶
A custom rule is a YAML file that defines the following blocks:
- Alerting is used define the alert format, it's severity…
- Detectors are used to detect if an alert must be raised by inspecting queries.
- Transformations are used to mutate the requests (optional).
- Mutators are used inside the transformations.
- Seeders are used to seed the scan with requests (optional).
Examples¶
Minimal example¶
alert:
name: Deletion successful
context: >
For compliance reasons, the non admin user must not be able to delete some
data via the API.
severity: HIGH
detect:
- if: helpers.request.crud
is: DELETE
- if: request.user
is_not: admin
- if: helpers.response.is_successful
is: true
Mutated example¶
If you want to improve the above example, you can force escape to try to delete the resource by adding a mutation block:
transform:
trigger:
- if: helpers.request.crud
is: CREATE
- if: schema.path_ref
is: /record
- if: request.user
is_not: admin
mutate:
- key: request.method
value: DELETE
- key: request.body.json
jq: '{"id": .id}' # only keep the id in the delete body
alert:
name: Deletion successful forced
context: >
For compliance reasons, the non admin user must not be able to delete some
data via the API.
severity: HIGH
detect:
- if: helpers.request.crud
is: DELETE
- if: request.user
is_not: admin
- if: helpers.response.is_successful
is: true
Seeded example¶
seed:
- protocol: http
raw: |
@Host: https://backend-api.escape.tech
GET /data HTTP/1.1
Host: backend-api.tools.escape.tech
alert:
name: Environment isolation
context: >
Tested API may call the backend API, but customers must not be able to
access the backend API directly.
severity: MEDIUM
detect:
- if: helpers.response.is_successful
is: true
Seeded¶
transform:
trigger:
- if: helpers.response.is_successful
is: true
- if: request.headers
key:
is: X-API-Version
value:
is: V2
mutate:
- key: request.headers
name: X-API-Version
value: V1
alert:
name: V2 API with V1 tokens
context: >
Your current API seems to be confused between V1 and V2 endpoints.
For compliance reasons, an API must only be deployed with one version.
severity: LOW
detect:
- if: helpers.response.is_successful
is: true
Enforce all mutation requests to be authenticated¶
If you want to raise an alert on any successful unauthenticated mutation request, you can use the following example:
detect:
# If the request is a data mutating action (CREATE, UPDATE, DELETE)
- if: helpers.request.crud
is_not: READ
# AND the user is unauthenticated ('public' in Escape Platform means unauthenticated)
- if: request.user
is: public
# AND the request succeeded
- if: helpers.response.is_successful
is: true
# Then raise an alert
alert:
name: Mutations should be authenticated
context: >
All mutations should be authenticated, otherwise it might be possible to
perform actions without being noticed.
severity: MEDIUM
SQL Injection Detection¶
Here is an example of a custom rule that detects SQL injection attacks:
- It will target requests with emails or passwords in the query
- It will replace their content with an SQL injection payload
- Finally, it will check if the response indicates a SQL injection vulnerability
transform:
trigger: # This will select which requests to fuzz
# We want a request that worked
- if: helpers.response.is_successful
is: true
# AND with a parameter that we want to fuzz
- if: request.object
type:
in:
- email
- password
mutate:
# We will select all the emails and passwords in the request
- key: request.object
select:
type:
in:
- email
- password
mutate:
# And replace them with SQL injection payloads
values:
- "' OR 1=1"
- "' OR 1=1 --"
# ... other SQL injection payloads
detect:
# Finally, we will check if the response contains any of these keywords
- if: response.body.text
contains:
- "syntax error"
- "SQL error"
- "ORA-"
- "mysql_fetch"
# ... other SQL injection detection keywords
alert:
name: SQL Injection Vulnerability
context: >
The API endpoint is potentially vulnerable to SQL injection attacks,
which could allow attackers to access or modify sensitive database information.
severity: MEDIUM
Missing Security Headers¶
By default, Escape will raise an alert if a request is missing common security headers. If you want to raise an alert on other headers, you can use the following example:
detect:
- if: response.headers
key:
is: X-API-Version
value:
is_not: V2
alert:
name: Missing Security Headers
context: >
The API endpoint is missing the `X-API-Version` required security header.
severity: MEDIUM
Excessive Data Exposure¶
If you want to enforce that a specific key of a JSON will never be exposed, you can use the following example:
detect:
- if: response.body.json
is:
jq: '.admin != null'
alert:
name: Exposed Admin Data
context: >
The API endpoint is exposing admin data. It should be filtered out before returning the response.
severity: MEDIUM
Properties¶
id
: The unique identifier of the custom rule. It is provided by Escape, do not set it manually.seed
: A list of requests to seed the scan. See Seederstransform
: Defines lists of triggers and mutations (combined with AND operators).See Transformationsdetect
: The conditions to trigger the alert. See Detectorsalert
: The alert to raise if the detection conditions are met. See [Alerting]01-alerting.md)
Index¶
- Alerting
- Detectors
- Transformations
- Mutators
- Seeders
- Custom Rules Reference