Skip to content

Commit

Permalink
Merge pull request #483 from RedLegg/master
Browse files Browse the repository at this point in the history
Updating to use new API
  • Loading branch information
dadokkio authored Jun 17, 2020
2 parents 337a4dd + 17dad85 commit 52040d7
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 45 deletions.
12 changes: 6 additions & 6 deletions analyzers/SinkDB/SinkDB.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"name": "SinkDB",
"author": "Nils Kuhnert, CERT-Bund",
"author": "Mark Kikta, RedLegg Cybersecurity Solutions",
"license": "AGPL-V3",
"url": "https://github.com/BSI-CERT-Bund/sinkdb-analyzer",
"version": "1.0",
"description": "Check if ip is sinkholed via sinkdb.abuse.ch",
"dataTypeList": ["ip"],
"url": "https://github.com/RedLegg/sinkdb-analyzer",
"version": "1.1",
"description": "Check if ip is sinkholed via the new sinkdb.abuse.ch HTTPS API. Original analyzer can be found at https://github.com/BSI-CERT-Bund/sinkdb-analyzer",
"dataTypeList": ["ip", "domain", "mail"],
"command": "SinkDB/sinkdb.py",
"baseConfig": "SinkDB",
"configurationItems": [
{
"name": "key",
"description": "Define the API Key",
"description": "Define the HTTPS API Key",
"type": "string",
"multi": false,
"required": true
Expand Down
95 changes: 60 additions & 35 deletions analyzers/SinkDB/sinkdb.py
Original file line number Diff line number Diff line change
@@ -1,52 +1,77 @@
#!/usr/bin/env python3
import subprocess
#!/usr/bin/env python
import json, requests, traceback

from cortexutils.analyzer import Analyzer


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

if self.data_type != 'ip':
self.error('SinkDB Analyzer only usable with ip data type.')
if self.data_type not in ['ip', 'domain', 'mail']:
self.error('SinkDB Analyzer only usable with the ip, domain, and mail data types.')

self.apikey = self.get_param('config.key', None, 'API Key needed for querying SinkDB.')
self.data = self.get_data().split('.')
self.data.reverse()
self.data = '.'.join(self.data)
self.apikey = self.get_param('config.key', None, 'HTTPS API Key needed for querying SinkDB.')
self.data = self.get_data()

def dig(self, ip):
proc = subprocess.Popen(['dig', '+short', '{}.{}.sinkdb-api.abuse.ch'.format(ip, self.apikey)],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = proc.communicate()
out = out.decode('utf-8').strip('\n')
def query_db(self, indicator):

if err:
self.error('Error while calling dig: {}.'.format(err))
if self.data_type == 'ip':
return self.parse_entries(json.loads(self.do_post("api_key={}&ipv4={}".format(self.apikey, self.data)).text))

if out == '127.0.0.2':
return True
elif self.data_type == 'domain':
return self.parse_entries(json.loads(self.do_post("api_key={}&domain={}".format(self.apikey, self.data)).text))

return False
elif self.data_type == 'mail':
return self.parse_entries(json.loads(self.do_post("api_key={}&email={}".format(self.apikey, self.data)).text))

def run(self):
self.report({
"is_sinkhole": self.dig(self.data)
})
else:
raise TypeError('Error in query_db function. This error should not occur.')

def summary(self, raw):
taxonomies = []
def parse_entries(self, entries):
ret = {
"Sinkhole": [],
"Phishing": [],
"Scanner": []
}
if entries['query_status'] == 'ok':
for entry in entries['results']:
if entry['source'] == 'sinkhole':
ret['Sinkhole'].append(entry)
elif entry['source'] == 'awareness':
ret['Phishing'].append(entry)
elif entry['source'] == 'scanner':
ret['Scanner'].append(entry)
return ret
elif entries['query_status'] == 'no_results':
return ret
elif entries['query_status'] == 'invalid_ipaddress':
self.error("SinkDB did not recognize the IP as valid. Here is the full response:\n{}".format(json.dumps(entries)))
else:
self.error("There was an unknown error communicating with the SinkDB API. Here is the full response:\n{}".format(json.dumps(entries)))

if raw.get('is_sinkhole'):
taxonomies.append(self.build_taxonomy('safe', 'SinkDB', 'IsSinkhole', 'True'))
else:
taxonomies.append(self.build_taxonomy('suspicious', 'SinkDB', 'IsSinkhole', 'False'))
return {
"taxonomies": taxonomies
}
def do_post(self, data):
return requests.post('https://sinkdb-api.abuse.ch/api/v1/', headers={"Content-Type": "application/x-www-form-urlencoded"}, data=data)

def run(self):
try:
self.report(self.query_db(self.data))
except:
self.error("Error when attempting to retrieve data:\n{}".format(traceback.format_exc()))

def summary(self, raw):
taxonomies = []

for k, v in raw.iteritems():
if v:
taxonomies.append(self.build_taxonomy('suspicious', 'SinkDB', k, 'True'))
else:
taxonomies.append(self.build_taxonomy('safe', 'SinkDB', k, 'False'))

return {
"taxonomies": taxonomies
}


if __name__ == '__main__':
SinkDBAnalyzer().run()
SinkDBAnalyzer().run()
81 changes: 77 additions & 4 deletions thehive-templates/SinkDB_1_0/long.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,84 @@
<dt>Status</dt>
<dd>
<p style="font-size: 1.5em;">
<span class="label label-success" ng-if="content.is_sinkhole">
IP is sinkholed.
<span class="label label-warning" ng-if="content.Sinkhole.length > 0">
Artifact is sinkholed.

<table class="table" ng-if="content.Sinkhole.length !== 0 ">
<thead>
<th>SinkDB ID</th>
<th>SinkDB URL</th>
<th>Type</th>
<th>Classification</th>
<th>Operator</th>
</thead>
<tbody ng-repeat="r in content.Sinkhole | orderBy:'-date_added'">
<tr>
<td>{{r.id}}</td>
<td>{{r.sinkdb_reference}}</td>
<td>{{r.type}}</td>
<td>{{r.classification}}</td>
<td>{{r.operator}}</td>
</tr>
</tbody>
</table>
</span>
<span class="label label-success" ng-if="content.Sinkhole.length == 0">
Artifact is <strong>not</strong> sinkholed.
</span>
</p>
<p style="font-size: 1.5em;">
<span class="label label-warning" ng-if="content.Phishing.length > 0">
Artifact is part of a phishing awareness Campaign.

<table class="table" ng-if="content.Phishing.length !== 0 ">
<thead>
<th>SinkDB ID</th>
<th>SinkDB URL</th>
<th>Type</th>
<th>Classification</th>
<th>Operator</th>
</thead>
<tbody ng-repeat="r in content.Phishing | orderBy:'-date_added'">
<tr>
<td>{{r.id}}</td>
<td>{{r.sinkdb_reference}}</td>
<td>{{r.type}}</td>
<td>{{r.classification}}</td>
<td>{{r.operator}}</td>
</tr>
</tbody>
</table>
</span>
<span class="label label-success" ng-if="content.Phishing.length == 0">
Artifact is <strong>not</strong> part of a phishing awareness campaign.
</span>
</p>
<p style="font-size: 1.5em;">
<span class="label label-warning" ng-if="content.Scanner.length > 0">
Artifact is a scanner.

<table class="table" ng-if="content.Scanner.length !== 0 ">
<thead>
<th>SinkDB ID</th>
<th>SinkDB URL</th>
<th>Type</th>
<th>Classification</th>
<th>Operator</th>
</thead>
<tbody ng-repeat="r in content.Scanner | orderBy:'-date_added'">
<tr>
<td>{{r.id}}</td>
<td>{{r.sinkdb_reference}}</td>
<td>{{r.type}}</td>
<td>{{r.classification}}</td>
<td>{{r.operator}}</td>
</tr>
</tbody>
</table>
</span>
<span class="label label-warning" ng-if="!content.is_sinkhole">
IP is <strong>not</strong> sinkholed.
<span class="label label-success" ng-if="content.Scanner.length == 0">
Artifact is <strong>not</strong> a scanner.
</span>
</p>
</dd>
Expand Down

0 comments on commit 52040d7

Please sign in to comment.