Webhooks¶
Important
Webhooks are only available with Stamus NDR
What are Webhooks?¶
Webhooks are a mechanism used to push data to other systems, such as a ticketing system, a SOAR, a messaging app like Slack or Mattermost, and so on, using HTTP requests.
When a Declaration of Compromise is created, it can trigger a Webhook.
Webhooks are built using Jinja2 templating system which is a powerful templating system allowing logical construction and access to Python-like variables.
In order to set up webhooks: in the Administration menu go to the upper left corner click on Stamus Networks logo drop down icon -> Integrations
.
Objects & Variables¶
When resolving a template, the following objects and variables are available to the user.
Variable |
Type |
Description |
---|---|---|
family.pk |
integer |
family primary key (id) |
family.family_id |
integer |
family unique id |
family.name |
string |
family name |
family.family_type |
choice/string |
Threat actors / Threat family / Generic threat |
family.description |
string |
family description |
family.version |
integer |
family version |
threat.pk |
integer |
threat primary key (id) |
threat.threat_id |
integer |
threat unique id |
threat.name |
string |
family name |
threat.description |
string |
threat description |
threat.additional_info |
string |
more information on family |
threat.criticity |
integer |
level of criticity |
threat.version |
integer |
threat version |
threat.active |
boolean |
Indicates if the threat is active or not |
threat.creation_date |
date/string |
family description |
threat.user_defined |
boolean |
threat created by user or predifined threat |
method.pk |
integer |
method primary key (id) |
method.method_id |
integer |
threat unique id |
method.target_key |
string |
src_ip or dest_ip as target |
method.source_key |
string |
src_ip or dest_ip as target |
method.description |
string |
method.method description |
method.version |
integer |
method version |
method.active |
boolean |
the method is active or not |
method.target_type |
choice/string |
ip /username / mail |
method.method_type |
choice/string |
Signature / Code |
method.kill_chain |
choice/integer |
most advanced killchain on this method 1 |
method.original_sid |
integer |
method generated from rule with this SID |
method.owner |
string |
assigned user |
method.user_defined |
boolean |
method created by user or predifined threat |
method.action |
foreign key |
action created in Hunt => user_defined is true |
asset.pk |
integer |
asset primary key (id) |
asset.first_seen |
date/string |
asset seen for the first time |
asset.last_seen |
date/string |
asset seen for the last time |
asset.close_status_date |
date/string |
asset has been closed at this date |
asset.value |
string |
ip: ‘192.168.0.12’ / username: ‘Neo’ / mail: |
asset.asset_type |
choice/string |
ip /username / mail |
asset.network_def |
string |
associated network |
asset.status |
choice/string |
global status of the Asset new / fixed |
asset.tenant |
integer |
from which tenant the asset is from |
asset.kill_chain |
choice/integer |
most advanced killchain on this asset 1 |
threat_status.pk |
integer |
threatstatus primary key (id) |
threat_status.status |
choice/string |
status for the pair threat and asset (new / fixed ) |
threat_status.tenant |
integer |
from which tenant the asset is from |
threat_status.first_seen |
date/string |
pair asset and threat seen for the first time |
threat_status.last_seen |
date/string |
pair asset and threat seen for the first time |
threat_status.close_status_date |
date/string |
pair asset and threat has been closed at this date |
threat_status.kill_chain |
choice/integer |
killchain on pair threat and asset 1 |
event |
string |
Metadata information about the event (suricata event) |
family_url |
string |
link the URL of the Threat Family in Stamus Central Server |
threat_url |
string |
link the URL of the Threat in Stamus Central Server |
killchain_name |
string |
the textual name of the kill chain phase 1 |
threat_list |
list |
list of names of threats seen on the current asset |
family_list |
list |
list of names of families seen on the current asset |
threat_kill_chain |
string |
asset kill chain phase in the threat |
family_kill_chain |
string |
asset kill chain phase in the family |
asset_kill_chain |
string |
asset absolute kill chain phase |
Footnotes
Conditional webhooks¶
The webhook template jinja syntax allows the use of conditions directly when setting the webhook. Based on the condition the webhook will be send or not.
{% if condition == True %}
{"text": "New Declaration of Compromise:
* Asset under attack: **{{ asset.value | tojson }}**
* Threat: **{{ threat.name | tojson }}**
* Threat Family: **{{ family.name | tojson }}**
* Killchain phase: **{{ killchain_name | tojson }}**
Investigate using Stamus Central Server: {{ family_url | tojson }}"}
{% endif %}
In the example above, if the condition
variable is equal to False the webhook will not be send.
Examples¶
Splunk¶
Stamus Central Server can trigger a Webhook to Splunk using Splunk HTTP Event Collector. The minimum required parameters are:
The URL such as
https://SPLUNK_IP:8088/services/collector/event
The only header to send is
Authorization: Splunk YOUR_HEC_TOKEN
An example event for a Threat on new Asset could be:
{
"event":
{
"event_type": "stamus_threat",
"threat_status": "new",
"threat": "{{ threat.name | tojson }}",
"asset": "{{ asset.value | tojson }}",
"killchain": "{{ killchain_name }}",
"timestamp": "{{event.timestamp | tojson }}",
"data": {{ event | tojson }}
}
}
Service Now¶
You can do a POST on your instance of ServiceNow at the following address: https://myinstannce.service-now.com/api/global/em/jsonv2
With regard to the headers, you need:
Content-Type: application/json
Authorization: Basic BASE64(user:password)
An example event for a Threat on new Asset could be:
{ "records":
[
{
"source":"Stamus",
"event_class":"{{ threat.name | tojson }} on {{ asset.value | tojson }}",
"node":"{{ asset.value | tojson }}",
"severity":"4",
"description":"Threat {{ threat.name | tojson }} has been discovered on {{ asset.value | tojson }} at kill chain phase {{ killchain_name }}.",
"time_of_event": "{{ event.timestamp | tojson }}",
"message_key": "{{asset.value | tojson }}-{{ threat.name | tojson }}",
"additional_info":{
{% if event.stamus.source %}
"offender": "{{ event.stamus.source | tojson }}",
{% endif %}
"asset": "{{ asset.value | tojson }}",
"killchain": "{{ killchain_name }}"
}
}
]
}
Slack / Mattermost¶
This example post a new message on your chat application such as Slack or Mattermost when a new threat is detected.
In the headers, just keep the default.
Content-Type: application/json
The following text is an example of notification for Mattermost for a new threat seen on an asset.
{
"text": "Stamus Networks - **Asset under attack:** `{{ asset.value }}`, **Killchain:** `{{ killchain_name }}`. **Threat Family:** `{{ family.name }}`. **Threat:** `{{ threat.name }}` have been detected.\nIncident Response ticket:\nhttps://192.168.1.26/HIVE/ir/\n\nFollow up with investigation using Stamus Central Server:\n{{ family_url }}"
}
TheHive¶
In the headers, you will need something like:
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
The URL that you need to use to send alerts is http://THEHIVE_IP:PORT/api/alert
.
The following text is an example of alert for TheHive for a New Threat. It will add basic data and extract observables coming from the application layer analysis. You can customize the message by setting the variables at the beginning.
{% set hook = 'new threat' %}
{% set case_template = 'external-alert' %}
{% set stamus_tag = 'Stamus' %}
{% set stamus_prefix = 'Stamus' %}
{% set asset_tag = 'Stamus:asset' %}
{% set offender_tag = 'Stamus:offender' %}
{% if event.stamus.asset == event.src_ip %}
{% set server_tag = offender_tag %}
{% set client_tag = asset_tag %}
{% else %}
{% set server_tag = asset_tag %}
{% set client_tag = offender_tag %}
{% endif %}
{
{% if hook == 'new threat' %}
"title": "Threat {{ threat.name | tojson }} seen on asset {{ asset.value | tojson }}",
{% else %}
"title": "Progression in kill chain to {{ killchain_name }} for {{ threat.name | tojson }} on asset {{ asset.value | tojson }}",
{% endif %}
"description": "{{ threat.description | tojson }}",
"type": "stamus",
{% if event.host %}
"source": "{{ event.host.name }}",
{% else %}
"source": "Stamus",
{% endif %}
"sourceRef": "{{ threat_status.pk }}-{{ method.kill_chain }}",
"severity": 3,
"tlp": 2,
"tags": ["network", "{{ threat.name | tojson }}", "{{ stamus_tag }}"],
"artifacts": [
{% if event.tls %}
{% if event.tls.sni %}
{ "dataType": "fqdn", "data": "{{ event.tls.sni | tojson }}", "tags": ["{{ server_tag }}", "{{ stamus_prefix }}:tls.sni"] },
{% endif %}
{% if event.tls.fingerprint %}
{ "dataType": "other", "data": "{{ event.tls.fingerprint | tojson }}", "tags": ["{{ server_tag }}", "{{ stamus_prefix }}:tls.fingerprint"] },
{% endif %}
{% if event.tls.ja3 %}
{ "dataType": "other", "data": "{{ event.tls.ja3.hash | tojson }}", "tags": ["{{ client_tag }}", "{{ stamus_prefix }}:tls.ja3"] },
{% endif %}
{% if event.tls.ja3s %}
{ "dataType": "other", "data": "{{ event.tls.ja3s.hash | tojson }}", "tags": ["{{ server_tag }}", "{{ stamus_prefix }}:tls.ja3s"] },
{% endif %}
{% endif %}
{% if event.http %}
{% if event.http.hostname %}
{ "dataType": "fqdn", "data": "{{ event.http.hostname | tojson }}", "tags": ["{{ server_tag }}", "{{ stamus_prefix }}:http.hostname"] },
{% endif %}
{% if event.http.url %}
{ "dataType": "uri_path", "data": "{{ event.http.url | tojson }}", "tags": ["{{ server_tag }}", "{{ stamus_prefix }}:http.url"] },
{% endif %}
{% if event.http.http_user_agent %}
{ "dataType": "user-agent", "data": "{{ event.http.http_user_agent | tojson }}", "tags": ["{{ client_tag }}", "{{ stamus_prefix }}:http.http_user_agent"] },
{% endif %}
{% endif %}
{% if event.dns %}
{% if event.dns.query[0].rrname %}
{ "dataType": "fqdn", "data": "{{ event.dns.query[0].rrname | tojson }}", "tags": ["{{ server_tag }}", "{{ stamus_prefix }}:dns.query.rrname"] },
{% endif %}
{% endif %}
{% if event.fileinfo %}
{% if event.fileinfo.sha256 %}
{ "dataType": "hash", "data": "{{ event.fileinfo.sha256 | tojson }}", "tags": ["{{ stamus_tag }}", "{{ stamus_prefix }}:fileinfo.sha256"] },
{% endif %}
{% if event.fileinfo.filename %}
{ "dataType": "filename", "data": "{{ event.fileinfo.filename | tojson }}", "tags": ["{{ stamus_tag }}", "{{ stamus_prefix }}:fileinfo.filename"] },
{% endif %}
{% endif %}
{% if event.stamus.source %}
{ "dataType": "ip", "data": "{{ event.stamus.source | tojson }}", "tags": ["{{ offender_tag }}", "{{ stamus_prefix }}:stamus.source"] },
{% endif %}
{ "dataType": "ip", "data": "{{ asset.value | tojson }}", "tags": ["{{ asset_tag }}", "{{ stamus_prefix }}:stamus.asset"] }
],
"caseTemplate": "{{ case_template }}"
}
Discord¶
You can do a POST on your instance of Discord at the following address: https://link-to-your-discord.com/api/webhooks/
In the headers, just keep the default.
Content-Type: application/json
Template format should be kept to the default one - json
.
Next, you need to add a Template content
. The following text is a working example of notification for Discord for a new threat seen on an asset:
{"content": "Stamus Networks - **Asset under attack:** `{{ asset.value | tojson }}`, **Killchain:** `{{ killchain_name | tojson }}`. **Threat Family:** `{{ family.name | tojson }}`. **Threat:** `{{ threat.name | tojson }}` has been detected.\n\nFollow up with investigation using Scirius security Platform:\n\n{{ family_url | tojson }}"}
Special Cases¶
In some specific cases, if you are using the AIO
, Logstash over VLAN
, etc. - you would need to adjust the webhooks template content, in order to make it work.
Webhook takes the scirius visible address
to construct the links to NDR. Since in such cases, the visible address might differ, you can use the following Template content
:
{"text": "New Declaration of Compromise:
* Asset under attack: **{{ asset.value | tojson }}**
* Threat: **{{ threat.name | tojson }}**
* Threat Family: **{{ family.name | tojson }}**
* Killchain phase: **{{ killchain_name | tojson }}**
Investigate using Stamus Central Server: https://new.ip.ip.ip/appliances/str/family/{{ family.id }}