Skip to content

Commit

Permalink
Merge pull request #725 from amr-cossi/add-opencti-analyzer
Browse files Browse the repository at this point in the history
Add OpenCTI Analyzer v1
  • Loading branch information
garanews authored Apr 27, 2020
2 parents 8d638c8 + d9cd614 commit 6263ff1
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 0 deletions.
57 changes: 57 additions & 0 deletions analyzers/OpenCTI/OpenCTI.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "OpenCTI_SearchObservable",
"author": "ANSSI",
"license": "AGPL-V3",
"url": "https://github.com/TheHive-Project/Cortex-Analyzers/",
"version": "1.0",
"description": "Query multiple OpenCTI instances for an observable.",
"dataTypeList": [
"domain",
"ip",
"url",
"fqdn",
"uri_path",
"user-agent",
"hash",
"email",
"mail",
"mail_subject",
"registry",
"regexp",
"other",
"filename"
],
"baseConfig": "OpenCTI",
"command": "OpenCTI/opencti.py",
"configurationItems": [
{
"name": "name",
"description": "Name of OpenCTI servers",
"multi": true,
"required": false,
"type": "string"
},
{
"name": "url",
"description": "URL of OpenCTI servers",
"type": "string",
"multi": true,
"required": true
},
{
"name": "key",
"description": "API key for each server",
"type": "string",
"multi": true,
"required": true
},
{
"name": "cert_check",
"description": "Verify server certificate",
"type": "boolean",
"multi": false,
"required": true,
"defaultValue": true
}
]
}
119 changes: 119 additions & 0 deletions analyzers/OpenCTI/opencti.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/usr/bin/env python3
from cortexutils.analyzer import Analyzer
from pycti import OpenCTIApiClient

class OpenCTIAnalyzer(Analyzer):
"""Searches for given Observables in configured OpenCTI instances. All standard data types are supported."""

def __init__(self):
Analyzer.__init__(self)

self.service = self.get_param(
'config.service', "search_observable", None)

ssl = self.get_param('config.cert_check', True)
names = self.get_param('config.name', None, 'No OpenCTI instance name given.')
urls = self.get_param('config.url', None, 'No OpenCTI url given.')
keys = self.get_param('config.key', None, 'No OpenCTI api key given.')

if len(names) != len(urls) or len(urls) != len(keys):
self.error("Config error: please add a name, an url and a key for each OpenCTI instance.")

else:
try:
self.openctis = []
for i in range(len(names)):
self.openctis.append({
"name": names[i],
"url": urls[i],
"api_client": OpenCTIApiClient(
urls[i],
keys[i],
"error",
ssl,
)
})
except Exception as e:
self.error(str(e))

def summary(self, raw):
taxonomies = []
level = "info"
namespace = "OpenCTI"
predicate = "Search Observable"

data = []
found = False
for r in raw['results']:
if r['observable']:
found = True
for res in r['reports']:
if 'id' in res:
data.append(res['id'])

# return number of reports
value = "Found - " if found else "Not found - "
if not data:
value += "0 reports"
taxonomies.append(self.build_taxonomy(level, namespace, predicate, value))
else:
value += "{} report(s)".format(len(list(set(data))))
level = "suspicious"
taxonomies.append(self.build_taxonomy(level, namespace, predicate, value))

return {"taxonomies": taxonomies}

def run(self):

data = self.get_param('data', None, 'Data is missing')

response = []

for opencti in self.openctis:
# Lookup observable
observable = opencti["api_client"].stix_observable.read(
filters=[{"key": "observable_value", "values": [data]}]
)
reports = []
if observable:
# Strip observable data for lighter output.
del(observable["markingDefinitionsIds"])
del(observable["tagsIds"])
del(observable["externalReferencesIds"])
del(observable["indicatorsIds"])

# Get a list of reports containing this observable
reports = opencti["api_client"].report.list(
filters=[
{
"key": "observablesContains",
"values": [observable["id"]],
}
]
)

# Strip reports data for lighter output.
for r in reports:
del(r["graph_data"])
del(r["objectRefs"])
del(r["observableRefs"])
del(r["relationRefs"])
del(r["markingDefinitionsIds"])
del(r["tagsIds"])
del(r["externalReferencesIds"])
del(r["objectRefsIds"])
del(r["observableRefsIds"])
del(r["relationRefsIds"])

response.append({
"name": opencti["name"],
"url": opencti["url"],
"observable": observable,
"reports": reports
})

self.report({'results': response})


if __name__ == '__main__':
OpenCTIAnalyzer().run()
2 changes: 2 additions & 0 deletions analyzers/OpenCTI/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cortexutils
pycti
136 changes: 136 additions & 0 deletions thehive-templates/OpenCTI_SearchObservable_1_0/long.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<div class="panel panel-info" ng-repeat="res in content.results">
<div class="panel-heading">
<b>OpenCTI {{res.name}}</b> - Report from {{res.url}}
</div>
<div class="panel-body">
<div ng-if="res.observable==undefined">
<dl class="dl-horizontal">
<dt><i class="fa fa-warning"></i> No results</dt>
<dd>No results from OpenCTI {{res.name}}</dd>
</dl>
</div>
<div ng-if="res.observable!==undefined">
<dl class="dl-horizontal">
<dt>Observable Id:</dt>
<dd><a target="_blank" href="{{res.url}}/dashboard/signatures/observables/{{res.observable.id}}">{{res.observable.id}}</a></dd>
</dl>
<dl class="dl-horizontal">
<dt>Entity Type:</dt>
<dd>{{res.observable.entity_type}}</dd>
</dl>
<dl class="dl-horizontal">
<dt>Created on:</dt>
<dd>{{res.observable.created_at}}</dd>
</dl>
<dl class="dl-horizontal">
<dt>Created by:</dt>
<dd><a target="_blank" href="{{res.url}}/dashboard/entities/organizations/{{res.observable.createdByRef.id}}">{{res.observable.createdByRef.name}}</a></dd>
</dl>
<dl class="dl-horizontal" ng-if="res.observable.markingDefinitions.length > 0" >
<dt>Marking Definitions:</dt>
<dd ng-repeat="md in res.observable.markingDefinitions">
<span ng-if="md.color==='#ffffff'" class="label"
ng-style="{'border':'1px solid','color': '#000000', 'background-color': md.color}">{{md.definition}}
</span>
<span ng-if="md.color!=='#ffffff'" class="label"
ng-style="{'background-color': md.color}">{{md.definition}}
</span>
</dd>
</dl>
<dl class="dl-horizontal" ng-if="res.observable.tags.length > 0" >
<dt>Tags:</dt>
<dd ng-repeat="tag in res.observable.tags">
<span ng-if="tag.color==='#ffffff'" class="label"
ng-style="{'border':'1px solid','color': '#000000', 'background-color': tag.color}">{{tag.tag_type}}:{{tag.value}}
</span>
<span ng-if="tag.color!=='#ffffff'" class="label"
ng-style="{'background-color': tag.color}">{{tag.tag_type}}:{{tag.value}}
</span>
</dd>
</dl>
<dl class="dl-horizontal" ng-if="res.observable.externalReferences.length > 0" >
<dt>External refs:</dt>
<dd ng-repeat="extref in res.observable.externalReferences">
<a target="_blank" href="{{extref.url}}">{{extref.source_name}}</a>
</dd>
</dl>
<dl class="dl-horizontal" ng-if="res.observable.indicators.length > 0" >
<dt>Indicators:</dt>
<dd ng-repeat="ind in res.observable.indicators">
<a target="_blank" href="{{res.url}}/dashboard/signatures/indicators/{{ind.id}}">{{ind.indicator_pattern}}</a>
</dd>
</dl>
</div>
<div ng-repeat="report in res.reports">
<dl class="dl-horizontal">
<dt>Report Id:</dt>
<dd><a target="_blank" href="{{res.url}}/dashboard/reports/all/{{report.id}}">{{report.id}}</a></dd>
</dl>
<dl class="dl-horizontal">
<dt>Report class:</dt>
<dd>{{report.report_class}}</dd>
</dl>
<dl class="dl-horizontal">
<dt>Name:</dt>
<dd>{{report.name}}</dd>
</dl>
<dl class="dl-horizontal">
<dt>Description:</dt>
<dd>{{report.description}}</dd>
</dl>
<dl class="dl-horizontal">
<dt>Published on:</dt>
<dd>{{report.published}}</dd>
</dl>
<dl class="dl-horizontal">
<dt>Source confidence level:</dt>
<dd>{{report.source_confidence_level}}</dd>
</dl>
<dl class="dl-horizontal">
<dt>Created by:</dt>
<dd><a target="_blank" href="{{res.url}}/dashboard/entities/organizations/{{report.createdByRef.id}}">{{report.createdByRef.name}}</a></dd>
</dl>
<dl class="dl-horizontal" ng-if="report.markingDefinitions.length > 0" >
<dt>Marking Definitions:</dt>
<dd ng-repeat="md in report.markingDefinitions">
<span ng-if="md.color==='#ffffff'" class="label"
ng-style="{'border':'1px solid','color': '#000000', 'background-color': md.color}">{{md.definition}}
</span>
<span ng-if="md.color!=='#ffffff'" class="label"
ng-style="{'background-color': md.color}">{{md.definition}}
</span>
</dd>
</dl>
<dl class="dl-horizontal" ng-if="report.tags.length > 0" >
<dt>Tags:</dt>
<dd ng-repeat="tag in report.tags">
<span ng-if="tag.color==='#ffffff'" class="label"
ng-style="{'border':'1px solid','color': '#000000', 'background-color': tag.color}">{{tag.tag_type}}:{{tag.value}}
</span>
<span ng-if="tag.color!=='#ffffff'" class="label"
ng-style="{'background-color': tag.color}">{{tag.tag_type}}:{{tag.value}}
</span>
</dd>
</dl>
<dl class="dl-horizontal" ng-if="report.externalReferences.length > 0" >
<dt>External refs:</dt>
<dd ng-repeat="extref in report.externalReferences">
<a target="_blank" href="{{extref.url}}">{{extref.source_name}}</a>
</dd>
</dl>
<hr>
<br>
</div>
</div>
</div>


<!-- General error -->
<div class="panel panel-danger" ng-if="!success">
<div class="panel-heading">
<strong>{{(artifact.data || artifact.attachment.name) | fang}}</strong>
</div>
<div class="panel-body">
{{content.errorMessage}}
</div>
</div>
3 changes: 3 additions & 0 deletions thehive-templates/OpenCTI_SearchObservable_1_0/short.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<span class="label" ng-repeat="t in content.taxonomies" ng-class="{'info': 'label-info', 'safe': 'label-success', 'suspicious': 'label-warning', 'malicious':'label-danger'}[t.level]">
{{t.namespace}}:{{t.predicate}}="{{t.value}}"
</span>

0 comments on commit 6263ff1

Please sign in to comment.