Skip to content

Commit

Permalink
Working copy of Backscatter.io analyzer (#420)
Browse files Browse the repository at this point in the history
  • Loading branch information
9b authored and nadouani committed Feb 12, 2019
1 parent 884db2b commit fdc8e5b
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 0 deletions.
26 changes: 26 additions & 0 deletions analyzers/BackscatterIO/BackscatterIO_Enrichment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "BackscatterIO_Enrichment",
"version": "1.0",
"author": "[email protected]",
"url": "https://github.com/TheHive-Project/Cortex-Analyzers",
"license": "APLv2",
"description": "Enrich values using Backscatter.io data.",
"dataTypeList": ["ip", "network", "autonomous-system", "port"],
"baseConfig": "BackscatterIO",
"command": "BackscatterIO/backscatter-io.py",
"configurationItems": [
{
"name": "key",
"description": "API key for Backscatter.io",
"type": "string",
"multi": false,
"required": true
}
],
"config": {
"check_tlp": true,
"max_tlp": 2,
"auto_extract": true,
"service": "enrichment"
}
}
26 changes: 26 additions & 0 deletions analyzers/BackscatterIO/BackscatterIO_GetObservations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "BackscatterIO_GetObservations",
"version": "1.0",
"author": "[email protected]",
"url": "https://github.com/TheHive-Project/Cortex-Analyzers",
"license": "APLv2",
"description": "Determine whether a value has known scanning activity using Backscatter.io data.",
"dataTypeList": ["ip", "network", "autonomous-system"],
"baseConfig": "BackscatterIO",
"command": "BackscatterIO/backscatter-io.py",
"configurationItems": [
{
"name": "key",
"description": "API key for Backscatter.io",
"type": "string",
"multi": false,
"required": true
}
],
"config": {
"check_tlp": true,
"max_tlp": 2,
"auto_extract": true,
"service": "observations"
}
}
105 changes: 105 additions & 0 deletions analyzers/BackscatterIO/backscatter-io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from backscatter import Backscatter
from collections import defaultdict, OrderedDict
from cortexutils.analyzer import Analyzer


class BackscatterAnalyzer(Analyzer):

"""
Backscatter.io API docs: https://backscatter.io/developers
"""

def __init__(self):
"""Setup the Backscatter object."""
Analyzer.__init__(self)
self.api_key = self.get_param('config.key', None, 'No Backscatter.io API key provided.')
self.proxies = {
"https" : self.get_param("config.proxy_https"),
"http" : self.get_param("config.proxy_http")
}
kwargs = {'api_key': self.api_key, 'headers': {'X-Integration': 'TheHive'}}
if self.proxies['https'] or self.proxies['http']:
kwargs.update({'proxies': self._proxies})
self.bs = Backscatter(**kwargs)
self.service = self.get_param('config.service', None, 'Backscatter service is missing')

def run(self):
"""Run the process to get observation data from Backscatter.io."""
kwargs = {'query': self.get_data()}
if self.data_type == "ip":
kwargs.update({'query_type': 'ip'})
elif self.data_type == "network":
kwargs.update({'query_type': 'network'})
elif self.data_type == 'autonomous-system':
kwargs.update({'query_type': 'asn'})
elif self.data_type == 'port':
kwargs.update({'query_type': 'port'})
else:
self.notSupported()
return False

if self.service == 'observations':
response = self.bs.get_observations(**kwargs)
self.report(response)
elif self.service == 'enrichment':
response = self.bs.enrich(**kwargs)
self.report(response)
else:
self.report({'error': 'Invalid service defined.'})

def summary(self, raw):
"""Use the Backscatter.io summary data to create a view."""
try:
taxonomies = list()
level = 'info'
namespace = 'Backscatter.io'

if self.service == 'observations':
summary = raw.get('results', dict()).get('summary', dict())
taxonomies = taxonomies + [
self.build_taxonomy(level, namespace, 'Observations', str(summary.get('observations_count', 0))),
self.build_taxonomy(level, namespace, 'IP Addresses', str(summary.get('ip_address_count', 0))),
self.build_taxonomy(level, namespace, 'Networks', str(summary.get('network_count', 0))),
self.build_taxonomy(level, namespace, 'AS', str(summary.get('autonomous_system_count', 0))),
self.build_taxonomy(level, namespace, 'Ports', str(summary.get('port_count', 0))),
self.build_taxonomy(level, namespace, 'Protocols', str(summary.get('protocol_count', 0)))
]
elif self.service == 'enrichment':
summary = raw.get('results', dict())
if self.data_type == 'ip':
taxonomies = taxonomies + [
self.build_taxonomy(level, namespace, 'Network', summary.get('network')),
self.build_taxonomy(level, namespace, 'Network Broadcast', summary.get('network_broadcast')),
self.build_taxonomy(level, namespace, 'Network Size', summary.get('network_size')),
self.build_taxonomy(level, namespace, 'Country', summary.get('country_name')),
self.build_taxonomy(level, namespace, 'AS Number', summary.get('as_num')),
self.build_taxonomy(level, namespace, 'AS Name', summary.get('as_name')),
]
elif self.data_type == 'network':
taxonomies = taxonomies + [
self.build_taxonomy(level, namespace, 'Network Size', summary.get('network_size'))
]
elif self.data_type == 'autonomous-system':
taxonomies = taxonomies + [
self.build_taxonomy(level, namespace, 'Prefix Count', summary.get('prefix_count')),
self.build_taxonomy(level, namespace, 'AS Number', summary.get('as_num')),
self.build_taxonomy(level, namespace, 'AS Name', summary.get('as_name'))
]
elif self.data_type == 'port':
for result in raw.get('results', list()):
display = "%s (%s)" % (result.get('service'), result.get('protocol'))
taxonomies.append(self.build_taxonomy(level, namespace, 'Service', display))
else:
pass
else:
pass
return {"taxonomies": taxonomies}

except Exception as e:
self.error('Summary failed\n{}'.format(e.message))


if __name__ == '__main__':
BackscatterAnalyzer().run()
2 changes: 2 additions & 0 deletions analyzers/BackscatterIO/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cortexutils
backscatter
21 changes: 21 additions & 0 deletions thehive-templates/BackscatterIO_Enrichment_1_0/long.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div class="panel panel-info" ng-if="success">
<div class="panel-heading">
Backscatter.io results for <strong>{{artifact.data}}</strong>
</div>
<div class="panel-body">
<div ng-repeat="(k,v) in content.results">
<span><strong>{{k}}:</strong> {{v}}</spam>
</div>
<p ng-if="!content.results">No records found for {{artifact.data}}.</p>
</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/BackscatterIO_Enrichment_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>
62 changes: 62 additions & 0 deletions thehive-templates/BackscatterIO_GetObservations_1_0/long.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<div class="panel panel-info" ng-if="success">
<div class="panel-heading">
Backscatter.io results for <strong>{{artifact.data}}</strong>
</div>
<div class="panel-body">
<table class="table" ng-if="content.results.summary">
<tbody>
<tr>
<th>Observation Count</th>
<td>{{content.results.summary['observations_count']}}</td>
</tr>
<tr>
<th>IP Address Count</th>
<td>{{content.results.summary['ip_address_count']}}</td>
</tr>
<tr>
<th>Network Count</th>
<td>{{content.results.summary['network_count']}}</td>
</tr>
<tr>
<th>AS Count</th>
<td>{{content.results.summary['autonomous_system_count']}}</td>
</tr>
<tr>
<th>Port Count</th>
<td>{{content.results.summary['port_count']}}</td>
</tr>
<tr>
<th>Protocol Count</th>
<td>{{content.results.summary['protocol_count']}}</td>
</tr>
</tbody>
</table>
<table class="table" ng-if="content.results.observations">
<thead>
<th>Observed</th>
<th>Protocol</th>
<th>Destination Port</th>
<th>Length</th>
</thead>
<tbody ng-repeat="record in content.results.observations">
<tr>
<td>{{record['observed']}}</td>
<td>{{record['protocol']}}</td>
<td>{{record['dst_port']}}</td>
<td>{{record['length']}}</td>
</tr>
</tbody>
</table>
<p ng-if="!content.results.observations">No records found for {{artifact.data}}.</p>
</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>
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 fdc8e5b

Please sign in to comment.