-
Notifications
You must be signed in to change notification settings - Fork 385
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #880 from uchakin/oscd
- Loading branch information
Showing
18 changed files
with
459 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Vulners-analyzer | ||
|
||
This analyzer consists of 2 parts. | ||
1. **Vulners_IOC**: As a result of collaboration between Vulners and RST Threat Feed, the idea was to send IOC analysis results through theHive analyzer: blog post | ||
2. **Vulners_CVE**: Vulners have a strong vulnerability database. This data is useful if: | ||
"if the case (incident) is related to the exploitation of a vulnerability, then the analyst (manually / automatically) can add it to observables and quickly get all the basic information on it in order to continue analyzing the case." | ||
|
||
Vulners API key required. | ||
|
||
## Setting up analyzer | ||
|
||
* copy the folders "Vulners" analyzer & "Vulners" into your Cortex analyzer path | ||
* install necessary python modules from the requirements.txt (**pip install -r requirements.txt**) | ||
* restart Cortex to initialize the new Responder "**systemctl restart cortex**" | ||
|
||
Get your Vulners api key:  | ||
|
||
Add your Vulners API in Cortex settings:  | ||
|
||
## Add Observable type in TheHive | ||
|
||
By default theHive does not have a "cve" type to be observables, so we have to add it to Administrator Settings: | ||
|
||
 | ||
|
||
## Run the Analyzer in TheHive | ||
|
||
####Network IOCs: | ||
|
||
Short template: | ||
|
||
 | ||
|
||
Long template: | ||
|
||
 | ||
|
||
|
||
 | ||
|
||
|
||
####Vulnerabilities: | ||
|
||
Short template: | ||
|
||
 | ||
|
||
Long template: | ||
|
||
 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"name": "Vulners_CVE", | ||
"version": "1.0", | ||
"author": "Dmitry Uchakin, Vulners team", | ||
"url": "https://github.com/TheHive-Project/Cortex-Analyzers", | ||
"license": "AGPL-V3", | ||
"description": "Get information about CVE from powerful Vulners database.", | ||
"dataTypeList": ["cve"], | ||
"command": "Vulners/vulners_analyzer.py", | ||
"baseConfig": "Vulners", | ||
"config": { | ||
"service": "vulnerability" | ||
}, | ||
"configurationItems": [ | ||
{ | ||
"name": "key", | ||
"description": "API key for Vulners", | ||
"type": "string", | ||
"multi": false, | ||
"required": true | ||
} | ||
], | ||
"registration_required": true, | ||
"subscription_required": true, | ||
"free_subscription": true, | ||
"service_homepage": "https://vulners.com", | ||
"service_logo": {"path":"assets/vulners_logo.png", "caption": "logo"}, | ||
"screenshots": [ | ||
{ | ||
"path": "assets/theHive_add_cve", | ||
"caption": "Add new IOC type in theHive observables" | ||
}, | ||
{ | ||
"path": "assets/cve_long_template.gif", | ||
"caption": "Long template for CVE" | ||
}, | ||
{ | ||
"path": "assets/cve_short_template", | ||
"caption": "Short template for CVE" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
{ | ||
"name": "Vulners_IOC", | ||
"version": "1.0", | ||
"author": "Dmitry Uchakin, Vulners team", | ||
"url": "https://github.com/TheHive-Project/Cortex-Analyzers", | ||
"license": "AGPL-V3", | ||
"description": "Get information from the RST Threat Feed, which integrated with Vulners, for a domain, url or an IP address.", | ||
"dataTypeList": ["url", "domain", "ip"], | ||
"command": "Vulners/vulners_analyzer.py", | ||
"baseConfig": "Vulners", | ||
"config": { | ||
"service": "ioc" | ||
}, | ||
"configurationItems": [ | ||
{ | ||
"name": "key", | ||
"description": "API key for Vulners", | ||
"type": "string", | ||
"multi": false, | ||
"required": true | ||
} | ||
], | ||
"registration_required": true, | ||
"subscription_required": true, | ||
"free_subscription": true, | ||
"service_homepage": "https://vulners.com", | ||
"service_logo": {"path":"assets/vulners_logo.png", "caption": "logo"}, | ||
"screenshots": [ | ||
{ | ||
"path": "assets/vulners_api.png", | ||
"caption": "Vulners API key for analyzer" | ||
}, | ||
{ | ||
"path": "assets/Cortex_settings.png", | ||
"caption": "Paste Vulners API key in Cortex settings" | ||
}, | ||
{ | ||
"path": "assets/ioc_long_template.png", | ||
"caption": "Long template for network IOCs (ip, url, domain)" | ||
}, | ||
{ | ||
"path": "assets/ioc_short_template.png", | ||
"caption": "Short template for network IOCs (ip, url, domain)" | ||
}, | ||
{ | ||
"path": "assets/assets/ioc_with_malware_family.png", | ||
"caption": "Full template with malware family" | ||
} | ||
] | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
cortexutils | ||
vulners |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
#!/usr/bin/env python3 | ||
from cortexutils.analyzer import Analyzer | ||
import vulners | ||
|
||
|
||
class VulnersAnalyzer(Analyzer): | ||
|
||
def __init__(self): | ||
Analyzer.__init__(self) | ||
self.service = self.get_param('config.service', None, 'Service parameter is missing') | ||
self.api_key = self.get_param('config.key', None, 'Missing vulners api key') | ||
proxies = { | ||
"https": self.get_param("config.proxy_https"), | ||
"http": self.get_param("config.proxy_http"), | ||
} | ||
self.vulners = vulners.Vulners(api_key=self.api_key, proxies=proxies) | ||
|
||
def summary(self, raw): | ||
taxonomies = [] | ||
namespace = "Vulners" | ||
if self.service == 'ioc': | ||
predicate = "IOC" | ||
if raw['results']: | ||
tags = ', '.join( | ||
set([', '.join(result['tags']) for result in raw['results']]) | ||
) | ||
level = 'malicious' | ||
value = f"Finded IOCs: {len(raw['results'])} / tags: {tags}" | ||
else: | ||
level = 'info' | ||
value = 'No results' | ||
|
||
if self.service == 'vulnerability': | ||
predicate = "CVE" | ||
if not raw['exploits']: | ||
level = 'suspicious' | ||
value = f"CVSS score: {raw['cvss']['score']} / Vulners score: {raw['vulners_AI']} / No exploits" | ||
else: | ||
level = 'malicious' | ||
value = f"CVSS score: {raw['cvss']['score']} / Vulners score: {raw['vulners_AI']} / Exploits {len(raw['exploits'])}" | ||
|
||
taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) | ||
return {"taxonomies": taxonomies} | ||
|
||
def run(self): | ||
if self.service == 'ioc': | ||
if self.data_type in ['ip', 'domain', 'url']: | ||
data = self.get_param('data', None, 'Data is missing') | ||
all_short_results = self.vulners.search( | ||
f'type:rst AND iocType:{self.data_type} AND {self.data_type}:"{data}"') | ||
|
||
results = [] | ||
|
||
if all_short_results: | ||
if all_short_results[0]['type'] == 'rst' or 'type' in all_short_results[0]: | ||
|
||
full_documents_info = self.vulners.documentList( | ||
[doc_id['id'] for doc_id in all_short_results], fields=["*"]) | ||
|
||
for document_results in full_documents_info: | ||
info_from_document = full_documents_info[f'{document_results}'] | ||
|
||
ioc_report = { | ||
'service': self.service, | ||
'first_seen': info_from_document['published'], | ||
'last_seen': info_from_document['lastseen'], | ||
'tags': info_from_document['tags'], | ||
'ioc_score': info_from_document['iocScore']['ioc_total'], | ||
'ioc_url': info_from_document['id'], | ||
'fp_descr': info_from_document['fp']['descr'] | ||
} | ||
if self.data_type == 'ip': | ||
ioc_report['ioc_result'] = info_from_document['ip'] | ||
ioc_report['geo_info'] = info_from_document['geodata'] | ||
ioc_report['asn_info'] = info_from_document['asn'] | ||
elif self.data_type == 'url': | ||
ioc_report['ioc_result'] = info_from_document['url'] | ||
elif self.data_type == 'domain': | ||
ioc_report['ioc_result'] = info_from_document['domain'] | ||
|
||
if 'threat' in info_from_document: | ||
ioc_report['threat_family'] = info_from_document['threat'] | ||
|
||
results.append(ioc_report) | ||
|
||
self.report({'results': results}) | ||
else: | ||
self.report({'results': 'No data found'}) | ||
else: | ||
self.error('Invalid data type') | ||
|
||
if self.service == 'vulnerability': | ||
if self.data_type == 'cve': | ||
data = self.get_param('data', None, 'Data is missing') | ||
cve_info = self.vulners.document(data, fields=["*"]) | ||
cve_exploits = self.vulners.searchExploit(data) | ||
full_cve_info = {} | ||
|
||
if cve_info: | ||
full_cve_info = { | ||
'service': self.service, | ||
'title': cve_info['title'], | ||
'published': cve_info['published'], | ||
'modified': cve_info['modified'], | ||
'cvss3': cve_info['cvss3'], | ||
'cvss2': cve_info['cvss2'], | ||
'cvss': cve_info['cvss'], | ||
'vulners_AI': cve_info['enchantments']['vulnersScore'], | ||
'cwe': cve_info['cwe'], | ||
'description': cve_info['description'], | ||
'affectedSoftware': cve_info['affectedSoftware'] | ||
} | ||
else: | ||
self.report({'result': 'No data for specified CVE was found'}) | ||
|
||
if cve_exploits: | ||
full_exploit_info = [] | ||
for exploit in cve_exploits: | ||
full_exploit_info.append({ | ||
'title': exploit['title'], | ||
'published': exploit['published'], | ||
'url': exploit['vhref'] | ||
}) | ||
|
||
full_cve_info['exploits'] = full_exploit_info | ||
else: | ||
full_cve_info['exploits'] = False | ||
|
||
self.report(full_cve_info) | ||
else: | ||
self.error('Invalid data type') | ||
|
||
|
||
if __name__ == '__main__': | ||
VulnersAnalyzer().run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<!-- Success --> | ||
<div class="panel panel-info" ng-if="success"> | ||
<div class="panel-heading"> | ||
Vulners information for <strong>{{artifact.data | fang}}</strong> | ||
</div> | ||
<div class="panel-body"> | ||
<h3 align="center"><b>{{artifact.data}}</b></h3> | ||
<dl class="dl-horizontal"> | ||
<dt>Published: </dt><dd>{{content.published | limitTo : 10}}</dd> | ||
<dt>Modified: </dt><dd>{{content.published | limitTo : 10}}</dd> | ||
</dl> | ||
<dl class="dl-horizontal" ng-if="content.cvss2"> | ||
<dt>CVSSv2.0: </dt><dd>{{content.cvss2.cvssV2.baseScore}}</dd> | ||
</dl> | ||
<dl class="dl-horizontal" ng-if="content.cvss3"> | ||
<dt>CVSSv3.1: </dt><dd>{{content.cvss3.cvssV3.baseScore}}</dd> | ||
</dl> | ||
<dl class="dl-horizontal" ng-if="content.vulners_AI"> | ||
<dt>Vulners Score: </dt> <dd>{{content.vulners_AI}}</dd> | ||
</dl> | ||
<dl class="dl-horizontal" ng-if="content.cwe"> | ||
<dt>CWE: </dt> | ||
<dd> | ||
<span class="label" | ||
ng-style="{'border':'1px solid','color': '#000000', 'background-color': md.color}"> | ||
{{content.cwe[0]}} | ||
</span> | ||
</dd> | ||
</dl> | ||
<dl class="dl-horizontal" ng-if="content.exploits"> | ||
<dt>Exploits: </dt> <dd style="color:#ff0000">Yes</dd> | ||
</dl> | ||
<hr> | ||
<h3>Description</h3> | ||
<p>{{content.description}}</p> | ||
<hr> | ||
<h3>Affected products</h3> | ||
<table class="table table-stripped"> | ||
<tr> | ||
<th>Product name</th> | ||
<th>Product version</th> | ||
</tr> | ||
<tr ng-repeat="soft in content.affectedSoftware"> | ||
<td>{{soft.name}}</td> | ||
<td>{{soft.version}}</td> | ||
</tr> | ||
</table> | ||
<p><br>Source info: | ||
<a href="https://vulners.com/cve/{{artifact.data}}" target="_blank">https://vulners.com/cve/{{artifact.data}}</a> | ||
</p> | ||
</div><br /> | ||
|
||
<div class="panel panel-info" ng-if="content.exploits"> | ||
<div class="panel-heading"> | ||
<strong>Exploits</strong> | ||
</div> | ||
|
||
<div class="panel-body"> | ||
<dl class="dl-horizontal" ng-repeat="exploit in content.exploits"> | ||
<dt>Title: </dt> <dd>{{exploit.title}}</dd> | ||
<dt>Published: </dt> <dd>{{exploit.published | limitTo : 10}}</dd> | ||
<dt>Exploit url: </dt> <dd><a href="{{exploit.url}}" target="_blank">{{exploit.url}}</a></dd> | ||
<hr> | ||
</dl> | ||
</div> | ||
</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"> | ||
<dl class="dl-horizontal" ng-if="content.errorMessage"> | ||
<dt><i class="fa fa-warning"></i> ANALYZERNAME: </dt> | ||
<dd class="wrap">{{content.errorMessage}}</dd> | ||
</dl> | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<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> |
Oops, something went wrong.