-
Notifications
You must be signed in to change notification settings - Fork 383
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 #1241 from Mv35/feature/c25-cortex-analyzer
feat(c25): adds cluster25's cortex analyzer
- Loading branch information
Showing
9 changed files
with
662 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,53 @@ | ||
{ | ||
"name": "C25CortexAnalyzer_Investigate", | ||
"version": "1.0", | ||
"author": "Cluster25", | ||
"url": "https://github.com/TheHive-Project/Cortex-Analyzers", | ||
"license": "AGPL-V3", | ||
"description": "Use Cluster25's CTI API to investigate an observable.", | ||
"dataTypeList": ["domain", "file", "hash", "ip", "mail", "url"], | ||
"command": "c25-cortex-analyzer/c25_cortex_analyzer.py", | ||
"baseConfig": "c25-cortex-analyzer", | ||
"config": { | ||
"check_tlp": false, | ||
"check_pap": false, | ||
"auto_extract_artifacts": true, | ||
"service": "investigate" | ||
}, | ||
"configurationItems": [ | ||
{ | ||
"name": "client_id", | ||
"description": "Cluster25 CTI API credentials", | ||
"type": "string", | ||
"multi": false, | ||
"required": true | ||
}, | ||
{ | ||
"name": "client_key", | ||
"description": "Cluster25 CTI API credentials", | ||
"type": "string", | ||
"multi": false, | ||
"required": true | ||
}, | ||
{ | ||
"name": "base_url", | ||
"description": "Cluster25 CTI API base url", | ||
"type": "string", | ||
"multi": false, | ||
"required": true | ||
} | ||
], | ||
"registration_required": true, | ||
"subscription_required": true, | ||
"free_subscription": false, | ||
"service_homepage": "https://www.duskrise.com/the-c25-intelligence/", | ||
"service_logo": {"path":"assets/cluster25_logo.png", "caption": "logo"}, | ||
"screenshots": [ | ||
{"path":"assets/short_report_sample.png", | ||
"caption":"report sample" | ||
}, | ||
{ | ||
"path": "assets/long_report_sample.png", | ||
"caption:":"report sample" | ||
}] | ||
} |
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,7 @@ | ||
FROM python:3.11 | ||
|
||
WORKDIR /worker | ||
COPY . c25_analyzer | ||
|
||
RUN pip install --no-cache-dir -r c25_analyzer/requirements.txt | ||
ENTRYPOINT c25_analyzer/c25_cortex_analyzer.py |
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,101 @@ | ||
# Cluster25 Cortex Analyzer | ||
|
||
Allows to query Cluster25's CTI API investigation service. | ||
Running the analyzer will return a short report with taxonomies, | ||
as well as a long report and extracted artefacts. | ||
|
||
## Requirements: | ||
* C25 API KEY | ||
* C25 CLIENT ID | ||
* C25 BASE URL | ||
|
||
Raw investigate result query example: | ||
```json | ||
{ | ||
"indicator": "211.56.98.146", | ||
"indicator_type": "ipv4", | ||
"whitelisted": false, | ||
"tags": [], | ||
"score": 70, | ||
"is_known": false, | ||
"actors": [], | ||
"related_indicators": { | ||
"by_file": [], | ||
"by_content": [] | ||
}, | ||
"related_contexts": [], | ||
"created_dt": null, | ||
"modified_dt": null, | ||
"attacker_activities": [], | ||
"targeted_sectors": [], | ||
"targeted_countries": [], | ||
"file_info": null, | ||
"cve_info": null, | ||
"asn_info": null, | ||
"btcaddress_info": null, | ||
"family_info": null, | ||
"stats": { | ||
"harmless": 61, | ||
"malicious": 5, | ||
"suspicious": 0, | ||
"undetected": 23 | ||
}, | ||
"communicating_files": [], | ||
"contacted_ips": [], | ||
"contacted_domains": [], | ||
"contacted_urls": [], | ||
"dropped_files": [], | ||
"passive_dns": { | ||
"resolutions": [ | ||
{ | ||
"record_name": "c3kr.simonxu.cc", | ||
"record_value": "211.56.98.146", | ||
"record_type": "A", | ||
"first_seen": "2021-03-26T14:16:15", | ||
"last_seen": "2021-03-26T14:16:55", | ||
"country_name": "South Korea", | ||
"$$hashKey": "object:64" | ||
}, | ||
{ | ||
"record_name": "counter.yadro.ru", | ||
"record_value": "211.56.98.146", | ||
"record_type": "A", | ||
"first_seen": "2018-10-19T22:00:00", | ||
"last_seen": "2018-10-19T22:00:00", | ||
"country_name": "South Korea", | ||
"$$hashKey": "object:65" | ||
} | ||
] | ||
}, | ||
"whois": { | ||
"ip": null, | ||
"created_date": null, | ||
"updated_date": "[email protected]", | ||
"expires_date": null, | ||
"registrant": { | ||
"name": "IP Manager", | ||
"organization": "Korea Telecom", | ||
"street1": "Gyeonggi-do Bundang-gu, Seongnam-si Buljeong-ro 90", | ||
"street2": null, | ||
"city": null, | ||
"state": null, | ||
"country": null, | ||
"country_code": null, | ||
"postal_code": "13606", | ||
"raw_text": null, | ||
"unparsable": null | ||
}, | ||
"registrar_name": null, | ||
"name_servers_hostnames": null, | ||
"name_servers_ips": null, | ||
"email_provider": null, | ||
"email_registrant": null, | ||
"status": null | ||
}, | ||
"guessed_types": [], | ||
"intelligence": null, | ||
"first_seen": null, | ||
"last_seen": null, | ||
"dns_resolutions": null | ||
} | ||
``` |
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,97 @@ | ||
#!/usr/bin/env python3 | ||
# encoding: utf-8 | ||
from typing import Optional, List | ||
|
||
import requests | ||
from cortexutils.analyzer import Analyzer | ||
|
||
|
||
class Cluster25Client: | ||
def __init__( | ||
self, | ||
customer_id: Optional[str] = None, | ||
customer_key: Optional[str] = None, | ||
base_url: Optional[str] = None | ||
): | ||
self.client_id = customer_id | ||
self.client_secret = customer_key | ||
self.base_url = base_url | ||
self.current_token = self._get_cluster25_token() | ||
self.headers = {"Authorization": f"Bearer {self.current_token}"} | ||
|
||
def _get_cluster25_token( | ||
self | ||
) -> List[dict]: | ||
payload = {"client_id": self.client_id, "client_secret": self.client_secret} | ||
r = requests.post(url=f"{self.base_url}/token", json=payload, headers={"Content-Type": "application/json"}) | ||
if r.status_code != 200: | ||
raise Exception(f"Unable to retrieve the token from C25 platform, status {r.status_code}") | ||
return r.json()["data"]["token"] | ||
|
||
def investigate( | ||
self, | ||
indicator | ||
) -> dict: | ||
params = {'indicator': indicator.get('value')} | ||
r = requests.get(url=f"{self.base_url}/investigate", params=params, headers=self.headers) | ||
if r.status_code != 200: | ||
return {'error': f"Unable to retrieve investigate result for indicator '{indicator.get('value')}' " | ||
f"from C25 platform, status {r.status_code}"} | ||
return r.json()["data"] | ||
|
||
|
||
class C25CortexAnalyzer(Analyzer): | ||
def __init__( | ||
self | ||
): | ||
Analyzer.__init__(self) | ||
self.c25_api_key = self.get_param("config.client_key", None, "Missing Cluster25 api key") | ||
self.c25_client_id = self.get_param("config.client_id", None, "Missing Cluster25 client id") | ||
self.c25_base_url = self.get_param("config.base_url", None, "Missing Cluster25 base url") | ||
self.c25_api_client = Cluster25Client(self.c25_client_id, self.c25_api_key, self.c25_base_url) | ||
|
||
def investigate( | ||
self, | ||
indicator: str | ||
) -> dict: | ||
return self.c25_api_client.investigate({'value': indicator}) | ||
|
||
def summary( | ||
self, | ||
indicator_data: dict | ||
) -> dict: | ||
taxonomies = [] | ||
namespace = "C25" | ||
level = 'info' | ||
if indicator_data.get('indicator'): | ||
taxonomies.append(self.build_taxonomy(level, namespace, "Indicator", indicator_data.get('indicator'))) | ||
if indicator_data.get('indicator_type'): | ||
taxonomies.append( | ||
self.build_taxonomy(level, namespace, "Indicator Type", indicator_data.get('indicator_type'))) | ||
if indicator_data.get('score'): | ||
if indicator_data.get('score') < 50: | ||
level = 'safe' | ||
elif 50 <= indicator_data.get('score') < 80: | ||
level = 'suspicious' | ||
else: | ||
level = 'malicious' | ||
taxonomies.append(self.build_taxonomy(level, namespace, "Score", indicator_data.get('score'))) | ||
if len(taxonomies) == 0: | ||
taxonomies.append(self.build_taxonomy(level, namespace, 'Threat', 'Not found')) | ||
|
||
return {"taxonomies": taxonomies} | ||
|
||
def run( | ||
self | ||
): | ||
try: | ||
indicator = self.get_param('data', None, 'Data is missing') | ||
indicator_data = self.investigate(indicator) | ||
if indicator_data: | ||
self.report(indicator_data) | ||
except Exception as e: | ||
self.error(e) | ||
|
||
|
||
if __name__ == '__main__': | ||
C25CortexAnalyzer().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,2 @@ | ||
requests~=2.31.0 | ||
cortexutils~=2.2.0 |
Oops, something went wrong.