Skip to content

Commit

Permalink
Merge pull request #1297 from TheHive-Project/csfalcon-integration-1
Browse files Browse the repository at this point in the history
Multiple Analyzers & Responders for CrowdstrikeFalcon
  • Loading branch information
nusantara-self authored Nov 26, 2024
2 parents 6d6eb50 + fefd077 commit a0f139f
Show file tree
Hide file tree
Showing 62 changed files with 4,064 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"name": "CrowdstrikeFalcon_GetDeviceVulnerabilities",
"version": "1.0",
"author": "nusantara-self, StrangeBee",
"url": "https://github.com/TheHive-Project/Cortex-Analyzers",
"license": "AGPL-V3",
"baseConfig": "CrowdstrikeFalcon",
"config": {
"check_tlp": false,
"max_tlp": 3,
"service": ""
},
"description": "Get device vulnerabilities from hostname",
"dataTypeList": [
"hostname"
],
"command": "CrowdstrikeFalcon/CrowdstrikeFalcon_getDeviceVulnerabilities.py",
"configurationItems": [
{
"name": "client_id",
"description": "Crowdstrike client ID key",
"type": "string",
"multi": false,
"required": true,
"defaultValue": ""
},
{
"name": "client_secret",
"description": "Crowdstrike client secret key",
"type": "string",
"multi": false,
"required": true,
"defaultValue": ""
},
{
"name": "vuln_fields",
"description": "Specific field values to keep in resulting payload for vulnerabilities",
"type": "string",
"multi": true,
"required": true,
"defaultValue": [
"vulnerability_id",
"status",
"created_timestamp",
"updated_timestamp",
"apps.product_name_version",
"confidence",
"cve",
"host_info.asset_criticality",
"host_info.internet_exposure",
"remediation.entities.action"
]
}
],
"registration_required": true,
"subscription_required": true,
"free_subscription": false,
"service_homepage": "https://www.crowdstrike.com",
"service_logo": {
"path": "assets/crowdstrike.png",
"caption": "Crowdstrike logo"
},
"screenshots": [
{
"path": "assets/short-report-vulns.png",
"caption": "Crowdstrike: Short report template"
},
{
"path": "assets/long-report-vulns.png",
"caption": "Crowdstrike: Long report template"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env python3
# encoding: utf-8
from cortexutils.analyzer import Analyzer
from falconpy import OAuth2
from falconpy import Hosts
from falconpy import SpotlightVulnerabilities


class CrowdstrikeFalcon_GetDeviceVulnerabilities(Analyzer):
def __init__(self):
Analyzer.__init__(self)
self.client_id = self.get_param("config.client_id")
self.client_secret = self.get_param("config.client_secret")
self.vuln_fields = self.get_param("config.vuln_fields", [])



def run(self):
Analyzer.run(self)
if self.data_type == 'hostname':
try:
auth = OAuth2(client_id=self.client_id, client_secret=self.client_secret)
hosts = Hosts(auth_object=auth)
hostname = self.get_data()

# Search for the device ID using the hostname
response = hosts.query_devices_by_filter(filter=f"hostname:'{hostname}'")
device_ids = response["body"]["resources"]

# Check the response
status_code = response["status_code"]
if status_code != 200 :
self.error(f"No devices found with hostname: {hostname} -- {status_code}")

if device_ids:
device_id = device_ids[0]
# Get detailed asset information using the device ID
spotlight = SpotlightVulnerabilities(auth_object=auth)
host_vulns = spotlight.query_vulnerabilities_combined(parameters={"filter": f"aid:'{device_id}'+status:!'closed'"})
host_vulns = host_vulns["body"]["resources"]
#print(host_vulns)
vuln_details = []
products_with_vulns = {}
for vuln in host_vulns:
product_name = vuln["apps"][0]["product_name_normalized"]
vuln_id = vuln["id"]

if product_name not in products_with_vulns:
products_with_vulns[product_name] = []

products_with_vulns[product_name].append(vuln_id)
for key, vuln_ids in products_with_vulns.items():
for vuln_id in vuln_ids:
request = spotlight.get_vulnerabilities(vuln_id)
data = request["body"]["resources"][0]
# Filter the dictionary
#filtered_data = {key: data[key] for key in top_10_keys if key in data}
filtered_data = self.filter_dict(data, self.vuln_fields)
vuln_details.append(filtered_data)
self.report({"message": vuln_details})
except Exception as e:
self.unexpectedError(e)
else:
self.notSupported()

def filter_dict(self, d, keys):
filtered = {}
for key in keys:
parts = key.split(".")
if len(parts) == 3:
main_key, sub_key, sub_sub_key = parts
if main_key in d and sub_key in d[main_key]:
filtered.setdefault(main_key, {}).setdefault(sub_key, [])
for entity in d[main_key][sub_key]:
filtered[main_key][sub_key].append({sub_sub_key: entity[sub_sub_key]})
elif len(parts) == 2:
main_key, sub_key = parts
if main_key in d and sub_key in d[main_key]:
filtered.setdefault(main_key, {})[sub_key] = d[main_key][sub_key]
elif len(parts) == 1:
main_key = parts[0]
if main_key in d:
filtered[main_key] = d[main_key]
return filtered

def summary(self, raw):
taxonomies = []
level = "safe"
namespace = "CSFalcon"
predicate = "VulnDetails"

count_vulns = len(raw["message"])
if count_vulns > 0:
level = "suspicious"
for vuln in raw["message"]:
if vuln["cve"]["base_score"] >= 7:
level = "malicious"

# Build summary
taxonomies.append(
self.build_taxonomy(
level, namespace, predicate, str(count_vulns)
)
)
return {"taxonomies": taxonomies}

def artifacts(self, raw):
artifacts = []
#artifacts.append(self.build_artifact("ip",raw["external_ip"],tags=["hostname=" + raw["hostname"], "external_ip"]))
return artifacts


if __name__ == "__main__":
CrowdstrikeFalcon_GetDeviceVulnerabilities().run()
121 changes: 121 additions & 0 deletions analyzers/CrowdstrikeFalcon/CrowdstrikeFalcon_Sandbox.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python3
# encoding: utf-8
from os.path import basename
from cortexutils.analyzer import Analyzer
from falconpy import FalconXSandbox, SampleUploads, OAuth2
import time



class CrowdstrikeFalcon_Sandbox(Analyzer):
def __init__(self):
Analyzer.__init__(self)
# filename of the observable
self.filename = self.getParam("attachment.name", "noname.ext")
self.filepath = self.getParam("file", None, "File is missing")
self.client_id = self.get_param("config.client_id")
self.client_secret = self.get_param("config.client_secret")
self.environment = self.get_param("config.service", 160)
self.network_settings = self.get_param("config.network_settings", "default")
self.action_script = self.get_param("config.action_script", "default")

def run(self):
Analyzer.run(self)

# file analysis
if self.data_type == 'file':
filepath = self.get_param('file', None, 'File is missing')
filename = self.get_param('filename', basename(filepath))
comment = f"Submitted from TheHive"
# additional_params = {
# "action_script": "default",
# "command_line": "",
# "document_password": "",
# "environment_id": 160,
# "network_settings": "default",
# "send_email_notifications": False,
# "submit_name": filename,
# "submit_date": "2024-08-01",
# "submit_time": "12:00:00",
# "user_tags": ["test", "sample"]
# }

additional_params = {
"environment_id": self.environment,
"submit_name": filename,
"network_settings": self.network_settings,
"action_script": self.action_script
}

with open(filepath, "rb") as sample:
auth = OAuth2(client_id=self.client_id, client_secret=self.client_secret)
samples = SampleUploads(auth_object=auth)
sandbox = FalconXSandbox(auth_object=auth)
response = samples.upload_sample(file_data=sample.read(),
file_name=filename,
comment=comment,
is_confidential=True
)
#response = falconx.query_sample()

#response = falconx.submit(file_name=filename, file_data=sample, **additional_params)

# Check the response
if response["status_code"] in [200, 201] :
#message = f"File uploaded successfully! Submission ID : {response['body']["resources"]}"
sha256 = response['body']["resources"][0]["sha256"]
submit_response = sandbox.submit(body={
"sandbox": [{
"sha256": sha256,
**additional_params
}]
})

message = f"File submitted successfully for ! Submission ID : {submit_response}"

## Check status of on-going scan
status = "running"
while status == "running":
submit_id = submit_response["body"]["resources"][0]["id"]
scan_status = sandbox.get_submissions(ids=submit_id)
if scan_status["body"]["resources"]:
status = scan_status["body"]["resources"][0]["state"]

analysis_result = sandbox.get_reports(ids=submit_id)
message = analysis_result['body']
else:
self.error(f"Error uploading file: {response} and {filepath} and {sample} and {filename}")
self.report(message)
else:
self.error("Datatype is not file")

def summary(self, raw):
taxonomies = []

level = "info"
namespace = "CSFalcon"
predicate = "Sandbox"

value = raw["resources"][0]["verdict"]

if value == "suspicious":
level = "suspicious"
elif value == "malicious":
level = "malicious"
elif value == "no specific threat":
level = "safe"

# Build summary
taxonomies.append(
self.build_taxonomy(
level, namespace, predicate, value
)
)
return {"taxonomies": taxonomies}

def artifacts(self, raw):
artifacts = []
return artifacts

if __name__ == "__main__":
CrowdstrikeFalcon_Sandbox().run()
70 changes: 70 additions & 0 deletions analyzers/CrowdstrikeFalcon/CrowdstrikeFalcon_Sandbox_Android.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"name": "CrowdstrikeFalcon_Sandbox_Android",
"version": "1.0",
"author": "nusantara-self, StrangeBee",
"url": "https://github.com/TheHive-Project/Cortex-Analyzers",
"license": "AGPL-V3",
"baseConfig": "CrowdstrikeFalcon",
"config": {
"check_tlp": false,
"max_tlp": 3,
"service": 200
},
"description": "Send a file to CrowdstrikeFalcon Sandbox",
"dataTypeList": [
"file"
],
"command": "CrowdstrikeFalcon/CrowdstrikeFalcon_Sandbox.py",
"configurationItems": [
{
"name": "client_id",
"description": "Crowdstrike client ID key",
"type": "string",
"multi": false,
"required": true,
"defaultValue": ""
},
{
"name": "client_secret",
"description": "Crowdstrike client secret key",
"type": "string",
"multi": false,
"required": true,
"defaultValue": ""
},
{
"name": "network_settings",
"description": "Specifies the sandbox network_settings used for analysis : default, tor, simulated, offline",
"type": "string",
"multi": false,
"required": true,
"defaultValue": "default"
},
{
"name": "action_script",
"description": "Runtime script for sandbox analysis : default, default_randomtheme, default_maxantievasion, default_openie, default_randomfiles",
"type": "string",
"multi": false,
"required": true,
"defaultValue": "default"
}
],
"registration_required": true,
"subscription_required": true,
"free_subscription": false,
"service_homepage": "https://www.crowdstrike.com",
"service_logo": {
"path": "assets/crowdstrike.png",
"caption": "Crowdstrike logo"
},
"screenshots": [
{
"path": "assets/short-report-sandbox.png",
"caption": "Crowdstrike: Short report template"
},
{
"path": "assets/long-report-sandbox.png",
"caption": "Crowdstrike: Long report template"
}
]
}
Loading

0 comments on commit a0f139f

Please sign in to comment.