From 388e63593e346d2df49e3bc974e83f76e47a7eaa Mon Sep 17 00:00:00 2001 From: 3c7 <3c7@posteo.de> Date: Wed, 13 Dec 2017 08:19:14 +0100 Subject: [PATCH] Added first version of censys.io analyzer --- analyzers/Censys/Censys.json | 13 ++ analyzers/Censys/censys_analyzer.py | 118 +++++++++++++ analyzers/Censys/requirements.txt | 2 + thehive-templates/Censys_1_0/long.html | 212 ++++++++++++++++++++++++ thehive-templates/Censys_1_0/short.html | 3 + 5 files changed, 348 insertions(+) create mode 100644 analyzers/Censys/Censys.json create mode 100755 analyzers/Censys/censys_analyzer.py create mode 100644 analyzers/Censys/requirements.txt create mode 100644 thehive-templates/Censys_1_0/long.html create mode 100644 thehive-templates/Censys_1_0/short.html diff --git a/analyzers/Censys/Censys.json b/analyzers/Censys/Censys.json new file mode 100644 index 000000000..cc1335f5d --- /dev/null +++ b/analyzers/Censys/Censys.json @@ -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" +} + diff --git a/analyzers/Censys/censys_analyzer.py b/analyzers/Censys/censys_analyzer.py new file mode 100755 index 000000000..676ec4348 --- /dev/null +++ b/analyzers/Censys/censys_analyzer.py @@ -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() diff --git a/analyzers/Censys/requirements.txt b/analyzers/Censys/requirements.txt new file mode 100644 index 000000000..9f65dca14 --- /dev/null +++ b/analyzers/Censys/requirements.txt @@ -0,0 +1,2 @@ +cortexutils +censys diff --git a/thehive-templates/Censys_1_0/long.html b/thehive-templates/Censys_1_0/long.html new file mode 100644 index 000000000..82b37d96c --- /dev/null +++ b/thehive-templates/Censys_1_0/long.html @@ -0,0 +1,212 @@ +
Key | +Value | +
---|---|
IP | +{{content.ip.ip}} | +
Last update | +{{content.ip.updated_at}} | +
Location | ++ {{content.ip.location.continent}} - + {{content.ip.location.country}} - + {{content.ip.location.province}} - + {{content.ip.location.city}} + | +
AS | +{{content.ip.autonomous_system.asn}}: {{content.ip.autonomous_system.name}} | +
Info on port {{protocol}} | +
+
+ +
+
+
+
+ {{content.ip[protocol] | json}}+ + |
+
Key | +Value | +
---|---|
Metadata | +
+ Source: {{content.cert.metadata.source}} +Added at: {{content.cert.metadata.added_at}} +Updated at: {{content.cert.metadata.updated_at}} + |
+
Added to CT | +
+ Comodo Mammoth Comodo Sabre Google Pilot Google Rocketeer Symantec WS CT |
+
Issuer | +
+ {{cn}} + |
+
Validity | +
+ Valid since: {{content.cert.parsed.validity.start}} +Valid until: {{content.cert.parsed.validity.end}} + |
+
Full certificate data | +
+
+ +
+
+
+
+ {{content.cert | json}}+ + |
+
Key | +Value | +
---|---|
Domain | +{{content.website.domain}} | +
Last update | +{{content.website.updated_at}} | +
Location | ++ {{content.website.location.continent}} - + {{content.website.location.country}} - + {{content.website.location.province}} - + {{content.website.location.city}} + | +
AS | +{{content.website.autonomous_system.asn}}: {{content.website.autonomous_system.name}} | +
Info on port {{protocol}} | +
+
+ +
+
+
+
+ {{content.website[protocol] | json}}+ + |
+