Sqreen Webhooks

Webhooks v1 deprecated

Sqreen Webhooks v1 is deprecated. However, the documentation remains available.

Use Sqreen Webhooks to send Sqreen security data to a third-party tool. In your Sqreen Dashboard, you can configure the conditions in which Sqreen sends a notification to a third-party tool in the form of an HTTP POST request.

For example, when Sqreen detects that a user has repeatedly failed to login, it can POST a message to the Pager Duty REST API with the details of the security incident.

Configure a webhook

  1. In the Sqreen Dashboard, from the application to connect, navigate to Settings > Integrations.
  2. In the Webhook pane, enter the URL. It's the destination to which you wish to POST messages from Sqreen (https://example.com/postreceive).
  3. Retrieve the secret. This secret will be used to validate the message was emitted by Sqreen.
  4. Test, then Save the configuration.
  5. Navigate to your Protection modules to select a particular protection and adjust its settings to send data to the webhook URL. For example, navigate to Configuration > Runtime Application Self-Protection > Shell Injection. Use the interface to adjust the settings.
  6. If you use Security Automation Playbooks in Sqreen, navigate to Playbooks in your Sqreen Dashboard to create a new playbook and set the notification to send data to the webhook URL.

Webhook request specifications

The body of each request Sqreen sends to a third-party receiver is encoded in JSON, as indicated by the content-type application/json with UTF-8 encoding (as per RFC 4627). The maximum size of the array of payloads is 1000 events; Sqreen splits the payload into multiple requests if necessary.

The payloads of each HTTP POST request have the same basic structure.

  • message_id - unique ID of the webhook
  • api_version - version of the api
  • date_created - date in UTC (isoformat) indicating when Sqreen sent the request
  • message_type - type of message (see section below)
  • retry_count - number of times Sqreen sent the request
  • message - payload data

Message types

The message_type matches an object in the Sqreen Dashboard. The volume corresponds to the severity of the conditions which trigger Sqreen to send the notification/HTTP request (High, Medium, Low).

Message type Description Volume
security_event a security event as seen in the Sqreen Dashboard high
other an Incident as seen in the Sqreen Dashboard, such as a brute force attack low
security_response a security response that Sqreen sends when user activity triggers a playbook medium
test test payload on demand

Security event

Sqreen Webhook provides information about the following event categories:

Category Description
authentication user-related activity in your application
injection injection-related attacks occurring in your application
http_error HTTP scanners targeting your application
package vulnerable packages in your application

Each event category has sub-categories. The table below uses the example category authentication.

Sub-category Description
auth_ato_attempt targeted account takeover tentative
auth_ato_success successful account takeover
auth_new_location connection from a new location
auth_tor_tentative connection tentative from TOR
auth_multi_locations simultaneous connection from multiple locations

Each security event has the following message payload structure.

  • application_id
  • application_name
  • environment
  • date_occured
  • event_category
  • event_id
  • event_kind
  • event_url
  • humanized_description
  • ips: array of
    • address
    • date_resolved
    • city
    • country_code
    • geo_longitude
    • geo_latitude
    • is_tor
[{
  "message_id": "5de50f9bf681244a8cbf68f5",
  "api_version": "2",
  "date_created": "2019-12-02T13:18:21.708110+00:00",
  "message_type": "security_event",
  "retry_count": 0,
  "message": {
    "application_id": "587b23384891d57c1bf5bf4f",
    "application_name": "Demo app",
    "environment": "production",
    "date_occurred": "2016-12-21T07:22:32.732000+00:00",
    "event_category": "authentication",
    "event_id": "587b234e4891d57c1bf5c8c9",
    "event_kind": "auth_tor_tentative",
    "event_url": "https://my.sqreen.com/application/d8b47501fad44fb28d09967e1f1b09a258d85f4ba5d44e759b886f9663e7cf01/events/587b234e4891d57c1bf5c8c9",
    "humanized_description": "Connection to jeff45@harrell.com from TOR (135.96.171.118)",
    "ips": [
      {
        "address": "135.96.171.118",
        "date_resolved": "2017-01-15T07:22:54.573000+00:00",
        "geo": {
          "city": "Sag",
          "code": "ROU",
          "point": [
            21.283300399780273,
            46.04999923706055
          ]
        },
        "is_tor": true
      }
    ]
  }
}]

Other

An Incident (other message type) corresponds to a significant security event or group of events occurring in an application. Sqreen Webhook provides information about the following event categories:

Category Description
vulnerable_packages vulnerabilities detected in your dependencies
injection_* injection triggered by the RASP
http_scan a massive security scan has been {detected
user_risk_increased risk score of {account} exceeded {threshold}%
account_takeover successful account takeover attempt on user {account}

Each incident has the following message payload structure.

  • incident_thread (ID of the event)
  • incident_status (updated or created)
  • date_started
  • date_last_updated
  • application_id
  • new_related_ips: array of
    • address
    • date_resolved
    • city
    • country_code
    • geo_longitude
    • geo_latitude
  • new_compromised_account: array of
    • sqreen_id
    • user_identifiers
    • ip_address
{
  "message_id": "5de52295f68124623a7f16f5",
  "api_version": "2",
  "date_created": "2019-12-02T14:38:31.486469+00:00",
  "message_type": "account_takeover",
  "retry_count": 0,
  "message": {
    "incident_thread": "track_collection_7c21d0f112098078dc19ca458f74a184",
    "incident_status": "created",
    "date_started": "2019-12-02T13:34:42.908000+00:00",
    "date_last_updated": "2019-12-02T13:36:24.449000+00:00",
    "application_id": "587b23384891d57c1bf5bf4f",
    "new_related_ips": [
      {
        "address": "135.96.171.118",
        "date_resolved": "2017-01-15T07:22:54.573000+00:00",
        "geo": {
          "city": "Sag",
          "code": "ROU",
          "point": [
            21.283300399780273,
            46.04999923706055
          ]
        },
        "date_resolved": "2019-12-02T12:53:09.094000+00:00",
        "vpn": false,
        "proxy": false,
        "datacenter": false,
        "metadata": {
          "version": 4,
          "multicast": false,
          "private": false,
          "global": true,
          "unspecified": false,
          "reserved": false,
          "loopback": false
        },
        "tags": []
      }
    ],
    "new_compromised_accounts": [
      {
        "sqreen_id": "W1siZW1haWwiLCAiZm9vQGJhci5iYXoiXV0=",
        "user_identifiers": {
          "email": "foo@bar.baz"
        },
        "ip_address": "135.96.171.118"
      }
    ]
  }
}

Security response

Sqreen sends a security response payload each time user activity triggers a Security Automation Playbook.

Each incident has the following message payload structure.

  • application
    • name
    • environment
    • id
  • properties
    • ips
    • user_identifiers
  • playbook
    • name
    • id
[
  {
    "id": "5de51a89f681245ab970ad66",
    "message_type": "security_response",
    "retry_count": 2,
    "date_created": "2018-07-20T12:01:17.374627+00:00",
    "message": {
      "application": {
        "name": "Application name",
        "environment": "production",
        "id": "5a87625fcefe8b16933724"
      },
      "properties": {
        "ips": [
          {
            "ip_cidr": "172.17.0.1/32"
          }
        ],
        "user_identifiers": [
          {
            "email": "user@sqreen.com"
          }
        ]
      },
      "playbook": {
        "name": "Peak of login failure",
        "id": "5b3e2b316964a8001b500ca2"
      }
    }
  }
]

HTTP response

When Sqreen posts a request to webhook's URL, it interprets the returned HTTP status code according to the table below. Sqreen does not follow any redirects to your application.

HTTP code Interpretation
range [200, 299] success
all else fail

Signature

Sqreen uses the Secret Key provided when you configured the webhook to sign the HTTP request body. The signature is in the X-Sqreen-Integrity header. The signature algorithm is an HMAC with the SHA-256 digest.

Example for the key 1234:

POST /some/url HTTP/1.1
...
X-Sqreen-Integrity: 9d101d2bf630748679226b767d2031634c520390ff0e926afc09bc65a05bfdb2
...
4567

Ruby:

require 'openssl'

def check_signature(secret_key, request_signature, request_body)

  digest = OpenSSL::Digest.new('sha256')

  hmac = OpenSSL::HMAC.new(secret_key, digest)
  hmac.update(request_body)
  hmac.to_s == request_signature
end

# req_sig = request.headers['X-Sqreen-Integrity']
# req_body = request.body.read
# secret_key = ENV['SQREEN_WEBHOOK_KEY']

req_sig = '9d101d2bf630748679226b767d2031634c520390ff0e926afc09bc65a05bfdb2'
req_body = '4567'
secret_key = '1234'

puts check_signature(secret_key, req_sig, req_body)

Python:

import hmac
import hashlib

def check_signature(secret_key, request_signature, request_body):

    hasher = hmac.new(secret_key, request_body, hashlib.sha256)
    dig = hasher.hexdigest()

    return hmac.compare_digest(dig, request_signature)

# for Flask:
# request_body = request.get_data()
# request_signature = request.headers['X-Sqreen-Integrity']

# for Django:
# request_body = request.request_body
# request_signature = request.META['X-Sqreen-Integrity']

req_sig = '9d101d2bf630748679226b767d2031634c520390ff0e926afc09bc65a05bfdb2'
req_body = b'4567'
secret_key = b'1234'

print(check_signature(secret_key, req_sig, req_body))

Node.js:

const crypto = require('crypto');

function check_signature(secret_key, request_signature, request_body) {
  const digest = crypto.createHmac('sha256', secret_key)
    .update(request_body)
    .digest();

  return crypto.timingSafeEqual(digest,  Buffer.from(request_signature, 'hex'));
}

// for Express (needs a body parser middleware):
// req_body = req.body;
// req_sig = req.header('X-Sqreen-Integrity');
// secret_key = process.env.SQREEN_WEBHOOK_KEY;

const req_sig = '9d101d2bf630748679226b767d2031634c520390ff0e926afc09bc65a05bfdb2';
const req_body = '4567';
const secret_key = '1234';

console.log(check_signature(secret_key, req_sig, req_body));

Example: Connection from new location

[{
  "id": "5de51ae9f681245ab970ad67",
  "message_type": "security_event",
  "retry_count": 1,
  "date_created": "2017-01-04T07:22:32.732000+00:00",
  "message": {
    "application_id": "587b23384891d57c1bf5bf4f",
    "application_name": "Demo app",
    "environment": "production",
    "date_occurred": "2017-01-04T07:22:32.732000+00:00",
    "event_category": "authentication",
    "event_id": "587b234b4891d57c1bf5c766",
    "event_kind": "auth_new_location",
    "event_url": "https://my.sqreen.com/application/d8b47501fad44fb28d09967e1f1b09a258d85f4ba5d44e759b886f9663e7cf01/events/587b234b4891d57c1bf5c766",
    "humanized_description": "Connection to tsanchez@yahoo.com from Sag, Romania",
    "ips": [
      {
        "address": "84.185.129.221",
        "date_resolved": "2017-01-15T07:22:51.494000+00:00",
        "geo": {
          "city": "Sag",
          "code": "ROU",
          "point": [
            21.283300399780273,
            46.04999923706055
          ]
        },
        "is_tor": false
      }
    ]
  }
}]

Example: Massive security scan

[{
  "message_id": "5de51b8af681245ab970ad68",
  "api_version": "2",
  "date_created": "2019-12-02T14:04:49.455514+00:00",
  "message_type": "http_scan",
  "retry_count": 0,
  "message": {
    "incident_thread": "in_7493f8e8c6084457a6e5a38af2ddbd31",
    "incident_status": "created",
    "date_started": "2017-10-17T14:03:00+00:00",
    "date_last_updated": "2017-10-17T15:20:35.129000+00:00",
    "application_id": "587b23384891d57c1bf5bf4f",
    "new_related_ips": [
      {
        "address": "84.185.129.221",
        "date_resolved": "2017-01-15T07:22:51.494000+00:00",
        "geo": {
          "city": "Sag",
          "code": "ROU",
          "point": [
            21.283300399780273,
            46.04999923706055
          ]
        },
        "is_tor": false
      }
    ]
  }
}]

Example: SQL Injection

[{
  "message_id": "5de51c15f681245ab970ad69",
  "api_version": "2",
  "date_created": "2019-12-02T14:12:44.581570+00:00",
  "message_type": "injection_sql",
  "retry_count": 0,
  "message": {
    "incident_thread": "track_collection_98b9f15eb0c0eb87580d7d662e108e26",
    "incident_status": "created",
    "date_started": "2019-11-14T13:46:36.764000+00:00",
    "date_last_updated": "2019-11-14T13:57:55.377000+00:00",
    "application_id": "587b23384891d57c1bf5bf4f",
    "new_related_ips": [
      {
        "is_tor": false,
        "date_resolved": "2019-11-14T08:57:52.600000+00:00",
        "proxy": false,
        "metadata": {
          "version": 4,
          "multicast": false,
          "private": true,
          "global": false,
          "unspecified": false,
          "reserved": false,
          "loopback": true
        },
        "geo": {},
        "vpn": false,
        "address": "127.0.0.1",
        "tags": [
          "private"
        ],
        "datacenter": false
      }
    ]
  }
}]