Workshop "How to write custom security tests" - Main Takeaways
Organizations are constantly seeking ways to improve their defenses against business logic vulnerabilities. These vulnerabilities, often difficult to detect, can lead to significant security breaches if left unchecked. To address this challenge, we've introduced a new feature within our platform that empowers teams to create custom business logic tests for APIs, enabling the identification and remediation of security flaws at scale.
To explain how to get started with custom security tests, we held a hands-on workshop for our community. Here’s the video if you’d like to watch it on YouTube:
In this article, we will cover the essential steps we went through during the workshop. These steps are crucial to consider when if you want to start writing your custom security tests with Escape.
The challenge of traditional business logic tests
Traditional business logic tests are often rigid, requiring extensive maintenance and hard-coded data. This approach is not only time-consuming but also fails to adapt to changes in APIs or underlying databases. As a result, these tests quickly become obsolete, leaving APIs vulnerable to new threats.
To overcome these limitations, we've developed a new language that simplifies the creation of business logic tests. This language is designed to be user-friendly for both security engineers and developers, allowing for the efficient testing of APIs.
How the custom test language works
Our custom test language consists of several key components:
- Alert Block: This is where you define the nature of the vulnerability and its severity. This block is informative, describing the vulnerability for user feedback.
- Seed Block: This allows you to guide the scanner to test specific aspects of your API, akin to hot-starting a scan. Force a visit to a particular endpoint/domain.
- Detect Block: The core of the test, where you can interpret the final request/response and where the conditions for triggering an alert are specified.
- Transform Block: Here, you can specify how to modify and resend a request/response based on certain triggers, such as detecting an object or a specific route.
Integrate the inference engine to provide context to the manipulated data, thus making it accessible to the testing language.
The language is built on YAML, making it accessible and easy to use. It includes a variety of operators and helpers that allow you to focus on the business logic rather than the intricacies of the API's technical implementation.
Real-world applications and benefits
The flexibility of our custom test language enables you to address a wide range of vulnerabilities, including tenant isolation issues, mass assignment vulnerabilities, and misconfigurations in frameworks like Spring Boot. It also allows for the easy replication of pen test findings, ensuring that vulnerabilities are not reintroduced in future updates.
Here are several examples from the presentation:
Order processing feature vulnerability
A common vulnerability in e-commerce platforms is the acceptance of unreasonable order quantities. A custom test can be created to detect if an API endpoint responsible for processing orders allows for the submission of excessively large quantities. By mutating the quantity parameter to an abnormally high value and checking the response, the test can identify if there is a lack of proper validation in place:
Mass Assignment Vulnerability
Mass assignment vulnerabilities occur when an API endpoint accepts additional, unexpected fields in the request payload, potentially leading to unauthorized changes. A custom test can detect this by adding unexpected properties to the request body, such as an "isAdmin" flag set to true, and observing if the API improperly processes these properties:
Framework Misconfiguration: Spring Boot Actuator
Frameworks like Spring Boot can sometimes expose sensitive information through endpoints like the actuator, which are not always documented. A custom test can be crafted to specifically target these endpoints, even if they are not part of the documented API, to ensure they are not publicly accessible or leaking sensitive data:
alert:
name: Exposed Spring Boot Actuator Endpoint
context: A Spring Boot Actuator endpoint is publicly accessible and could reveal
sensitive information.
severity: HIGH
detect:
- if: response.status_code
is: 200
transform:
mutate:
- key: schema.path_ref
value: /actuator/beans
trigger:
- if: scan.type
is: REST
Email Domain Validation
This test focuses on validating that an API properly handles email inputs, particularly in fields labeled as "admin email." By using regular expressions to mutate the domain part of the email address, the test can check if the API is correctly validating email domains and preventing unauthorized domain usage:
transform:
trigger:
- if: schema.url
is: "/api/v1/tested/route"
mutate:
- key: request.object
select:
type:
is: email
name:
is: "admin_email"
value:
regex: .*@escape.tech
mutate:
regex_replace:
pattern: (.*)@escape.tech
replacement: \1@attacker.com
Tenant Isolation
Tenant isolation is crucial in multi-tenant environments to prevent users from accessing data belonging to other tenants. Custom tests can be created to simulate requests from different users, ensuring that each tenant's data remains isolated and inaccessible to others. This is particularly important for SaaS applications where data segregation is a key security concern:
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
Admin Route Accessibility
This test verifies that administrative routes or endpoints are not accessible to non-admin users. By attempting to access URLs with "admin" in the path using a non-admin user's credentials, the test can identify if proper access controls are in place to restrict sensitive areas of the API:
alert:
name: V2 API with V1 tokens
context: >
Your current API seems to be confused between V1 and V2 endpoints.
severity: LOW
detect:
- if: helpers.response.is_successful
is: true
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
These examples demonstrate the versatility and power of custom business logic tests. By abstracting the complexities of API testing, our language allows security teams to focus on the logic and behavior of their APIs, ensuring that they can quickly and effectively identify and remediate vulnerabilities.
Collaborating with the community
We've launched Escape’s public custom rules repository where users can share and collaborate on custom rules, further enhancing the platform's capabilities. This community-driven approach ensures that our platform remains at the forefront of API security.
Looking ahead
Our roadmap includes exciting features such as Git synchronization and bulk import/export capabilities. We're also working on extending custom rule creation to APIs in the inventory, allowing for the detection of vulnerabilities in shadow APIs.
Conclusion
The introduction of custom business logic tests represents a significant leap forward in API security. By providing an easy-to-use language and a platform that automates the testing process, we empower organizations to secure their APIs against business logic vulnerabilities effectively. We encourage you to try out this feature, share your rules with the community, and join us in our mission to create more secure applications.
For more information or to discuss your specific use cases, feel free to reach out to us or join our community. We're here to assist you in leveraging the full potential of custom business logic tests for your API security needs!
💡 Want to explore more? Check out the following articles and webinars: