mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2025-12-10 01:02:52 +01:00
Release catalyst
This commit is contained in:
25
database/migrations/automations/comment.py
Normal file
25
database/migrations/automations/comment.py
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
subprocess.call(
|
||||
[sys.executable, "-m", "pip", "install", "requests"],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
import json
|
||||
import requests
|
||||
|
||||
|
||||
def run(msg):
|
||||
if "ticket" in msg["context"]:
|
||||
headers = {"PRIVATE-TOKEN": msg["secrets"]["catalyst_apikey"]}
|
||||
url = "%s/tickets/%d/comments" % (msg["secrets"]["catalyst_apiurl"], msg["context"]["ticket"]["id"])
|
||||
data = {'message': msg["payload"]["default"], 'creator': 'automation'}
|
||||
requests.post(url, json=data, headers=headers).json()
|
||||
|
||||
return {"done": True}
|
||||
|
||||
|
||||
print(json.dumps(run(json.loads(sys.argv[1]))))
|
||||
13
database/migrations/automations/hash.sha1.py
Executable file
13
database/migrations/automations/hash.sha1.py
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import json
|
||||
import hashlib
|
||||
|
||||
|
||||
def run(msg):
|
||||
sha1 = hashlib.sha1(msg['payload']['default'].encode('utf-8'))
|
||||
return {"hash": sha1.hexdigest()}
|
||||
|
||||
|
||||
print(json.dumps(run(json.loads(sys.argv[1]))))
|
||||
630
database/migrations/automations/thehive.py
Normal file
630
database/migrations/automations/thehive.py
Normal file
@@ -0,0 +1,630 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import json
|
||||
from datetime import datetime
|
||||
import io
|
||||
|
||||
subprocess.check_call(
|
||||
[sys.executable, "-m", "pip", "install", "thehive4py", "requests", "minio"],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
defaultschema = {
|
||||
"definitions": {},
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://example.com/object1618746510.json",
|
||||
"title": "Default",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"severity",
|
||||
"description",
|
||||
"summary",
|
||||
"tlp",
|
||||
"pap"
|
||||
],
|
||||
"properties": {
|
||||
"severity": {
|
||||
"$id": "#root/severity",
|
||||
"title": "Severity",
|
||||
"type": "string",
|
||||
"default": "Medium",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
"x-display": "icon",
|
||||
"x-itemIcon": "icon",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "Unknown",
|
||||
"title": "Unknown",
|
||||
"icon": "mdi-help"
|
||||
},
|
||||
{
|
||||
"const": "Low",
|
||||
"title": "Low",
|
||||
"icon": "mdi-chevron-up"
|
||||
},
|
||||
{
|
||||
"const": "Medium",
|
||||
"title": "Medium",
|
||||
"icon": "mdi-chevron-double-up"
|
||||
},
|
||||
{
|
||||
"const": "High",
|
||||
"title": "High",
|
||||
"icon": "mdi-chevron-triple-up"
|
||||
},
|
||||
{
|
||||
"const": "Very High",
|
||||
"title": "Very High",
|
||||
"icon": "mdi-exclamation"
|
||||
}
|
||||
]
|
||||
},
|
||||
"flag": {
|
||||
"title": "Flag",
|
||||
"type": "boolean",
|
||||
"x-cols": 6,
|
||||
},
|
||||
"tlp": {
|
||||
"$id": "#root/tlp",
|
||||
"title": "TLP",
|
||||
"type": "string",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
"x-display": "icon",
|
||||
"x-itemIcon": "icon",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "White",
|
||||
"title": "White",
|
||||
"icon": "mdi-alpha-w"
|
||||
},
|
||||
{
|
||||
"const": "Green",
|
||||
"title": "Green",
|
||||
"icon": "mdi-alpha-g"
|
||||
},
|
||||
{
|
||||
"const": "Amber",
|
||||
"title": "Amber",
|
||||
"icon": "mdi-alpha-a"
|
||||
},
|
||||
{
|
||||
"const": "Red",
|
||||
"title": "Red",
|
||||
"icon": "mdi-alpha-r"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pap": {
|
||||
"$id": "#root/pap",
|
||||
"title": "PAP",
|
||||
"type": "string",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
"x-display": "icon",
|
||||
"x-itemIcon": "icon",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "White",
|
||||
"title": "White",
|
||||
"icon": "mdi-alpha-w"
|
||||
},
|
||||
{
|
||||
"const": "Green",
|
||||
"title": "Green",
|
||||
"icon": "mdi-alpha-g"
|
||||
},
|
||||
{
|
||||
"const": "Amber",
|
||||
"title": "Amber",
|
||||
"icon": "mdi-alpha-a"
|
||||
},
|
||||
{
|
||||
"const": "Red",
|
||||
"title": "Red",
|
||||
"icon": "mdi-alpha-r"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tags": {
|
||||
"$id": "#root/tags",
|
||||
"title": "Tags",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"$id": "#root/description",
|
||||
"title": "Description",
|
||||
"type": "string",
|
||||
"x-display": "textarea",
|
||||
"x-class": "pr-2"
|
||||
},
|
||||
"resolutionStatus": {
|
||||
"$id": "#root/resolutionStatus",
|
||||
"title": "Resolution Status",
|
||||
"type": "string",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
},
|
||||
"endDate": {
|
||||
"$id": "#root/endDate",
|
||||
"title": "End Data",
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
},
|
||||
"summary": {
|
||||
"$id": "#root/summary",
|
||||
"title": "Summary",
|
||||
"type": "string",
|
||||
"x-display": "textarea",
|
||||
"x-class": "pr-2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultalertschema = {
|
||||
"definitions": {},
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://example.com/object1618746510.json",
|
||||
"title": "Default",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"severity",
|
||||
"description",
|
||||
"summary",
|
||||
"tlp",
|
||||
"pap"
|
||||
],
|
||||
"properties": {
|
||||
"severity": {
|
||||
"$id": "#root/severity",
|
||||
"title": "Severity",
|
||||
"type": "string",
|
||||
"default": "Medium",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
"x-display": "icon",
|
||||
"x-itemIcon": "icon",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "Unknown",
|
||||
"title": "Unknown",
|
||||
"icon": "mdi-help"
|
||||
},
|
||||
{
|
||||
"const": "Low",
|
||||
"title": "Low",
|
||||
"icon": "mdi-chevron-up"
|
||||
},
|
||||
{
|
||||
"const": "Medium",
|
||||
"title": "Medium",
|
||||
"icon": "mdi-chevron-double-up"
|
||||
},
|
||||
{
|
||||
"const": "High",
|
||||
"title": "High",
|
||||
"icon": "mdi-chevron-triple-up"
|
||||
},
|
||||
{
|
||||
"const": "Very High",
|
||||
"title": "Very High",
|
||||
"icon": "mdi-exclamation"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tlp": {
|
||||
"$id": "#root/tlp",
|
||||
"title": "TLP",
|
||||
"type": "string",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
"x-display": "icon",
|
||||
"x-itemIcon": "icon",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "White",
|
||||
"title": "White",
|
||||
"icon": "mdi-alpha-w"
|
||||
},
|
||||
{
|
||||
"const": "Green",
|
||||
"title": "Green",
|
||||
"icon": "mdi-alpha-g"
|
||||
},
|
||||
{
|
||||
"const": "Amber",
|
||||
"title": "Amber",
|
||||
"icon": "mdi-alpha-a"
|
||||
},
|
||||
{
|
||||
"const": "Red",
|
||||
"title": "Red",
|
||||
"icon": "mdi-alpha-r"
|
||||
}
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"$id": "#root/source",
|
||||
"title": "Source",
|
||||
"type": "string",
|
||||
"x-cols": 4,
|
||||
"x-class": "pr-2",
|
||||
},
|
||||
"sourceRef": {
|
||||
"$id": "#root/sourceRef",
|
||||
"title": "Source Ref",
|
||||
"type": "string",
|
||||
"x-cols": 4,
|
||||
"x-class": "pr-2",
|
||||
},
|
||||
"type": {
|
||||
"$id": "#root/type",
|
||||
"title": "Type",
|
||||
"type": "string",
|
||||
"x-cols": 4,
|
||||
"x-class": "pr-2",
|
||||
},
|
||||
"description": {
|
||||
"$id": "#root/description",
|
||||
"title": "Description",
|
||||
"type": "string",
|
||||
"x-display": "textarea",
|
||||
"x-class": "pr-2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class schema:
|
||||
def __init__(self):
|
||||
self.schema = defaultschema
|
||||
|
||||
def add_string(self, title):
|
||||
self.schema["properties"][title] = { "type": "string", "x-cols": 6, "x-class": "pr-2" }
|
||||
|
||||
def add_boolean(self, title):
|
||||
self.schema["properties"][title] = { "type": "boolean", "x-cols": 6, "x-class": "pr-2" }
|
||||
|
||||
def add_date(self, title):
|
||||
self.schema["properties"][title] = { "type": "string", "format": "date-time", "x-cols": 6, "x-class": "pr-2" }
|
||||
|
||||
def add_integer(self, title):
|
||||
self.schema["properties"][title] = { "type": "integer", "x-cols": 6, "x-class": "pr-2" }
|
||||
|
||||
def add_float(self, title):
|
||||
self.schema["properties"][title] = { "type": "number", "x-cols": 6, "x-class": "pr-2" }
|
||||
|
||||
|
||||
class alertschema:
|
||||
def __init__(self):
|
||||
self.schema = defaultalertschema
|
||||
|
||||
|
||||
def maptime(hivetime):
|
||||
if hivetime is None:
|
||||
return None
|
||||
return datetime.fromtimestamp(hivetime/1000).isoformat() + "Z"
|
||||
|
||||
|
||||
def mapstatus(hivestatus):
|
||||
if hivestatus == "Open" or hivestatus == "New":
|
||||
return "open"
|
||||
return "closed"
|
||||
|
||||
|
||||
def maptlp(hivetlp):
|
||||
if hivetlp == 0:
|
||||
return "White"
|
||||
if hivetlp == 1:
|
||||
return "Green"
|
||||
if hivetlp == 2:
|
||||
return "Amber"
|
||||
if hivetlp == 3:
|
||||
return "Red"
|
||||
return "White"
|
||||
|
||||
|
||||
def mapseverity(hiveseverity):
|
||||
if hiveseverity == 1:
|
||||
return "Low"
|
||||
if hiveseverity == 2:
|
||||
return "Medium"
|
||||
if hiveseverity == 3:
|
||||
return "High"
|
||||
if hiveseverity == 4:
|
||||
return "Very High"
|
||||
return "Unknown"
|
||||
|
||||
# {
|
||||
# "_id": "~16416",
|
||||
# "id": "~16416",
|
||||
# "createdBy": "jonas@thehive.local",
|
||||
# "updatedBy": "jonas@thehive.local",
|
||||
# "createdAt": 1638704013583,
|
||||
# "updatedAt": 1638704061151,
|
||||
# "_type": "case",
|
||||
# "caseId": 1,
|
||||
# "title": "My Test 1",
|
||||
# "description": "My Testcase",
|
||||
# "severity": 2,
|
||||
# "startDate": 1638703980000,
|
||||
# "endDate": null,
|
||||
# "impactStatus": null,
|
||||
# "resolutionStatus": null,
|
||||
# "tags": [],
|
||||
# "flag": false,
|
||||
# "tlp": 2,
|
||||
# "pap": 2,
|
||||
# "status": "Open",
|
||||
# "summary": null,
|
||||
# "owner": "jonas@thehive.local",
|
||||
# "customFields": {},
|
||||
# "stats": {},
|
||||
# "permissions": [ "manageShare", "manageAnalyse", "manageTask", "manageCaseTemplate", "manageCase", "manageUser", "manageProcedure", "managePage", "manageObservable", "manageTag", "manageConfig", "manageAlert", "accessTheHiveFS", "manageAction" ]
|
||||
# }
|
||||
def mapcase(hivecase, url, keep_ids):
|
||||
|
||||
s = schema()
|
||||
details = {}
|
||||
for name, data in hivecase["customFields"].items():
|
||||
if "string" in data and data["string"] is not None:
|
||||
s.add_string(name)
|
||||
details[name] = data["string"]
|
||||
if "boolean" in data and data["boolean"] is not None:
|
||||
s.add_boolean(name)
|
||||
details[name] = data["boolean"]
|
||||
if "date" in data and data["date"] is not None:
|
||||
s.add_date(name)
|
||||
details[name] = maptime(data["date"])
|
||||
if "integer" in data and data["integer"] is not None:
|
||||
s.add_integer(name)
|
||||
details[name] = data["integer"]
|
||||
if "float" in data and data["float"] is not None:
|
||||
s.add_float(name)
|
||||
details[name] = data["float"]
|
||||
|
||||
case = {}
|
||||
if keep_ids:
|
||||
case["id"] = hivecase["caseId"]
|
||||
|
||||
return {
|
||||
"name": hivecase["title"],
|
||||
"type": "incident",
|
||||
"status": mapstatus(hivecase["status"]),
|
||||
|
||||
"owner": hivecase["owner"],
|
||||
# "write": hivecase["write"],
|
||||
# "read": hivecase["read"],
|
||||
|
||||
"schema": json.dumps(s.schema),
|
||||
"details": {
|
||||
"tlp": maptlp(hivecase["tlp"]),
|
||||
"pap": maptlp(hivecase["pap"]),
|
||||
"severity": mapseverity(hivecase["severity"]),
|
||||
"description": hivecase["description"],
|
||||
"summary": hivecase["summary"],
|
||||
"tags": hivecase["tags"],
|
||||
"endDate": maptime(hivecase["endDate"]),
|
||||
"resolutionStatus": hivecase["resolutionStatus"],
|
||||
"flag": hivecase["flag"],
|
||||
} | details,
|
||||
"references": [
|
||||
{ "name": "TheHive #%d" % hivecase["caseId"], "href": "%s/index.html#!/case/~%s/details" % (url, hivecase["id"]) }
|
||||
],
|
||||
#
|
||||
# "playbooks": hivecase["playbooks"],
|
||||
#
|
||||
"files": [],
|
||||
"comments": [],
|
||||
# creator, created, message
|
||||
#
|
||||
"artifacts": [],
|
||||
# name, type, status, enrichment
|
||||
# name, data
|
||||
|
||||
"created": maptime(hivecase["createdAt"]),
|
||||
"modified": maptime(hivecase["updatedAt"]),
|
||||
} | case
|
||||
|
||||
# {
|
||||
# "_id": "ce2c00f17132359cb3c50dfbb1901810",
|
||||
# "_type": "alert",
|
||||
# "artifacts": [],
|
||||
# "createdAt": 1495012062014,
|
||||
# "createdBy": "myuser",
|
||||
# "date": 1495012062016,
|
||||
# "description": "N/A",
|
||||
# "follow": true,
|
||||
# "id": "ce2c00f17132359cb3c50dfbb1901810",
|
||||
# "lastSyncDate": 1495012062016,
|
||||
# "severity": 2,
|
||||
# "source": "instance1",
|
||||
# "sourceRef": "alert-ref",
|
||||
# "status": "New",
|
||||
# "title": "New Alert",
|
||||
# "tlp": 2,
|
||||
# "type": "external",
|
||||
# "user": "myuser"
|
||||
# }
|
||||
def mapalert(hivealert, url):
|
||||
s = alertschema()
|
||||
details = {}
|
||||
|
||||
return {
|
||||
"name": hivealert["title"],
|
||||
"type": "alert",
|
||||
"status": mapstatus(hivealert["status"]),
|
||||
"owner": hivealert["user"],
|
||||
"schema": json.dumps(s.schema),
|
||||
"details": {
|
||||
"tlp": maptlp(hivealert["tlp"]),
|
||||
"severity": mapseverity(hivealert["severity"]),
|
||||
"description": hivealert["description"],
|
||||
"source": hivealert["source"],
|
||||
"sourceRef": hivealert["sourceRef"],
|
||||
"type": hivealert["type"],
|
||||
} | details,
|
||||
"references": [
|
||||
{ "name": "TheHive Alerts", "href": "%s/index.html#!/alert/list" % url }
|
||||
],
|
||||
"files": [],
|
||||
"comments": [],
|
||||
"artifacts": [],
|
||||
"created": maptime(hivealert["createdAt"]),
|
||||
"modified": maptime(hivealert["lastSyncDate"]),
|
||||
}
|
||||
|
||||
# {
|
||||
# "_id": "~41152",
|
||||
# "id": "~41152",
|
||||
# "createdBy": "jonas@thehive.local",
|
||||
# "createdAt": 1638723814523,
|
||||
# "_type": "case_artifact",
|
||||
# "dataType": "ip",
|
||||
# "data": "2.2.2.2",
|
||||
# "startDate": 1638723814523,
|
||||
# "tlp": 2,
|
||||
# "tags": [],
|
||||
# "ioc": false,
|
||||
# "sighted": false,
|
||||
# "message": ".",
|
||||
# "reports": {},
|
||||
# "stats": {},
|
||||
# "ignoreSimilarity": false
|
||||
# }
|
||||
def mapobservable(hiveobservable):
|
||||
status = "unknown"
|
||||
if hiveobservable["ioc"]:
|
||||
status = "malicious"
|
||||
return {
|
||||
"name": hiveobservable["data"],
|
||||
"type": hiveobservable["dataType"],
|
||||
"status": status,
|
||||
}
|
||||
|
||||
# {
|
||||
# "id": "~12296",
|
||||
# "_id": "~12296",
|
||||
# "createdBy": "jonas@thehive.local",
|
||||
# "createdAt": 1638704029800,
|
||||
# "_type": "case_task",
|
||||
# "title": "Start",
|
||||
# "group": "MyTaskGroup1",
|
||||
# "owner": "jonas@thehive.local",
|
||||
# "status": "InProgress",
|
||||
# "flag": false,
|
||||
# "startDate": 1638704115667,
|
||||
# "order": 0
|
||||
# }
|
||||
# {
|
||||
# "_id": "~24656",
|
||||
# "id": "~24656",
|
||||
# "createdBy": "jonas@thehive.local",
|
||||
# "createdAt": 1638729992590,
|
||||
# "_type": "case_task_log",
|
||||
# "message": "asd",
|
||||
# "startDate": 1638729992590,
|
||||
# "attachment": {
|
||||
# "name": "Chemistry Vector.eps",
|
||||
# "hashes": [
|
||||
# "adf2d4cd72f4141fe7f8eb4af035596415a29c048d3039be6449008f291258e9",
|
||||
# "180f66a6d22b1f09ed198afd814f701e42440e7c",
|
||||
# "b28ae347371df003b76cbb8c6199c97e"
|
||||
# ],
|
||||
# "size": 3421842,
|
||||
# "contentType": "application/postscript",
|
||||
# "id": "adf2d4cd72f4141fe7f8eb4af035596415a29c048d3039be6449008f291258e9"
|
||||
# },
|
||||
# "status": "Ok",
|
||||
# "owner": "jonas@thehive.local"
|
||||
# }
|
||||
def maptasklog(hivetask, hivetasklog):
|
||||
message = "**" + hivetask["group"] + ": " + hivetask["title"] + "** (" + hivetask["status"] + ")\n\n"
|
||||
message += hivetasklog["message"]
|
||||
if 'attachment' in hivetasklog:
|
||||
message += "\n\n*Attachment*: " + hivetasklog['attachment']["name"]
|
||||
return {
|
||||
"creator": hivetasklog["createdBy"],
|
||||
"created": maptime(hivetasklog["createdAt"]),
|
||||
"message": message,
|
||||
}
|
||||
|
||||
|
||||
def run(msg):
|
||||
skip_files = msg["payload"]["skip_files"]
|
||||
keep_ids = msg["payload"]["keep_ids"]
|
||||
|
||||
from thehive4py.api import TheHiveApi
|
||||
import requests
|
||||
from minio import Minio
|
||||
|
||||
headers = {"PRIVATE-TOKEN": msg["secrets"]["catalyst_apikey"]}
|
||||
# minioclient = Minio("try.catalyst-soar.com:9000", access_key="minio", secret_key="password")
|
||||
if not skip_files:
|
||||
minioclient = Minio(
|
||||
msg["secrets"]["minio_host"],
|
||||
access_key=msg["secrets"]["minio_access_key"],
|
||||
secret_key=msg["secrets"]["minio_secret_key"])
|
||||
|
||||
# url = "http://localhost:9000"
|
||||
url = msg["payload"]["thehiveurl"]
|
||||
# api = TheHiveApi(url, "dtUCnzY4h291GIFHJKW/Z2I2SgjTRQqo")
|
||||
api = TheHiveApi(url, msg["payload"]["thehivekey"])
|
||||
|
||||
print("find alerts", file=sys.stderr)
|
||||
alerts = []
|
||||
resp = api.find_alerts(query={}, sort=['-createdAt'], range='all')
|
||||
resp.raise_for_status()
|
||||
for alert in resp.json():
|
||||
alerts.append(mapalert(alert, url))
|
||||
|
||||
if alerts:
|
||||
print("create %s alerts" % len(alerts), file=sys.stderr)
|
||||
response = requests.post(msg["secrets"]["catalyst_apiurl"] + "/tickets/batch", json=alerts, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
print("find incidents", file=sys.stderr)
|
||||
incidents = []
|
||||
resp = api.find_cases(query={}, sort=['-createdAt'], range='all')
|
||||
resp.raise_for_status()
|
||||
for case in resp.json():
|
||||
incident = mapcase(case, url, keep_ids)
|
||||
for observable in api.get_case_observables(case["id"]).json():
|
||||
incident["artifacts"].append(mapobservable(observable))
|
||||
for task in api.get_case_tasks(case["id"]).json():
|
||||
for log in api.get_task_logs(task["id"]).json():
|
||||
incident["comments"].append(maptasklog(task, log))
|
||||
if 'attachment' in log and not skip_files:
|
||||
incident["files"].append({ "key": log['attachment']["id"], "name": log['attachment']["name"] })
|
||||
|
||||
bucket_name = "catalyst-%d" % incident["id"]
|
||||
if not minioclient.bucket_exists(bucket_name):
|
||||
minioclient.make_bucket(bucket_name)
|
||||
|
||||
response = api.download_attachment(log["attachment"]["id"])
|
||||
data = io.BytesIO(response.content)
|
||||
|
||||
minioclient.put_object(bucket_name, log["attachment"]["id"], data, length=-1, part_size=10*1024*1024)
|
||||
incidents.append(incident)
|
||||
|
||||
if incidents:
|
||||
if keep_ids:
|
||||
print("delete incidents", file=sys.stderr)
|
||||
for incident in incidents:
|
||||
requests.delete(msg["secrets"]["catalyst_apiurl"] + "/tickets/%d" % incident["id"], headers=headers)
|
||||
print("create %d incidents" % len(incidents), file=sys.stderr)
|
||||
response = requests.post(msg["secrets"]["catalyst_apiurl"] + "/tickets/batch", json=incidents, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
return {"done": True}
|
||||
|
||||
|
||||
print(json.dumps(run(json.loads(sys.argv[1]))))
|
||||
22
database/migrations/automations/vt.hash.py
Normal file
22
database/migrations/automations/vt.hash.py
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
subprocess.call(
|
||||
[sys.executable, "-m", "pip", "install", "requests"],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
import json
|
||||
import requests
|
||||
|
||||
|
||||
def run(msg):
|
||||
api_key = msg['secrets']['vt_api_key'].encode('utf-8')
|
||||
resource = msg['payload']['default'].encode('utf-8')
|
||||
params = {'apikey': api_key, 'resource': resource}
|
||||
return requests.get("https://www.virustotal.com/vtapi/v2/file/report", params=params).json()
|
||||
|
||||
|
||||
print(json.dumps(run(json.loads(sys.argv[1]))))
|
||||
27
database/migrations/content.go
Normal file
27
database/migrations/content.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package migrations
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed templates/default.json
|
||||
var DefaultTemplateSchema string
|
||||
|
||||
//go:embed automations/hash.sha1.py
|
||||
var SHA1HashAutomation string
|
||||
|
||||
//go:embed automations/vt.hash.py
|
||||
var VTHashAutomation string
|
||||
|
||||
//go:embed automations/thehive.py
|
||||
var TheHiveAutomation string
|
||||
|
||||
//go:embed automations/comment.py
|
||||
var CommentAutomation string
|
||||
|
||||
//go:embed playbooks/malware.yml
|
||||
var MalwarePlaybook string
|
||||
|
||||
//go:embed playbooks/phishing.yml
|
||||
var PhishingPlaybook string
|
||||
|
||||
//go:embed playbooks/simple.yaml
|
||||
var SimplePlaybook string
|
||||
217
database/migrations/migrations.go
Normal file
217
database/migrations/migrations.go
Normal file
@@ -0,0 +1,217 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
|
||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||
"github.com/SecurityBrewery/catalyst/pointer"
|
||||
)
|
||||
|
||||
const MigrationCollection string = "migrations"
|
||||
|
||||
type Migration interface {
|
||||
MID() string
|
||||
Migrate(ctx context.Context, driver driver.Database) error
|
||||
}
|
||||
|
||||
func generateMigrations() ([]Migration, error) {
|
||||
// content here should never change
|
||||
return []Migration{
|
||||
&createCollection{ID: "create-log-collection", Name: "logs", DataType: "log", Schema: `{"properties":{"created":{"format":"date-time","type":"string"},"creator":{"type":"string"},"message":{"type":"string"},"reference":{"type":"string"}},"required":["created","creator","message","reference"],"type":"object"}`},
|
||||
&createCollection{ID: "create-ticket-collection", Name: "tickets", DataType: "ticket", Schema: `{"properties":{"artifacts":{"items":{"properties":{"enrichments":{"additionalProperties":{"properties":{"created":{"format":"date-time","type":"string"},"data":{"example":{"hash":"b7a067a742c20d07a7456646de89bc2d408a1153"},"properties":{},"type":"object"},"name":{"example":"hash.sha1","type":"string"}},"required":["created","data","name"],"type":"object"},"type":"object"},"name":{"example":"2.2.2.2","type":"string"},"status":{"example":"Unknown","type":"string"},"type":{"type":"string"}},"required":["name"],"type":"object"},"type":"array"},"comments":{"items":{"properties":{"created":{"format":"date-time","type":"string"},"creator":{"type":"string"},"message":{"type":"string"}},"required":["created","creator","message"],"type":"object"},"type":"array"},"created":{"format":"date-time","type":"string"},"details":{"example":{"description":"my little incident"},"properties":{},"type":"object"},"files":{"items":{"properties":{"key":{"example":"myfile","type":"string"},"name":{"example":"notes.docx","type":"string"}},"required":["key","name"],"type":"object"},"type":"array"},"modified":{"format":"date-time","type":"string"},"name":{"example":"WannyCry","type":"string"},"owner":{"example":"bob","type":"string"},"playbooks":{"additionalProperties":{"properties":{"name":{"example":"Phishing","type":"string"},"tasks":{"additionalProperties":{"properties":{"automation":{"type":"string"},"closed":{"format":"date-time","type":"string"},"created":{"format":"date-time","type":"string"},"data":{"properties":{},"type":"object"},"done":{"type":"boolean"},"join":{"example":false,"type":"boolean"},"payload":{"additionalProperties":{"type":"string"},"type":"object"},"name":{"example":"Inform user","type":"string"},"next":{"additionalProperties":{"type":"string"},"type":"object"},"owner":{"type":"string"},"schema":{"properties":{},"type":"object"},"type":{"enum":["task","input","automation"],"example":"task","type":"string"}},"required":["created","done","name","type"],"type":"object"},"type":"object"}},"required":["name","tasks"],"type":"object"},"type":"object"},"read":{"example":["bob"],"items":{"type":"string"},"type":"array"},"references":{"items":{"properties":{"href":{"example":"https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2017-0144","type":"string"},"name":{"example":"CVE-2017-0144","type":"string"}},"required":["href","name"],"type":"object"},"type":"array"},"schema":{"example":"{}","type":"string"},"status":{"example":"open","type":"string"},"type":{"example":"incident","type":"string"},"write":{"example":["alice"],"items":{"type":"string"},"type":"array"}},"required":["created","modified","name","schema","status","type"],"type":"object"}`},
|
||||
&createCollection{ID: "create-template-collection", Name: "templates", DataType: "template", Schema: `{"properties":{"name":{"type":"string"},"schema":{"type":"string"}},"required":["name","schema"],"type":"object"}`},
|
||||
&createCollection{ID: "create-playbook-collection", Name: "playbooks", DataType: "playbook", Schema: `{"properties":{"name":{"type":"string"},"yaml":{"type":"string"}},"required":["name","yaml"],"type":"object"}`},
|
||||
&createCollection{ID: "create-automation-collection", Name: "automations", DataType: "automation", Schema: `{"properties":{"image":{"type":"string"},"script":{"type":"string"}},"required":["image","script"],"type":"object"}`},
|
||||
&createCollection{ID: "create-userdata-collection", Name: "userdata", DataType: "userdata", Schema: `{"properties":{"email":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"timeformat":{"title":"Time Format (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)","type":"string"}},"type":"object"}`},
|
||||
&createCollection{ID: "create-tickettype-collection", Name: "tickettypes", DataType: "tickettype", Schema: `{"properties":{"default_groups":{"items":{"type":"string"},"type":"array"},"default_playbooks":{"items":{"type":"string"},"type":"array"},"default_template":{"type":"string"},"icon":{"type":"string"},"name":{"type":"string"}},"required":["default_playbooks","default_template","icon","name"],"type":"object"}`},
|
||||
&createCollection{ID: "create-user-collection", Name: "users", DataType: "user", Schema: `{"properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"roles":{"items":{"type":"string"},"type":"array"},"sha256":{"type":"string"}},"required":["apikey","blocked","roles"],"type":"object"}`},
|
||||
|
||||
&createGraph{ID: "create-ticket-graph", Name: "Graph", EdgeDefinitions: []driver.EdgeDefinition{{Collection: "related", From: []string{"tickets"}, To: []string{"tickets"}}}},
|
||||
|
||||
&createDocument{ID: "create-template-default", Collection: "templates", Document: &busdb.Keyed{Key: "default", Doc: models.TicketTemplate{Schema: DefaultTemplateSchema, Name: "Default"}}},
|
||||
&createDocument{ID: "create-automation-vt.hash", Collection: "automations", Document: &busdb.Keyed{Key: "vt.hash", Doc: models.Automation{Image: "docker.io/python:3", Script: VTHashAutomation}}},
|
||||
&createDocument{ID: "create-automation-comment", Collection: "automations", Document: &busdb.Keyed{Key: "comment", Doc: models.Automation{Image: "docker.io/python:3", Script: CommentAutomation}}},
|
||||
&createDocument{ID: "create-automation-thehive", Collection: "automations", Document: &busdb.Keyed{Key: "thehive", Doc: models.Automation{Image: "docker.io/python:3", Script: TheHiveAutomation}}},
|
||||
&createDocument{ID: "create-automation-hash.sha1", Collection: "automations", Document: &busdb.Keyed{Key: "hash.sha1", Doc: models.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation}}},
|
||||
&createDocument{ID: "create-playbook-malware", Collection: "playbooks", Document: &busdb.Keyed{Key: "malware", Doc: models.PlaybookTemplate{Name: "Malware", Yaml: MalwarePlaybook}}},
|
||||
&createDocument{ID: "create-playbook-phishing", Collection: "playbooks", Document: &busdb.Keyed{Key: "phishing", Doc: models.PlaybookTemplate{Name: "Phishing", Yaml: PhishingPlaybook}}},
|
||||
&createDocument{ID: "create-tickettype-alert", Collection: "tickettypes", Document: &busdb.Keyed{Key: "alert", Doc: models.TicketType{Name: "Alerts", Icon: "mdi-alert", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument{ID: "create-tickettype-incident", Collection: "tickettypes", Document: &busdb.Keyed{Key: "incident", Doc: models.TicketType{Name: "Incidents", Icon: "mdi-radioactive", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument{ID: "create-tickettype-investigation", Collection: "tickettypes", Document: &busdb.Keyed{Key: "investigation", Doc: models.TicketType{Name: "Forensic Investigations", Icon: "mdi-fingerprint", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument{ID: "create-tickettype-hunt", Collection: "tickettypes", Document: &busdb.Keyed{Key: "hunt", Doc: models.TicketType{Name: "Threat Hunting", Icon: "mdi-target", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
|
||||
&updateSchema{ID: "update-automation-collection-1", Name: "automations", DataType: "automation", Schema: `{"properties":{"image":{"type":"string"},"script":{"type":"string"}},"required":["image","script"],"type":"object"}`},
|
||||
&updateDocument{ID: "update-automation-vt.hash-1", Collection: "automations", Key: "vt.hash", Document: models.Automation{Image: "docker.io/python:3", Script: VTHashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}},
|
||||
&updateDocument{ID: "update-automation-comment-1", Collection: "automations", Key: "comment", Document: models.Automation{Image: "docker.io/python:3", Script: CommentAutomation, Type: []string{"playbook"}}},
|
||||
&updateDocument{ID: "update-automation-thehive-1", Collection: "automations", Key: "thehive", Document: models.Automation{Image: "docker.io/python:3", Script: TheHiveAutomation, Schema: pointer.String(`{"title":"TheHive credentials","type":"object","properties":{"thehiveurl":{"type":"string","title":"TheHive URL (e.g. 'https://thehive.example.org')"},"thehivekey":{"type":"string","title":"TheHive API Key"},"skip_files":{"type":"boolean", "default": true, "title":"Skip Files (much faster)"},"keep_ids":{"type":"boolean", "default": true, "title":"Keep IDs and overwrite existing IDs"}},"required":["thehiveurl", "thehivekey", "skip_files", "keep_ids"]}`), Type: []string{"global"}}},
|
||||
&updateDocument{ID: "update-automation-hash.sha1-1", Collection: "automations", Key: "hash.sha1", Document: models.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}},
|
||||
|
||||
&createCollection{ID: "create-job-collection", Name: "jobs", DataType: "job", Schema: `{"properties":{"automation":{"type":"string"},"log":{"type":"string"},"payload":{},"origin":{"properties":{"artifact_origin":{"properties":{"artifact":{"type":"string"},"ticket_id":{"format":"int64","type":"integer"}},"required":["artifact","ticket_id"],"type":"object"},"task_origin":{"properties":{"playbook_id":{"type":"string"},"task_id":{"type":"string"},"ticket_id":{"format":"int64","type":"integer"}},"required":["playbook_id","task_id","ticket_id"],"type":"object"}},"type":"object"},"output":{"properties":{},"type":"object"},"running":{"type":"boolean"},"status":{"type":"string"}},"required":["automation","running","status"],"type":"object"}`},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func loadSchema(dataType, jsonschema string) (*driver.CollectionSchemaOptions, error) {
|
||||
ticketCollectionSchema := &driver.CollectionSchemaOptions{Level: driver.CollectionSchemaLevelStrict, Message: fmt.Sprintf("Validation of %s failed", dataType)}
|
||||
|
||||
err := ticketCollectionSchema.LoadRule([]byte(jsonschema))
|
||||
return ticketCollectionSchema, err
|
||||
}
|
||||
|
||||
type migration struct {
|
||||
Key string `json:"_key"`
|
||||
}
|
||||
|
||||
func PerformMigrations(ctx context.Context, db driver.Database) error {
|
||||
collection, err := db.Collection(ctx, MigrationCollection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
migrations, err := generateMigrations()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate migrations: %w", err)
|
||||
}
|
||||
|
||||
for _, m := range migrations {
|
||||
migrationRan, err := collection.DocumentExists(ctx, m.MID())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !migrationRan {
|
||||
if err := m.Migrate(ctx, db); err != nil {
|
||||
return fmt.Errorf("migration %s failed: %w", m.MID(), err)
|
||||
}
|
||||
|
||||
if _, err := collection.CreateDocument(ctx, &migration{Key: m.MID()}); err != nil {
|
||||
return fmt.Errorf("could not save %s migration document: %w", m.MID(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type createCollection struct {
|
||||
ID string
|
||||
Name string
|
||||
DataType string
|
||||
Schema string
|
||||
}
|
||||
|
||||
func (m *createCollection) MID() string {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
func (m *createCollection) Migrate(ctx context.Context, db driver.Database) error {
|
||||
schema, err := loadSchema(m.DataType, m.Schema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = db.CreateCollection(ctx, m.Name, &driver.CreateCollectionOptions{
|
||||
Schema: schema,
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type updateSchema struct {
|
||||
ID string
|
||||
Name string
|
||||
DataType string
|
||||
Schema string
|
||||
}
|
||||
|
||||
func (m *updateSchema) MID() string {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
func (m *updateSchema) Migrate(ctx context.Context, db driver.Database) error {
|
||||
schema, err := loadSchema(m.DataType, m.Schema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
col, err := db.Collection(ctx, m.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = col.SetProperties(ctx, driver.SetCollectionPropertiesOptions{
|
||||
Schema: schema,
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type createGraph struct {
|
||||
ID string
|
||||
Name string
|
||||
EdgeDefinitions []driver.EdgeDefinition
|
||||
}
|
||||
|
||||
func (m *createGraph) MID() string {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
func (m *createGraph) Migrate(ctx context.Context, db driver.Database) error {
|
||||
_, err := db.CreateGraph(ctx, m.Name, &driver.CreateGraphOptions{
|
||||
EdgeDefinitions: m.EdgeDefinitions,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
type createDocument struct {
|
||||
ID string
|
||||
Collection string
|
||||
Document interface{}
|
||||
}
|
||||
|
||||
func (m *createDocument) MID() string {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
func (m *createDocument) Migrate(ctx context.Context, driver driver.Database) error {
|
||||
collection, err := driver.Collection(ctx, m.Collection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = collection.CreateDocument(ctx, m.Document)
|
||||
return err
|
||||
}
|
||||
|
||||
type updateDocument struct {
|
||||
ID string
|
||||
Collection string
|
||||
Key string
|
||||
Document interface{}
|
||||
}
|
||||
|
||||
func (m *updateDocument) MID() string {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
func (m *updateDocument) Migrate(ctx context.Context, driver driver.Database) error {
|
||||
collection, err := driver.Collection(ctx, m.Collection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
exists, err := collection.DocumentExists(ctx, m.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
_, err = collection.CreateDocument(ctx, m.Document)
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = collection.ReplaceDocument(ctx, m.Key, m.Document)
|
||||
return err
|
||||
}
|
||||
63
database/migrations/playbooks/malware.yml
Normal file
63
database/migrations/playbooks/malware.yml
Normal file
@@ -0,0 +1,63 @@
|
||||
name: Malware
|
||||
tasks:
|
||||
file-or-hash:
|
||||
name: Do you have the file or the hash?
|
||||
type: input
|
||||
schema:
|
||||
title: Malware
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
type: string
|
||||
title: "I have the"
|
||||
enum: [ "File", "Hash" ]
|
||||
next:
|
||||
enter-hash: "file == 'Hash'"
|
||||
upload: "file == 'File'"
|
||||
|
||||
enter-hash:
|
||||
name: Please enter the hash
|
||||
type: input
|
||||
schema:
|
||||
title: Malware
|
||||
type: object
|
||||
properties:
|
||||
hash:
|
||||
type: string
|
||||
title: Please enter the hash value
|
||||
minlength: 32
|
||||
next:
|
||||
virustotal: "hash != ''"
|
||||
|
||||
upload:
|
||||
name: Upload the malware
|
||||
type: input
|
||||
schema:
|
||||
title: Malware
|
||||
type: object
|
||||
properties:
|
||||
malware:
|
||||
type: object
|
||||
x-display: file
|
||||
title: Please upload the malware
|
||||
next:
|
||||
hash: "malware"
|
||||
|
||||
hash:
|
||||
name: Hash the malware
|
||||
type: automation
|
||||
automation: hash.sha1
|
||||
payload:
|
||||
default: "playbook.tasks['upload'].data['malware']"
|
||||
next:
|
||||
virustotal:
|
||||
|
||||
virustotal:
|
||||
name: Send hash to VirusTotal
|
||||
type: automation
|
||||
automation: vt.hash
|
||||
args:
|
||||
hash: "playbook.tasks['enter-hash'].data['hash'] || playbook.tasks['hash'].data['hash']"
|
||||
# next:
|
||||
# known-malware: "score > 5"
|
||||
# sandbox: "score < 6" # unknown-malware
|
||||
85
database/migrations/playbooks/phishing.yml
Normal file
85
database/migrations/playbooks/phishing.yml
Normal file
@@ -0,0 +1,85 @@
|
||||
name: Phishing
|
||||
tasks:
|
||||
board:
|
||||
name: Board Involvement?
|
||||
description: Is a board member involved?
|
||||
type: input
|
||||
schema:
|
||||
properties:
|
||||
boardInvolved:
|
||||
default: false
|
||||
title: A board member is involved.
|
||||
type: boolean
|
||||
required:
|
||||
- boardInvolved
|
||||
title: Board Involvement?
|
||||
type: object
|
||||
next:
|
||||
escalate: "boardInvolved == true"
|
||||
mail-available: "boardInvolved == false"
|
||||
|
||||
escalate:
|
||||
name: Escalate to CISO
|
||||
description: Please escalate the task to the CISO
|
||||
type: task
|
||||
|
||||
mail-available:
|
||||
name: Mail available
|
||||
type: input
|
||||
schema:
|
||||
oneOf:
|
||||
- properties:
|
||||
mail:
|
||||
title: Mail
|
||||
type: string
|
||||
x-display: textarea
|
||||
schemaKey:
|
||||
const: 'yes'
|
||||
type: string
|
||||
required:
|
||||
- mail
|
||||
title: 'Yes'
|
||||
- properties:
|
||||
schemaKey:
|
||||
const: 'no'
|
||||
type: string
|
||||
title: 'No'
|
||||
title: Mail available
|
||||
type: object
|
||||
next:
|
||||
block-sender: "schemaKey == 'yes'"
|
||||
extract-iocs: "schemaKey == 'yes'"
|
||||
search-email-gateway: "schemaKey == 'no'"
|
||||
|
||||
search-email-gateway:
|
||||
name: Search email gateway
|
||||
description: Please search email-gateway for the phishing mail.
|
||||
type: task
|
||||
next:
|
||||
extract-iocs:
|
||||
|
||||
block-sender:
|
||||
name: Block sender
|
||||
type: task
|
||||
next:
|
||||
extract-iocs:
|
||||
|
||||
extract-iocs:
|
||||
name: Extract IOCs
|
||||
description: Please insert the IOCs
|
||||
type: input
|
||||
schema:
|
||||
properties:
|
||||
iocs:
|
||||
items:
|
||||
type: string
|
||||
title: IOCs
|
||||
type: array
|
||||
title: Extract IOCs
|
||||
type: object
|
||||
next:
|
||||
block-iocs:
|
||||
|
||||
block-iocs:
|
||||
name: Block IOCs
|
||||
type: task
|
||||
37
database/migrations/playbooks/simple.yaml
Normal file
37
database/migrations/playbooks/simple.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Simple
|
||||
tasks:
|
||||
input:
|
||||
name: Enter something to hash
|
||||
type: input
|
||||
schema:
|
||||
title: Something
|
||||
type: object
|
||||
properties:
|
||||
something:
|
||||
type: string
|
||||
title: Something
|
||||
default: ""
|
||||
next:
|
||||
hash: "something != ''"
|
||||
|
||||
hash:
|
||||
name: Hash the something
|
||||
type: automation
|
||||
automation: hash.sha1
|
||||
payload:
|
||||
default: "playbook.tasks['input'].data['something']"
|
||||
next:
|
||||
comment: "hash != ''"
|
||||
|
||||
comment:
|
||||
name: Comment the hash
|
||||
type: automation
|
||||
automation: comment
|
||||
payload:
|
||||
default: "playbook.tasks['hash'].data['hash']"
|
||||
next:
|
||||
done: "done"
|
||||
|
||||
done:
|
||||
name: You can close this case now
|
||||
type: task
|
||||
208
database/migrations/templates/advanced.json
Normal file
208
database/migrations/templates/advanced.json
Normal file
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"definitions": {},
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://example.com/object1618746510.json",
|
||||
"title": "Advanced",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"severity": {
|
||||
"$id": "#root/severity",
|
||||
"title": "Severity",
|
||||
"type": "string",
|
||||
"default": "Medium",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
"x-display": "icon",
|
||||
"x-itemIcon": "icon",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "Low",
|
||||
"title": "Low",
|
||||
"icon": "mdi-chevron-up"
|
||||
},
|
||||
{
|
||||
"const": "Medium",
|
||||
"title": "Medium",
|
||||
"icon": "mdi-chevron-double-up"
|
||||
},
|
||||
{
|
||||
"const": "High",
|
||||
"title": "High",
|
||||
"icon": "mdi-chevron-triple-up"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tlp": {
|
||||
"$id": "#root/tlp",
|
||||
"title": "TLP",
|
||||
"type": "string",
|
||||
"nx-enum": [
|
||||
"White",
|
||||
"Green",
|
||||
"Amber",
|
||||
"Red"
|
||||
],
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
"x-display": "icon",
|
||||
"x-itemIcon": "icon",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "White",
|
||||
"title": "White",
|
||||
"icon": "mdi-alpha-w"
|
||||
},
|
||||
{
|
||||
"const": "Green",
|
||||
"title": "Green",
|
||||
"icon": "mdi-alpha-g"
|
||||
},
|
||||
{
|
||||
"const": "Amber",
|
||||
"title": "Amber",
|
||||
"icon": "mdi-alpha-a"
|
||||
},
|
||||
{
|
||||
"const": "Red",
|
||||
"title": "Red",
|
||||
"icon": "mdi-alpha-r"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"$id": "#root/description",
|
||||
"title": "Description",
|
||||
"type": "string",
|
||||
"x-display": "textarea",
|
||||
"x-class": "pr-2"
|
||||
},
|
||||
|
||||
"type": {
|
||||
"type": "object",
|
||||
"title": "Select an incident type",
|
||||
"oneOf": [
|
||||
{
|
||||
"title": "Malware",
|
||||
"properties": {
|
||||
"schemaKey": {
|
||||
"type": "string",
|
||||
"const": "malware"
|
||||
},
|
||||
"malware_type": {
|
||||
"type": "string",
|
||||
"title": "Malware Type",
|
||||
"enum": ["Ransomware", "Worm", "Virus"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Phishing",
|
||||
"properties": {
|
||||
"schemaKey": {
|
||||
"type": "string",
|
||||
"const": "phishing"
|
||||
},
|
||||
"phishing_type": {
|
||||
"type": "string",
|
||||
"title": "Phishing Type",
|
||||
"enum": ["Normal", "Spear", "Whale"]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"x-cols": 12
|
||||
},
|
||||
"apt": {
|
||||
"type": "boolean",
|
||||
"x-display": "switch",
|
||||
"title": "APT involved?",
|
||||
"x-cols": 6
|
||||
},
|
||||
"apt-group": {
|
||||
"type": "string",
|
||||
"title": "Select APT",
|
||||
"enum": ["Lazarus Group", "Equation Group", "Fancy Bear (APT 28)", "OceanLotus (APT 32)", "Other"],
|
||||
"x-if": "apt",
|
||||
"x-cols": 6
|
||||
},
|
||||
"tactics": {
|
||||
"type": "array",
|
||||
"title": "MITRE Att&ck",
|
||||
"description": "This description is used as a help message.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"oneOf": [
|
||||
{
|
||||
"title": "Reconnaissance",
|
||||
"properties": {
|
||||
"tactic": {
|
||||
"type": "string",
|
||||
"const": "reconnaissance",
|
||||
"title": "Tactic",
|
||||
"description": "The adversary is trying to gather information they can use to plan future operations."
|
||||
},
|
||||
"techniques": {
|
||||
"type": "array",
|
||||
"title": "Techniques",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "T1595",
|
||||
"title": "Active Scanning",
|
||||
"description": "Adversaries may execute active reconnaissance scans to gather information that can be used during targeting. Active scans are those where the adversary probes victim infrastructure via network traffic, as opposed to other forms of reconnaissance that do not involve direct interaction."
|
||||
},
|
||||
{
|
||||
"const": "T1592",
|
||||
"title": "Gather Victim Host Information"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Persistence",
|
||||
"properties": {
|
||||
"tactic": {
|
||||
"type": "string",
|
||||
"const": "persistence"
|
||||
},
|
||||
"techniques": {
|
||||
"type": "string",
|
||||
"title": "Techniques",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "T1098",
|
||||
"title": "Account Manipulation"
|
||||
},
|
||||
{
|
||||
"const": "T1197",
|
||||
"title": "BITS Jobs"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"title": "Tags",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"examples": [
|
||||
"misp",
|
||||
"external report",
|
||||
"internal report"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["severity", "description", "tactics", "type"]
|
||||
}
|
||||
|
||||
79
database/migrations/templates/default.json
Normal file
79
database/migrations/templates/default.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"definitions": {},
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://example.com/object1618746510.json",
|
||||
"title": "Default",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"severity",
|
||||
"description",
|
||||
"tlp"
|
||||
],
|
||||
"properties": {
|
||||
"severity": {
|
||||
"$id": "#root/severity",
|
||||
"title": "Severity",
|
||||
"type": "string",
|
||||
"default": "Medium",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
"x-display": "icon",
|
||||
"x-itemIcon": "icon",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "Low",
|
||||
"title": "Low",
|
||||
"icon": "mdi-chevron-up"
|
||||
},
|
||||
{
|
||||
"const": "Medium",
|
||||
"title": "Medium",
|
||||
"icon": "mdi-chevron-double-up"
|
||||
},
|
||||
{
|
||||
"const": "High",
|
||||
"title": "High",
|
||||
"icon": "mdi-chevron-triple-up"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tlp": {
|
||||
"$id": "#root/tlp",
|
||||
"title": "TLP",
|
||||
"type": "string",
|
||||
"x-cols": 6,
|
||||
"x-class": "pr-2",
|
||||
"x-display": "icon",
|
||||
"x-itemIcon": "icon",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "White",
|
||||
"title": "White",
|
||||
"icon": "mdi-alpha-w"
|
||||
},
|
||||
{
|
||||
"const": "Green",
|
||||
"title": "Green",
|
||||
"icon": "mdi-alpha-g"
|
||||
},
|
||||
{
|
||||
"const": "Amber",
|
||||
"title": "Amber",
|
||||
"icon": "mdi-alpha-a"
|
||||
},
|
||||
{
|
||||
"const": "Red",
|
||||
"title": "Red",
|
||||
"icon": "mdi-alpha-r"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"$id": "#root/description",
|
||||
"title": "Description",
|
||||
"type": "string",
|
||||
"x-display": "textarea",
|
||||
"x-class": "pr-2"
|
||||
}
|
||||
}
|
||||
}
|
||||
3644
database/migrations/templates/veris.json
Normal file
3644
database/migrations/templates/veris.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user