From d4ccae4ce000ae42eaaff9218844189c985ec18e Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Sat, 13 Mar 2021 19:21:44 +0100 Subject: [PATCH 1/6] StamusNetworks: introduce host ID analyzer Scirius Security Platform (SSP) from Stamus Networks is a Network Detection and Response solution that is analysing the network traffic of an organization to detect threats and provide insight on the monitored networks. SSP is not SaaS but is on install on premise or in the cloud. That to say, there is no public/centralized instance and all SSP users need to connect to the SSP of their organization. One of the feature fo SSP is the capability to build host identification of IP addresses. This patch is using this feature to extract all known information about an IP address artifact (by using the REST API of SSP). Configuration is key, url and ssl_verify: ``` { "data":"10.7.5.5", "dataType":"ip", "tlp":0, "config":{ "key":"XXXXXXXXXXXXXXXXXXXX", "url":"https://10.0.0.1/", "ssl_verify": false } } ``` The result is an artifact with the hostnames corresponding to the IP address as weel as first seen and last seen for this IP in taxonomies: ``` { "success": true, "summary": { "taxonomies": [ { "level": "info", "namespace": "SSP", "predicate": "first-seen", "value": "2021-03-08T21:25:34.996876+01:00" }, { "level": "info", "namespace": "SSP", "predicate": "last-seen", "value": "2021-03-08T21:25:34.996876+01:00" } ] }, "artifacts": [ { "tags": [ "first-seen:2021-03-08T21:25:34.999945+01:00", "last-seen:2021-03-08T21:50:23.644160+01:00" ], "dataType": "fqdn", "data": "phantasmedia-dc.phantasmedia.com" } ], "full": { "ip": "10.7.5.5", "host_id": { "first_seen": "2021-03-08T21:25:34.996876+01:00", "last_seen": "2021-03-08T21:25:34.996876+01:00", "hostname": [ { "host": "phantasmedia-dc.phantasmedia.com", "first_seen": "2021-03-08T21:25:34.999945+01:00", "last_seen": "2021-03-08T21:50:23.644160+01:00" } ], "net_info": [ { "agg": "sweden.internet", "first_seen": "2021-03-08T21:25:34.996876+01:00", "last_seen": "2021-03-08T22:01:37.001216+01:00" } ], "tls.ja3": [ { "agent": [ "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0" ], "string": "769,47-53-5-10-49171-49172-49161-49162-50-56-19-4,65281-10-11,23-24,0", "hash": "6734f37431670b3ab4292b8f60f29984", "first_seen": "2021-03-08T21:56:58.309064+01:00", "last_seen": "2021-03-08T22:00:12.487521+01:00" }, { "agent": [ "User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705" ], "string": "769,47-53-5-10-49171-49172-49161-49162-50-56-19-4,65281-0-10-11,23-24,0", "hash": "1d095e68489d3c535297cd8dffb06cb9", "first_seen": "2021-03-08T21:57:04.883618+01:00", "last_seen": "2021-03-08T21:57:04.883618+01:00" } ], "http.user_agent": [ { "agent": "test", "first_seen": "2021-03-08T22:00:14.851391+01:00", "last_seen": "2021-03-08T22:00:14.851391+01:00" }, { "agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Win64; x64; Trident/7.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)", "first_seen": "2021-03-08T22:00:50.975367+01:00", "last_seen": "2021-03-08T22:00:50.975367+01:00" }, { "agent": "WinHTTP sender/1.0", "first_seen": "2021-03-08T22:01:39.827278+01:00", "last_seen": "2021-03-08T22:01:39.827278+01:00" } ], "hostname_count": 1, "net_info_count": 1, "tls.ja3_count": 2, "http.user_agent_count": 3, "services": [ { "proto": "tcp", "port": 88, "values": [ { "first_seen": "2021-03-08T21:25:39.000157+0100", "last_seen": "2021-03-08T21:26:00.000642+0100", "app_proto": "krb5" } ] }, { "proto": "tcp", "port": 135, "values": [ { "first_seen": "2021-03-08T21:26:38.000967+0100", "last_seen": "2021-03-08T21:51:22.000422+0100", "app_proto": "dcerpc" } ] }, { "proto": "tcp", "port": 389, "values": [ { "first_seen": "2021-03-08T21:25:38.000940+0100", "last_seen": "2021-03-08T21:56:50.000475+0100", "app_proto": "unknown" } ] }, { "proto": "tcp", "port": 445, "values": [ { "first_seen": "2021-03-08T21:25:55.000262+0100", "last_seen": "2021-03-08T21:55:56.000211+0100", "app_proto": "smb" }, { "first_seen": "2021-03-08T21:52:45.000518+0100", "last_seen": "2021-03-08T21:52:45.000518+0100", "app_proto": "unknown" } ] }, { "proto": "tcp", "port": 3268, "values": [ { "first_seen": "2021-03-08T21:49:02.000600+0100", "last_seen": "2021-03-08T21:50:52.001114+0100", "app_proto": "unknown" } ] }, { "proto": "tcp", "port": 49155, "values": [ { "first_seen": "2021-03-08T21:26:38.001079+0100", "last_seen": "2021-03-08T21:51:22.001006+0100", "app_proto": "dcerpc" } ] }, { "proto": "tcp", "port": 49158, "values": [ { "first_seen": "2021-03-08T21:26:08.000171+0100", "last_seen": "2021-03-08T21:50:42.000992+0100", "app_proto": "dcerpc" } ] } ], "services_count": 8, "tenant": 4 } } } ``` The full sub object contains all the known information about the IP address. --- .../StamusNetworks/StamusNetworks_IPInfo.json | 37 +++++++++++ analyzers/StamusNetworks/hostid_analyzer.py | 63 +++++++++++++++++++ analyzers/StamusNetworks/requirements.txt | 2 + 3 files changed, 102 insertions(+) create mode 100644 analyzers/StamusNetworks/StamusNetworks_IPInfo.json create mode 100755 analyzers/StamusNetworks/hostid_analyzer.py create mode 100644 analyzers/StamusNetworks/requirements.txt diff --git a/analyzers/StamusNetworks/StamusNetworks_IPInfo.json b/analyzers/StamusNetworks/StamusNetworks_IPInfo.json new file mode 100644 index 000000000..ff00c437c --- /dev/null +++ b/analyzers/StamusNetworks/StamusNetworks_IPInfo.json @@ -0,0 +1,37 @@ +{ + "name": "StamusNetworks_HostID", + "version": "1.0", + "author": "Stamus Networks", + "url": "https://github.com/TheHive-Project/Cortex-Analyzers", + "license": "AGPL-V3", + "description": "Get information from your Scirius Security Platform for an IP address.", + "dataTypeList": ["ip"], + "command": "StamusNetworks/hostid_analyzer.py", + "baseConfig": "StamusNetworks", + "config": { + "service": "get" + }, + "configurationItems": [ + { + "name": "url", + "description": "Base URL of Scirius Security Platform", + "type": "string", + "multi": false, + "required": true + }, + { + "name": "key", + "description": "API key for Scirius Security Platform", + "type": "string", + "multi": false, + "required": true + }, + { + "name": "ssl_verify", + "description": "Verify TLS certificate when connection to Scirius Security Platform", + "type": "boolean", + "multi": false, + "required": true + } + ] +} diff --git a/analyzers/StamusNetworks/hostid_analyzer.py b/analyzers/StamusNetworks/hostid_analyzer.py new file mode 100755 index 000000000..28b72d12e --- /dev/null +++ b/analyzers/StamusNetworks/hostid_analyzer.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# encoding: utf-8 + +from cortexutils.analyzer import Analyzer + +import requests + + +class StamusNetworksAnalyzer(Analyzer): + def __init__(self): + Analyzer.__init__(self) + self.api_key = self.get_param('config.key', None, 'Scirius Security Platform api key is missing') + self.base_url = self.get_param('config.url', None, 'Scirius Security Platform url is missing') + self.base_url = self.base_url.rstrip('/ ') + self.ssl_verify = self.get_param('config.ssl_verify', None, 'Scirius Security Platform TLS verification info is missing') + self.proxies = { + "https" : self.get_param("config.proxy_https", None), + "http" : self.get_param("config.proxy_http", None) + } + self.session = requests.Session() + self.session.headers.update({ 'Content-Type': 'application/json', 'Authorization': 'Token ' + self.api_key }) + + def artifacts(self, raw): + artifacts = [] + hostnames = raw['host_id'].get('hostname', []) + for host in hostnames: + tags=["first-seen:" + host['first_seen'], "last-seen:" + host['last_seen']] + artifacts.append( + self.build_artifact('fqdn', + host['host'], + tags=tags)) + return artifacts + + def summary(self, raw): + taxonomies = [] + namespace = "SSP" + value = raw["host_id"]["first_seen"] + taxonomies.append(self.build_taxonomy("info", namespace, 'first-seen', value)) + value = raw["host_id"]["last_seen"] + taxonomies.append(self.build_taxonomy("info", namespace, 'last-seen', value)) + + return {"taxonomies": taxonomies} + + def run(self): + Analyzer.run(self) + info = {} + try: + if self.data_type == 'ip': + url = self.base_url + "/rest/appliances/host_id/" + self.get_data() + resp = self.session.get(url, verify=self.ssl_verify, proxies=self.proxies) + info = resp.json() + # TODO add support for user-agent and fqdn + else: + self.error('Invalid data type !') + + self.report(info) + + except Exception as e: + self.unexpectedError(e) + + +if __name__ == '__main__': + StamusNetworksAnalyzer().run() diff --git a/analyzers/StamusNetworks/requirements.txt b/analyzers/StamusNetworks/requirements.txt new file mode 100644 index 000000000..6aabc3cfa --- /dev/null +++ b/analyzers/StamusNetworks/requirements.txt @@ -0,0 +1,2 @@ +cortexutils +requests From 7b84c5d6818b6584193459f98a6d92637d7e4aa7 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Sat, 13 Mar 2021 23:28:07 +0100 Subject: [PATCH 2/6] StamusNetworks: add information about some counts Host Identification module in SSP keep track of how many TLS agents, HTTP agents and services have been seen. --- analyzers/StamusNetworks/hostid_analyzer.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/analyzers/StamusNetworks/hostid_analyzer.py b/analyzers/StamusNetworks/hostid_analyzer.py index 28b72d12e..dcf796d4d 100755 --- a/analyzers/StamusNetworks/hostid_analyzer.py +++ b/analyzers/StamusNetworks/hostid_analyzer.py @@ -39,6 +39,16 @@ def summary(self, raw): value = raw["host_id"]["last_seen"] taxonomies.append(self.build_taxonomy("info", namespace, 'last-seen', value)) + value = raw["host_id"].get("services_count") + if value: + taxonomies.append(self.build_taxonomy("info", namespace, 'services', value)) + value = raw["host_id"].get("tls.ja3_count") + if value: + taxonomies.append(self.build_taxonomy("info", namespace, 'tls-agents', value)) + value = raw["host_id"].get("http.user_agent_count") + if value: + taxonomies.append(self.build_taxonomy("info", namespace, 'http-agents', value)) + return {"taxonomies": taxonomies} def run(self): From 9887fc758d000c68be88d7f95081bfb59fc9cda7 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Sat, 13 Mar 2021 23:56:06 +0100 Subject: [PATCH 3/6] StamusNetworks: add network information --- analyzers/StamusNetworks/hostid_analyzer.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/analyzers/StamusNetworks/hostid_analyzer.py b/analyzers/StamusNetworks/hostid_analyzer.py index dcf796d4d..b1d5af5a3 100755 --- a/analyzers/StamusNetworks/hostid_analyzer.py +++ b/analyzers/StamusNetworks/hostid_analyzer.py @@ -29,6 +29,14 @@ def artifacts(self, raw): self.build_artifact('fqdn', host['host'], tags=tags)) + net_info = raw['host_id'].get('net_info', []) + if len(net_info) > -1: + net_info = sorted(net_info, key=lambda k: k['last_seen'], reverse=True)[0]['agg'] + tags=["network-info"] + artifacts.append( + self.build_artifact('other', + net_info, + tags=tags)) return artifacts def summary(self, raw): From 7e6fcda685946d36aa96c47e12e3e6544b5171d4 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Sun, 14 Mar 2021 18:26:50 +0100 Subject: [PATCH 4/6] StamusNetworks: add tenant support Scirius Security Platform supports multitenant where multiple organization network can use the same platform. If this feature is activated then the tenant option with value being the one of the organization has to be used to get access to the correct data. This matches the organization approach of Cortex and TheHive. --- analyzers/StamusNetworks/StamusNetworks_IPInfo.json | 7 +++++++ analyzers/StamusNetworks/hostid_analyzer.py | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/analyzers/StamusNetworks/StamusNetworks_IPInfo.json b/analyzers/StamusNetworks/StamusNetworks_IPInfo.json index ff00c437c..25dbb4f60 100644 --- a/analyzers/StamusNetworks/StamusNetworks_IPInfo.json +++ b/analyzers/StamusNetworks/StamusNetworks_IPInfo.json @@ -32,6 +32,13 @@ "type": "boolean", "multi": false, "required": true + }, + { + "name": "tenant", + "description": "Tenant value for organization in Scirius Security Platform", + "type": "string", + "multi": false, + "required": false } ] } diff --git a/analyzers/StamusNetworks/hostid_analyzer.py b/analyzers/StamusNetworks/hostid_analyzer.py index b1d5af5a3..3e464ddec 100755 --- a/analyzers/StamusNetworks/hostid_analyzer.py +++ b/analyzers/StamusNetworks/hostid_analyzer.py @@ -13,6 +13,11 @@ def __init__(self): self.base_url = self.get_param('config.url', None, 'Scirius Security Platform url is missing') self.base_url = self.base_url.rstrip('/ ') self.ssl_verify = self.get_param('config.ssl_verify', None, 'Scirius Security Platform TLS verification info is missing') + tenant = self.get_param('config.tenant') + if tenant is not None and len(tenant): + self.tenant_param = "?tenant=" + tenant + else: + self.tenant_param = "" self.proxies = { "https" : self.get_param("config.proxy_https", None), "http" : self.get_param("config.proxy_http", None) @@ -64,7 +69,7 @@ def run(self): info = {} try: if self.data_type == 'ip': - url = self.base_url + "/rest/appliances/host_id/" + self.get_data() + url = self.base_url + "/rest/appliances/host_id/" + self.get_data() + self.tenant_param resp = self.session.get(url, verify=self.ssl_verify, proxies=self.proxies) info = resp.json() # TODO add support for user-agent and fqdn From 299be6e305944d98b59fdc30cb65b68c01d376eb Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Sun, 14 Mar 2021 18:58:34 +0100 Subject: [PATCH 5/6] StamusNetworks: handle error from REST API --- analyzers/StamusNetworks/hostid_analyzer.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/analyzers/StamusNetworks/hostid_analyzer.py b/analyzers/StamusNetworks/hostid_analyzer.py index 3e464ddec..d7c19dc08 100755 --- a/analyzers/StamusNetworks/hostid_analyzer.py +++ b/analyzers/StamusNetworks/hostid_analyzer.py @@ -27,6 +27,8 @@ def __init__(self): def artifacts(self, raw): artifacts = [] + if raw.get('host_id') is None: + return [] hostnames = raw['host_id'].get('hostname', []) for host in hostnames: tags=["first-seen:" + host['first_seen'], "last-seen:" + host['last_seen']] @@ -71,6 +73,7 @@ def run(self): if self.data_type == 'ip': url = self.base_url + "/rest/appliances/host_id/" + self.get_data() + self.tenant_param resp = self.session.get(url, verify=self.ssl_verify, proxies=self.proxies) + resp.raise_for_status() info = resp.json() # TODO add support for user-agent and fqdn else: From 6d1b1e4cb3f504068886ebe4c06e205f4cb668a6 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Sat, 20 Mar 2021 00:59:45 +0100 Subject: [PATCH 6/6] StamusNetworks: add TheHive templates --- .../StamusNetworks_HostID_1_0/long.html | 80 +++++++++++++++++++ .../StamusNetworks_HostID_1_0/short.html | 3 + 2 files changed, 83 insertions(+) create mode 100644 thehive-templates/StamusNetworks_HostID_1_0/long.html create mode 100644 thehive-templates/StamusNetworks_HostID_1_0/short.html diff --git a/thehive-templates/StamusNetworks_HostID_1_0/long.html b/thehive-templates/StamusNetworks_HostID_1_0/long.html new file mode 100644 index 000000000..c18f81669 --- /dev/null +++ b/thehive-templates/StamusNetworks_HostID_1_0/long.html @@ -0,0 +1,80 @@ + +
+
+ {{(artifact.data || artifact.attachment.name) | fang}} + View All ({{::content.records.length}}) +
+
+

+ SSP Host Information Report +

+
+

Services for IP

+ + + + + + + + + + + + + +
#ProtoPort
{{$index + 1}}{{row.proto}}{{row.port}}
+
+
+

Username

+ + + + + + + + + + + + + + + +
#UsernameFirst SeenLast Seen
{{$index + 1}}{{row.user}}{{row.first_seen}}{{row.last_seen}}
+
+
+

Username

+ + + + + + + + + + + + + + + +
#HTTP User AgentFirst SeenLast Seen
{{$index + 1}}{{row.agent}}{{row.first_seen}}{{row.last_seen}}
+
+
+ +
+ + +
+
+ Error while running the service +
+
+
+        {{content.errorMessage}}
+        
+
+
diff --git a/thehive-templates/StamusNetworks_HostID_1_0/short.html b/thehive-templates/StamusNetworks_HostID_1_0/short.html new file mode 100644 index 000000000..5fc0dabfb --- /dev/null +++ b/thehive-templates/StamusNetworks_HostID_1_0/short.html @@ -0,0 +1,3 @@ + + {{t.namespace}}:{{t.predicate}}="{{t.value}}" +