Skip to content

Commit

Permalink
Added first version of censys.io analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
3c7 committed Dec 13, 2017
1 parent ae15f30 commit 388e635
Show file tree
Hide file tree
Showing 5 changed files with 348 additions and 0 deletions.
13 changes: 13 additions & 0 deletions analyzers/Censys/Censys.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "Censys",
"author": "Nils Kuhnert, CERT-Bund",
"license": "AGPL-V3",
"url": "https://github.com/BSI-CERT-Bund/censys-analyzer",
"version": "1.0",
"baseConfig": "Censys",
"config": {},
"description": "Check IPs, certificate hashs or domains against censys.io.",
"dataTypeList": ["ip", "hash", "domain"],
"command": "Censys/censys_analyzer.py"
}

118 changes: 118 additions & 0 deletions analyzers/Censys/censys_analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env python3
from cortexutils.analyzer import Analyzer
from censys.certificates import CensysCertificates
from censys.ipv4 import CensysIPv4
from censys.websites import CensysWebsites
from censys.base import CensysNotFoundException, CensysRateLimitExceededException, CensysUnauthorizedException


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

self.__uid = self.get_param(
'config.uid',
None,
'No UID for Censys given. Please add it to the cortex configuration.'
)
self.__api_key = self.get_param(
'config.key',
None,
'No API-Key for Censys given. Please add it to the cortex configuration.'
)

def search_hosts(self, ip):
"""
Searches for a host using its ipv4 address
:param ip: ipv4 address as string
:type ip: str
:return: dict
"""
c = CensysIPv4(api_id=self.__uid, api_secret=self.__api_key)
return c.view(ip)

def search_certificate(self, hash):
"""
Searches for a specific certificate using its hash
:param hash: certificate hash
:type hash: str
:return: dict
"""
c = CensysCertificates(api_id=self.__uid, api_secret=self.__api_key)
return c.view(hash)

def search_website(self, dom):
"""
Searches for a website using the domainname
:param dom: domain
:type dom: str
:return: dict
"""
c = CensysWebsites(api_id=self.__uid, api_secret=self.__api_key)
return c.view(dom)

def run(self):
try:
if self.data_type == 'ip':
self.report({
'ip': self.search_hosts(self.get_data())
})
elif self.data_type == 'hash':
self.report({
'cert': self.search_certificate(self.get_data())
})
elif self.data_type == 'domain' or self.data_type == 'fqdn':
self.report({
'website': self.search_website(self.get_data())
})
else:
self.error('Data type not supported. Please use this analyzer with data types hash, ip or domain.')
except CensysNotFoundException:
self.error('{} not found.'.format(self.get_data()))
except CensysUnauthorizedException:
self.error('Censys raised NotAuthorizedException. Please check your credentials.')
except CensysRateLimitExceededException:
self.error('Rate limit exceeded.')

def summary(self, raw):
taxonomies = []
if 'ip' in raw:
raw = raw['ip']
service_count = len(raw.get('protocols', []))
heartbleed = raw.get('443', {}).get('https', {}).get('heartbleed', {}).get('heartbleed_vulnerable', False)

taxonomies.append(self.build_taxonomy('info', 'Censys', 'OpenServices', service_count))
if heartbleed:
taxonomies.append(self.build_taxonomy('malicious', 'Censys', 'Heartbleed', 'vulnerable'))
elif 'website' in raw:
raw = raw['website']
service_count = len(raw.get('tags', []))

taxonomies.append(self.build_taxonomy('info', 'Censys', 'OpenServices', service_count))
elif 'cert' in raw:
raw = raw['cert']
trusted_count = len(raw.get('validation', []))
validator_count = len(raw.get('validation', []))

for _, validator in raw.get('validation', []).items():
if validator.get('blacklisted', False) or \
validator.get('in_revocation_set', False) or \
(not validator.get('whitelisted', False) and not validator.get('valid', False)):
trusted_count -= 1
if trusted_count < validator_count:
taxonomies.append(self.build_taxonomy('suspicious', 'Censys', 'TrustedCount', '{}/{}'.format(
trusted_count, validator_count
)))
else:
taxonomies.append(self.build_taxonomy('info', 'Censys', 'TrustedCount', '{}/{}'.format(
trusted_count, validator_count
)))
return {
'taxonomies': taxonomies
}


if __name__ == '__main__':
CensysAnalyzer().run()
2 changes: 2 additions & 0 deletions analyzers/Censys/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cortexutils
censys
212 changes: 212 additions & 0 deletions thehive-templates/Censys_1_0/long.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
<div class="panel panel-info" ng-if="success">
<div class="panel-heading">
Censys.io information for <strong>{{artifact.data}}</strong>
</div>
<div class="panel-body">
<dl class="dl-horizontal">
<dt>Results:</dt>
<dd>
<div id="ip-results" ng-if="content.ip">
<table class="table">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>IP</td>
<td>{{content.ip.ip}}</td>
</tr>
<tr>
<td>Last update</td>
<td>{{content.ip.updated_at}}</td>
</tr>
<tr>
<td>Location</td>
<td>
{{content.ip.location.continent}} -
{{content.ip.location.country}} -
{{content.ip.location.province}} -
{{content.ip.location.city}}
</td>
</tr>
<tr>
<td>AS</td>
<td>{{content.ip.autonomous_system.asn}}: {{content.ip.autonomous_system.name}}</td>
</tr>
<tr ng-repeat="protocol in content.ip.ports">
<td>Info on port {{protocol}}</td>
<td>
<button class="btn btn-primary"
type="button"
data-toggle="collapse"
data-target="#collapse-{{protocol}}"
aria-expanded="false"
aria-controls="collapse-{{protocol}}">
Show/hide
</button>
<br />
<div class="collapse" id="collapse-{{protocol}}">
<div class="card card-body">
<pre>{{content.ip[protocol] | json}}</pre>
<button class="btn btn-primary"
type="button"
data-toggle="collapse"
data-target="#collapse-{{protocol}}"
aria-expanded="false"
aria-controls="collapse-{{protocol}}">
Show/hide
</button>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div id="hash-results" ng-if="content.cert">
<table class="table">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>Metadata</td>
<td>
<p>Source: {{content.cert.metadata.source}}</p>
<p>Added at: {{content.cert.metadata.added_at}}</p>
<p>Updated at: {{content.cert.metadata.updated_at}}</p>
</td>
</tr>
<tr>
<td>Added to CT</td>
<td>
<p>Comodo Mammoth<br />{{content.cert.ct.comodo_mammoth.added_to_ct_at}}</p>
<p>Comodo Sabre<br />{{content.cert.ct.comodo_sabre.added_to_ct_at}}</p>
<p>Google Pilot<br />{{content.cert.ct.google_pilot.added_to_ct_at}}</p>
<p>Google Rocketeer<br />{{content.cert.ct.google_rocketeer.added_to_ct_at}}</p>
<p>Symantec WS CT<br />{{content.cert.ct.symantec_ws_ct.added_to_ct_at}}</p>
</td>
</tr>
<tr>
<td>Issuer</td>
<td>
<p ng-repeat="cn in content.cert.parsed.issuer.common_name">{{cn}}</p>
</td>
</tr>
<tr>
<td>Validity</td>
<td>
<p>Valid since: {{content.cert.parsed.validity.start}}</p>
<p>Valid until: {{content.cert.parsed.validity.end}}</p>
</td>
</tr>
<tr>
<td>Full certificate data</td>
<td>
<button class="btn btn-primary"
type="button"
data-toggle="collapse"
data-target="#collapse-certdata"
aria-expanded="false"
aria-controls="collapse-certdata">
Show/hide
</button>
<br />
<div class="collapse" id="collapse-certdata">
<div class="card card-body">
<pre>{{content.cert | json}}</pre>
<button class="btn btn-primary"
type="button"
data-toggle="collapse"
data-target="#collapse-certdata"
aria-expanded="false"
aria-controls="collapse-certdata">
Show/hide
</button>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div id="website-results" ng-if="content.website">
<table class="table">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>Domain</td>
<td>{{content.website.domain}}</td>
</tr>
<tr>
<td>Last update</td>
<td>{{content.website.updated_at}}</td>
</tr>
<tr>
<td>Location</td>
<td>
{{content.website.location.continent}} -
{{content.website.location.country}} -
{{content.website.location.province}} -
{{content.website.location.city}}
</td>
</tr>
<tr>
<td>AS</td>
<td>{{content.website.autonomous_system.asn}}: {{content.website.autonomous_system.name}}</td>
</tr>
<tr ng-repeat="protocol in content.website.ports">
<td>Info on port {{protocol}}</td>
<td>
<button class="btn btn-primary"
type="button"
data-toggle="collapse"
data-target="#collapse-{{protocol}}"
aria-expanded="false"
aria-controls="collapse-{{protocol}}">
Show/hide
</button>
<br />
<div class="collapse" id="collapse-{{protocol}}">
<div class="card card-body">
<pre>{{content.website[protocol] | json}}</pre>
<button class="btn btn-primary"
type="button"
data-toggle="collapse"
data-target="#collapse-{{protocol}}"
aria-expanded="false"
aria-controls="collapse-{{protocol}}">
Show/hide
</button>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</dd>
</dl>
</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/Censys_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 388e635

Please sign in to comment.