Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

created FireEyeiSight analyzer #202

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions analyzers/FireEyeiSight/FireEyeiSight.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "FireEyeiSight",
"version": "1.0",
"author": "Davide Arcuri, Andrea Garavaglia - LDO-CERT",
"url": "https://github.com/LDO-CERT/Cortex-Analyzers",
"license": "AGPL-V3",
"description": "iSIGHT API extends FireEye cyber threat intelligence products and associated technical indicators so that customers and partners can easily match indicators to rich intelligence context, ingest indicator data associated with intelligence reporting, and collect and consume intelligence reports. Integrating data tied to context allows the people, processes, and technologies within intelligence-led security organizations to more efficiently and effectively employ knowledge to proactively defend their business.",
"dataTypeList": ["domain", "ip", "hash", "url"],
"baseConfig": "FireEyeiSight",
"config": {
"check_tlp": true,
"max_tlp": 2,
"service": "query"
},
"command": "FireEyeiSight/fireeyeisight_lookup.py"
}
172 changes: 172 additions & 0 deletions analyzers/FireEyeiSight/fireeyeisight_lookup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#!/usr/bin/env python
# encoding: utf-8
import json
import requests
import hashlib
import hmac
import email
from datetime import datetime, date

from cortexutils.analyzer import Analyzer

class APIRequestHandler(object):

def __init__(self, public_key, private_key):
self.URL = 'https://api.isightpartners.com'
self.public_key = public_key
self.private_key = private_key
self.accept_version = '2.5'

def exec_query(self, endpoint):
time_stamp = email.utils.formatdate(localtime=True)
accept_header = 'application/json'
new_data = endpoint + self.accept_version + accept_header + time_stamp

key = bytearray()
key.extend(map(ord, self.private_key))
hashed = hmac.new(key, new_data.encode('utf-8'), hashlib.sha256)

headers = {
'Accept': accept_header,
'Accept-Version': self.accept_version,
'X-Auth': self.public_key,
'X-Auth-Hash': hashed.hexdigest(),
'Date': time_stamp,
}

r = requests.get(self.URL + endpoint, headers=headers)

if r.status_code == 200:
return r.json()
else:
return -1


class FireEyeiSightAnalyzer(Analyzer):

def __init__(self):
Analyzer.__init__(self)
self.service = self.getParam(
'config.service', None, 'Service parameter is missing')
self.url = self.getParam('config.url', None, 'Missing API url')
self.key = self.getParam('config.key', None, 'Missing API key')
self.pwd = self.getParam('config.pwd', None, 'Missing API password')
self.request_handler = APIRequestHandler(self.key, self.pwd)

def cleanup(self, data_info=[]):
response = {
'level': 'no-info',
'score': 0,
'domain': [],
'ip': [],
'md5': [],
'sha1': [],
'sha256': [],
'intelligenceType': [],
'webLink': [],
'identifier': [],
'observationTime': [],
'ThreatScape':[],
'title': [],
'size': [],
'fileName': [],
'packer': [],
'actor': [],
'report_data': []
}

json_fields = ['domain', 'intelligenceType', 'ip', 'title', 'webLink', 'observationTime', 'ThreatScape', 'sha1', 'sha256', 'md5', 'size', 'fileName', 'packer', 'actor']
json_unique_fields = ['domain', 'ip', 'sha1', 'sha256', 'md5', 'size', 'fileName', 'packer', 'actor']

for report in data_info:

identifier = report.get('fileIdentifier', None) if self.data_type == 'hash' else report.get('networkIdentifier', None)
if identifier and identifier not in response['identifier']:
response['identifier'].append(identifier)

for field in json_fields:
field_value = report.get(field, None)
if field == 'observationTime':
field_value = datetime.fromtimestamp(field_value).strftime('%Y-%m-%d %H:%M:%S')
if field_value and field in json_unique_fields and field_value not in response[field]:
response[field].append(field_value)
elif field_value and field not in json_unique_fields:
response[field].append(field_value)

for identifier in response['identifier']:
if identifier in ['Attacker', 'Compromised']:
response['level'] = 'malicious'
elif identifier in ['Victim', 'Related'] and response['level'] != 'malicious':
response['level'] = 'safe'

for i in range(len(data_info)):
response['report_data'].append({'title': response['title'][i],
'threatScape': response['ThreatScape'][i],
'intelligenceType': response['intelligenceType'][i],
'webLink': response['webLink'][i],
'observationTime': response['observationTime'][i]})

response['score'] = len(data_info)

del response['title']
del response['ThreatScape']
del response['webLink']
del response['observationTime']
del response['intelligenceType']

return response

def query(self, data):
results = dict()
try:
r = self.request_handler.exec_query('/search/text?text=%s' % data)
report_ids = [x.get('reportId', None) for x in r['message']] if r != -1 else []
data_info = []
for report in report_ids:
r = self.request_handler.exec_query('/pivot/report/%s/indicator' % report)
if self.data_type == 'domain':
tmp_info = [x for x in r['message'].get('publishedIndicators', []) if x.get(
'domain', None) == data] if r != -1 else []
elif self.data_type == 'hash':
tmp_info = [x for x in r['message'].get('publishedIndicators', []) if x.get(
'md5', None) == data or x.get('sha1', None) == data or x.get('sha256', None) == data] if r != -1 else []
elif self.data_type == 'ip':
tmp_info = [x for x in r['message'].get('publishedIndicators', []) if x.get(
'ip', None) == data] if r != -1 else []
if tmp_info:
for x in tmp_info:
tmp_dict = {k: v for k, v in x.items() if v}
if tmp_dict not in data_info:
data_info.append(tmp_dict)
return self.cleanup(data_info)
except Exception as e:
self.error("OS error: {0}".format(e))
return results

def summary(self, raw):
taxonomies = []
level = "info"
namespace = "FireEyeiSight"
predicate = "Report"
score = raw['score']
level = raw['level']
if score > 0:
taxonomies.append(self.build_taxonomy(level, namespace, predicate, score))
return {"taxonomies": taxonomies}

def run(self):

if self.service == 'query':
data = self.getParam('data', None, 'Data is missing')
if self.data_type in ['domain', 'url', 'hash', 'ip']:
rep = self.query(data)
self.report(rep)
else:
self.error('Invalid data type')
else:
self.error('Invalid service')


if __name__ == '__main__':
FireEyeiSightAnalyzer().run()

2 changes: 2 additions & 0 deletions analyzers/FireEyeiSight/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cortexutils
requests
92 changes: 92 additions & 0 deletions thehive-templates/FireEyeiSight_Lookup_1_0/long.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<!-- Success case -->
<div ng-if="success">
<div class="panel panel-info">
<div class="panel-heading">
<strong>{{name}} report</strong>
</div>
<div class="panel-body">

<h4>FireEye iSIGHT information for {{artifact.data | fang}}</h4>

<dl class="dl-horizontal">
<dt>Level</dt>
<dd>{{content.level}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.domain.length > 0">
<dt>Domains</dt>
<dd ng-repeat="domain in content.domain">{{domain}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.ip.length > 0">
<dt>Ips</dt>
<dd ng-repeat="ip in content.ip">{{ip}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.md5.length > 0">
<dt>Md5</dt>
<dd ng-repeat="md5 in content.md5">{{md5}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.sha1.length > 0">
<dt>Sha1</dt>
<dd ng-repeat="sha1 in content.sha1">{{sha1}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.sha256.length > 0">
<dt>Sha256</dt>
<dd ng-repeat="sha256 in content.sha256">{{sha256}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.fileName.length > 0">
<dt>fileName</dt>
<dd ng-repeat="fileName in content.fileName">{{fileName}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.filename.length > 0">
<dt>File Name</dt>
<dd ng-repeat="filename in content.filename">{{filename}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.size.length > 0">
<dt>File Size</dt>
<dd ng-repeat="type in content.size">{{type}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.packer.length > 0">
<dt>File Packers</dt>
<dd ng-repeat="packer in content.packer">{{packer}}</dd>
</dl>
<dl class="dl-horizontal" ng-if="content.actor.length > 0">
<dt>Actor</dt>
<dd ng-repeat="actor in content.actor">{{actor}}</dd>
</dl>
</div>
</div>

<div class="panel panel-info">
<div class="panel-heading">
<strong>Reports</strong>
</div>
<div class="panel-body">
<table class="table table-hover">
<tr>
<th>Title</th>
<th>Intelligence Type</th>
<th>Threat Scape</th>
<th>Web Link</th>
<th>Observation Time</th>
</tr>
<tr ng-repeat="report in content.report_data">
<td>{{report.title}}</td>
<td>{{report.intelligenceType}}</td>
<td>{{report.threatScape}}</td>
<td><a href="{{report.webLink}}" target="_blank"> <span class="glyphicon glyphicon-file" aria-hidden="true"></span></a></td>
<td>{{report.observationTime}}</td>
</tr>
</table>
</div>
</div>

</div>

<!-- Failure case -->
<div class="panel panel-danger" ng-if="!success">
<div class="panel-heading">
<strong>{{artifact.data | fang}}</strong>
</div>
<div class="panel-body">
{{content.errorMessage}}
</div>
</div>
3 changes: 3 additions & 0 deletions thehive-templates/FireEyeiSight_Lookup_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>