Using Webhooks - Start DevSecOps

How to use webhooks to script the Crashtest Security Suite functionalities. Allows integration in your continuous integration / continuous deployment (CI/CD) pipeline to pentest every release.

To run an automated security scan after a deployment (or other triggers), you can create a custom webhook in the project settings. This page explains how to create a webhook and the different payloads that you can execute.

We also have a complete example of a Circle CI pipeline setup, an app that is deployed via Circle CI, as well as running our scans for every deployment here. You can also define different rules for passing or failing builds.

Generating a webhook

Go to the project settings page and scroll down to the webhook settings in the Automation section. Click on "Generate" to create a new webhook for the project.

Screenshot 2020-04-02 at 15.50.21

You can now send a POST request to the webhook whenever you want to start a scan for the project. The following examples show how to send the request.

Send Webhook

The following section explains how to trigger the webhook in the following software:

  • cURL
  • Heroku
  • TeamCity

cURL

To run the webhook manually, you can use the following cURL command. To start the scan from a shell script, integrate this command:

curl -X POST --data "" https://api.crashtest.cloud/webhook/SECRET_HASH

Heroku

You can set up Heroku to automatically call the webhook after a successful deployment:

heroku addons:create deployhooks:http --url=https://api.crashtest.cloud/webhook/SECRET_HASH

TeamCity

In TeamCity you can create a new build step where you run the webhook:

TeamCity Webhook Integration

Webhook Payload

It is possible to send a payload which contains authentication data and/or the Swagger file when using an API scan. This data will be used to configure your project before starting the scan. Please note that previous user credentials will be overwritten and the credentials will be stored for the next scan. To send a webhook request with payload data you may use the following request:

curl --data '{
"system_authentication": {
"basic_auth": {
"username": "username",
"password": "password"
}
},
"application_authentication": [
{
"username": "username",
"password": "password",
"url": "example.com/login"
}
],
"parameter_authentication": [
{
"type": "HEADER",
"key": "Authorization",
"value": "Bearer 12345678"
}
],
"specs": {
"api_spec": {
"swagger": "2.0",
"info": [],
"host": "api.example.com",
"basePath": "/v1",
"schemes": [
"https"
],
"paths": []
}
}
}' -X POST https://api.crashtest.cloud/webhook/SECRET_HASH

Please note, that you can send a full API Specification file such as Swagger or OpenAPI file as part of the api_spec section.

The part application_authentication is not available for use with API scan targets as a ui-based login form cannot be mixed with the scanning of APIs.Manual Login Flow

Let's assume that you have an REST API at https://example.com/api/v1 which uses JWT Tokens for authentication. The token is generated by a POST request to /login with the username 'username' and the password 'password'.

$ curl --data '{"username": "username", "password": "password"}' -X POST https://example.com/api/v1/login

{
"token_type": "Bearer",
"expires_in": 86400,
"access_token": "ABCDEF",
"refresh_token": "ABCDEF",
"concurrent_sessions": 1,
"max_current_sessions": 40,
}

You may use this to generate a script which logs you in before starting the security scan. The token generated by the login request is then used for the security scan.

ACCESS_TOKEN=`curl --data '{"username": "username", "password": "password"}' -X POST https://example.com/api/v1/login | jq -r '.access_token'`
curl --data "{
\"parameter_authentication\": [
{
\"type\": \"HEADER\",
\"key\": \"Authorization\",
\"value\": \"Bearer $ACCESS_TOKEN\"
}
]
}" -X POST https://api.crashtest.cloud/webhook/SECRET_HASH

Responses

The following json responses inform you about the result of the webhook call:

{"message": "webhook_scan_started", "data": {"scanId": SCAN_ID}}    # Success Case
{"message": "Scan is already running"} # Failure Case

Retrieve Scan Report using Webhook

You can not only start the scan using a webhook but also retrieve the report as JUnit XML format. The following script will start the scan for your project and periodically poll the status of the scan. When the scan is finished, the report will be downloaded to the file report.xml. For this script to run properly, you will need to have the following requirements installed: curl, jq

#!/usr/bin/env sh


# TODO: Set WEBHOOK to webhook ID (without URL)
WEBHOOK="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"


API_ENDPOINT="https://api.crashtest.cloud/webhook"

# Start Scan and get scan ID
SCAN_ID=`curl --silent -X POST --data "" $API_ENDPOINT/$WEBHOOK | jq .data.scanId`
echo "Started Scan for Webhook $WEBHOOK. Scan ID is $SCAN_ID."

# Refresh Scan status
STATUS="100"
while [[ $STATUS -le "101" ]]
do
echo "Scan Status currently is $STATUS (101 = Running)"
# Only poll every minute
sleep 60

# Refresh status
STATUS=`curl --silent $API_ENDPOINT/$WEBHOOK/scans/$SCAN_ID/status | jq .data.status.code`
done

echo "Scan finished with status $STATUS."

# Download Report
curl --silent $API_ENDPOINT/$WEBHOOK/scans/$SCAN_ID/report/junit -o report.xml
echo "Downloaded Report to report.xml"