Skip to content
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
merged 11 commits into from
Jan 21, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions analyzers/Vulners/README.md
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: ![Vulners API](assets/vulners_api.png)

Add your Vulners API in Cortex settings: ![API key in Cortex](assets/Cortex_settings.png)

## 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:

![add observable](assets/theHive_add_cve.PNG)​

## Run the Analyzer in TheHive

####Network IOCs:

Short template:

![Short IOC template](assets/ioc_short_template.png)

Long template:

![Long IOC template](assets/ioc_long_template.png)

####Vulnerabilities:

Short template:

![Short CVE template](assets/cve_short_template.png)

Long template:

![Long CVE template](assets/cve_long_template.gif)
37 changes: 37 additions & 0 deletions analyzers/Vulners/Vulners_CVE.json
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"
}
]
}
41 changes: 41 additions & 0 deletions analyzers/Vulners/Vulners_IOC.json
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)"
}
]
}
Binary file added analyzers/Vulners/assets/Cortex_settings.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added analyzers/Vulners/assets/cve_long_template.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added analyzers/Vulners/assets/cve_short_template.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added analyzers/Vulners/assets/ioc_long_template.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added analyzers/Vulners/assets/ioc_short_template.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added analyzers/Vulners/assets/theHive_add_cve.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added analyzers/Vulners/assets/vulners_api.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions analyzers/Vulners/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cortexutils
vulners
129 changes: 129 additions & 0 deletions analyzers/Vulners/vulners_analyzer.py
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:
Copy link
Contributor

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.

Copy link
Contributor Author

@uchakin uchakin Oct 27, 2020

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.

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()
80 changes: 80 additions & 0 deletions thehive-templates/Vulners_CVE_1_0/long.html
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>
6 changes: 6 additions & 0 deletions thehive-templates/Vulners_CVE_1_0/short.html
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>
Loading