-
Notifications
You must be signed in to change notification settings - Fork 385
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
[OSCD Initiative] Vulners analyzer #880
Merged
+459
−0
Merged
Changes from 4 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
937028c
Create vulners analyzer
uchakin 934cd9b
Update vulners_analyzer.py
uchakin 9212fd5
Add assets for analyzer
uchakin ee10012
Update analyzer and fix issues
uchakin 688a88e
Update README.md
uchakin 062be46
Update README.md
uchakin 0295588
Add malware family for IOC analyzer
uchakin b58c598
Update vulners_analyzer.py
uchakin 07dc796
Add proxies for analyzer
uchakin 0b5c6c4
change reporting when not found
dadokkio c05b68c
README and config update
uchakin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,46 @@ | ||
# 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,37 @@ | ||
{ | ||
"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 | ||
} | ||
], | ||
"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,41 @@ | ||
{ | ||
"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 | ||
} | ||
], | ||
"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)" | ||
} | ||
] | ||
} |
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,129 @@ | ||
#!/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') | ||
self.vulners = vulners.Vulners(api_key=self.api_key) | ||
|
||
def summary(self, raw): | ||
taxonomies = [] | ||
namespace = "Vulners" | ||
if self.service == 'ioc': | ||
predicate = "IOC" | ||
tags = ', '.join( | ||
set([', '.join(result['tags']) for result in raw['results']]) | ||
) | ||
if tags: | ||
level = 'malicious' | ||
value = f"Finded IOCs: {len(raw['results'])} / tags: {tags}" | ||
elif not tags: | ||
level = 'suspicious' | ||
value = f"Finded IOCs: {len(raw['results'])}" | ||
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: | ||
ioc_report = { | ||
'service': self.service, | ||
'first_seen': full_documents_info[f'{document_results}']['published'], | ||
'last_seen': full_documents_info[f'{document_results}']['lastseen'], | ||
'tags': full_documents_info[f'{document_results}']['tags'], | ||
'ioc_score': full_documents_info[f'{document_results}']['iocScore']['ioc_total'], | ||
'ioc_url': full_documents_info[f'{document_results}']['id'], | ||
'fp_descr': full_documents_info[f'{document_results}']['fp']['descr'] | ||
} | ||
if self.data_type == 'ip': | ||
ioc_report['ioc_result'] = full_documents_info[f'{document_results}']['ip'] | ||
ioc_report['geo_info'] = full_documents_info[f'{document_results}']['geodata'] | ||
ioc_report['asn_info'] = full_documents_info[f'{document_results}']['asn'] | ||
elif self.data_type == 'url': | ||
ioc_report['ioc_result'] = full_documents_info[f'{document_results}']['url'] | ||
elif self.data_type == 'domain': | ||
ioc_report['ioc_result'] = full_documents_info[f'{document_results}']['domain'] | ||
|
||
results.append(ioc_report) | ||
|
||
self.report({'results': results}) | ||
else: | ||
self.error({'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.error('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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is something strange here. The code will not reach the else clause in any case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dadokkio done
You're right. I fixed and simplified this part.