Skip to content

Commit

Permalink
misp
Browse files Browse the repository at this point in the history
  • Loading branch information
doomedraven committed Feb 8, 2023
1 parent b317da1 commit 2ec6377
Show file tree
Hide file tree
Showing 2 changed files with 305 additions and 0 deletions.
174 changes: 174 additions & 0 deletions lib/cuckoo/common/integrations/misp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Disclaimer this code is not maintained by core devs
# pymisp is known to break api on updates.
# So you need it? You fix it!

import os
import json
import logging

from lib.cuckoo.common.config import Config
from lib.cuckoo.common.constants import CUCKOO_ROOT

try:
from pymisp import PyMISP
from pymisp import logger as pymisp_logger

pymisp_logger.setLevel(logging.ERROR)
HAVE_MISP = True
except ImportError:
print("Missed pymisp dependency. Run: poetry run pip install pymisp==2.4.168")
HAVE_MISP = False

log = logging.getLogger()

external_cfg = Config("externalservices")
misp_url = ""
MISP_HASH_LOOKUP = False

if HAVE_MISP:
misp_url = external_cfg.misp.url
misp = PyMISP(misp_url, external_cfg.misp.apikey, False, "json")
MISP_HASH_LOOKUP = external_cfg.misp.hash_lookup


def misp_hash_lookup(sha256: str, task_id: str, file_info: dict):

if not MISP_HASH_LOOKUP:
return

# Initialize MISP Variables
threat_actor_tag = ""
threat_actor = "Not Applicable"
threat_actor_list = []
threat_actor_dict = {}
event_link = []
link_list = []
event_tag = ""
tag_dict = {}
tag = ""
related_events_dict = {}
galaxy_cluster_dict = {}

# Search MISP for any events with attributes having the same hash as the submitted sample
response = misp.search("attributes", value=sha256, return_format="json", pythonify=True)

# For exporting of MISP Attribute and MISP Event JSON File
attribute_json_response = misp.search("attributes", value=sha256, return_format="json", includeCorrelations=1)
event_json_response = misp.get_event(response[0].event_id, pythonify=False)
try:
analysis_path = os.path.join(CUCKOO_ROOT, "storage", "analyses", task_id)
attribute_json = json.dumps(attribute_json_response, indent=4)
with open(os.path.join(analysis_path, "misp_attribute.json"), "w") as outfile:
outfile.write(attribute_json)
event_json = json.dumps(event_json_response, indent=4)
with open(os.path.join(analysis_path, "misp_event.json"), "w") as outfile:
outfile.write(event_json)
except Exception as e:
log.error("Exporting of MISP JSON Files have been skipped: " + e)

# Retrieve desired information regarding the event if there is a relevant response
if response:
event = misp.get_event(response[0].event_id, pythonify=True)
event_link = f"{misp_url}/events/view/" + str(response[0].event_id)
galaxy_link = f"{misp_url}/galaxy_clusters/view/"
search_tag_link = f"{misp_url}/events/index/searchtag:"
ids_links = [
(f"{misp_url}/events/nids/snort/download/{response[0].event_id}"),
(f"{misp_url}/events/nids/suricata/download/{response[0].event_id}"),
]
event_info = str(event).split("info=")[1].rsplit(")", 1)[0]

log.debug("Submitted samples is related to MISP event: %s", str(event))
for attribute in event["Attribute"]:
if "type=link" in str(attribute):
link_list = [value for key, value in attribute.items() if key == "value"]

# Get descriptions for Galaxy Clusters that match associated Tags
for galaxy in event["Galaxy"]:
for key, value in galaxy.items():
galaxy_cluster_dict = {
cluster["value"].title(): [cluster["id"], cluster["description"]] for cluster in value if key == "GalaxyCluster"
}

for tag in event["Tag"]:
event_tag_dict = {}
event_tag = ""
# Iterate through every tag to get the tag key and value for display in web UI
for key, value in tag.items():
if any(pattern in str(tag) for pattern in ("threat-actor", "intrusion-set", "group")):
threat_actor_tag = str(tag)
threat_actor = threat_actor_tag.split('="')[1].split('")>')[0]
threat_actor_list.append(threat_actor)
# Filter out irrelevant tags
elif key == "id" and any(pattern not in str(tag) for pattern in ("workflow", "tlp", "type", "osint", "OSINT")):
# e.g. mitre-attack-pattern
event_tag_name = str(tag).split("name=")[1].split('")>')[0].split(":")[1].split('="')[0].title()
# e.g. Symmetric Cryptography - T1573.001
event_tag = str(tag).split("name=")[1].split('")>')[0].split(":")[1].split('="')[1].title()
if event_tag in galaxy_cluster_dict:
event_tag_dict[event_tag] = [value, galaxy_cluster_dict[event_tag][1]]
else:
event_tag_dict[event_tag] = [value, 0]
if event_tag_name not in tag_dict.keys():
tag_dict[event_tag_name] = event_tag_dict
else:
# e.g. 'Mitre-Enterprise-Attack-Intrusion-Set': {'Dragonok - G0017': ['1099', '...'], 'Winnti Group - G0044': ['1107', '...']}
tag_dict[event_tag_name].update(event_tag_dict)
# Get a list of MISP event/s related to the current MISP event (if any)
related_events = event["RelatedEvent"]
for related_event in related_events:
for key, value in related_event.items():
related_event_dict = {}
dict_id = misp_url + "/events/view/" + str(value["id"])
related_event_dict[dict_id] = value["info"]
related_events_dict.update(related_event_dict)

# initialize list of threat actors
all_threat_actors = []
all_intrusion_sets = []
all_enterprise_attack_intrusion_sets = []
all_microsoft_activity_groups = []

try:
# Search for threat actor description (id 59 --> misp threat actor galaxy)
all_threat_actors = misp.search_galaxy_clusters(59)
# Search for intrusion set description (id 35 --> misp intrusion set galaxy)
all_intrusion_sets = misp.search_galaxy_clusters(35)
# Search for enterprise attack intrusion set description (id 26 --> enterprise attack intrusion set galaxy)
all_enterprise_attack_intrusion_sets = misp.search_galaxy_clusters(26)
# Search for microsoft activity groups description (id 20 --> microsoft activity groups galaxy)
all_microsoft_activity_groups = misp.search_galaxy_clusters(20)
# CURRENTLY USELESS BECAUSE NO ASSOCIATION WITH CURRENT EVENTS
# # Search for 360.net threat actors description (id 1 --> 360.net threat actor galaxy)
# all_360net_threat_actors = misp.search_galaxy_clusters(1)
except Exception as e:
log.error("Could not access MISP Galaxy Information: %s", str(e))

all_galaxies = all_threat_actors + all_intrusion_sets + all_enterprise_attack_intrusion_sets + all_microsoft_activity_groups

# Loop through list of threat actor(s) to retrieve their description(s)
for threat_actor in threat_actor_list:
# this line will ensure that threat actors appear even if they do not have related description in MISP
threat_actor_dict[threat_actor] = [0, 0]
for galaxy_cluster in all_galaxies:
if galaxy_cluster["GalaxyCluster"]["value"] == threat_actor:
# e.g. "threat_actor" : { "Sofacy" : [ "The Sofacy Group is ..." , "9926" ] }
threat_actor_dict[threat_actor] = [
galaxy_cluster["GalaxyCluster"]["description"],
galaxy_cluster["GalaxyCluster"]["id"],
]


file_info.setdefault("misp", {})
file_info["misp"] = {
"threat_actor": threat_actor_dict,
"event_link": event_link,
"event_info": event_info,
"event_tags": tag_dict,
"galaxy_link": galaxy_link,
"search_tag_link": search_tag_link,
"ids_links": ids_links,
"links": link_list,
"related_events": related_events_dict,
"url": misp_url,
}
131 changes: 131 additions & 0 deletions web/templates/analysis/generic/_misp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
{% load key_tags %}

{% if file.misp.event_link %}
<div class="card-header">
<center><a class="accordion-toggle" data-toggle="collapse" aria-expanded="false" href="#misp_info"><i class="fas fa-lightbulb"></i> MISP Threat Intelligence</a></center>
</div>

<div class="collapse" id="misp_info">
<div class="card card-body">
{% if file.misp.event_info %}
<div class="column center">
<a class="btn btn-secondary btn-sm" href='{% url "mispjson" id "attribute" %}' role="button" data-bs-toggle="tooltip" title="Download MISP Attribute JSON File"><span class="fas fa-download"></span> Download MISP Attribute JSON File</a>
<a class="btn btn-secondary btn-sm" href='{% url "mispjson" id "event" %}' role="button" data-bs-toggle="tooltip" title="Download MISP Event JSON File"><span class="fas fa-download"></span> Download MISP Event JSON File</a>
{% if file.misp.ids_links %}
<a class="btn btn-secondary btn-sm" href='{{file.misp.ids_links.0}}' role="button" data-bs-toggle="tooltip" title="Download Snort IDS Signatures"><span class="fas fa-download"></span> Download Snort IDS Signatures</a>
<a class="btn btn-secondary btn-sm" href='{{file.misp.ids_links.1}}' role="button" data-bs-toggle="tooltip" title="Download Suricata IDS Signatures"><span class="fas fa-download"></span> Download Suricata IDS Signatures</a>
{% endif %}
</div>
<h1></h1>
<h4><a href="{{file.misp.event_link}}" target="_blank" ><b><span class="fas fa-calendar-check"></span> {{file.misp.event_info}}</b></a></h4>
{% endif %}

<table class="table table-striped table-bordered">
{% if file.misp.related_events %}
<tr>
<th><span class="fas fa-calendar-plus"></span> Related Events [{{file.misp.related_events|length}}]</th>
<td>
<ul>
{% for event_link, event_info in file.misp.related_events.items %}
<li><a href="{{event_link}}" target="_blank">{{event_info}}</a></li>
{% endfor %}
</ul>
</td>
</tr>
{% endif %}
{% if file.misp.threat_actor %}
<tr>
<th><span class="fas fa-user-secret"></span>Threat Actor(s) [{{file.misp.threat_actor|length}}]</th>
<td style="word-wrap: break-word;">
<ul>
{% for threat_actor_name, threat_actor_value in file.misp.threat_actor.items %}
<li><b><u>{{threat_actor_name}}</u></b>
{% if threat_actor_value.1 != 0 %}
{% if file.misp.galaxy_link %}
<a href="{{file.misp.galaxy_link}}{{threat_actor_value.1}}" target="_blank" style="color: #e74c3c">[View MISP Threat Actor Information Here]</a><br>{{threat_actor_value.0}}<br><br>
{% else %}
<a href="{{file.misp.url}}galaxy_clusters/view/{{threat_actor_value.1}}" target="_blank" style="color: #e74c3c">[View MISP Threat Actor Information Here]</a><br>{{threat_actor_value.0}}<br><br>
{% endif %}
{% else %}
<br><br>
{% endif %}
</li>
{% endfor %}
</ul>
</td>
</tr>
{% endif %}
{% if file.misp.event_tags %}
{% for tag_name, tag_value in file.misp.event_tags.items %}
<tr>
{% if tag_name == "Topic" %}
<th><span class="fas fa-info-circle"></span>&nbsp; Topic(s) [{{tag_value|length}}]</th>
{% elif tag_name == "Malware-Category" %}
<th><span class="fas fa-virus"></span>&nbsp; Malware Categorie(s) [{{tag_value|length}}]</th>
{% elif tag_name == "Mitre-Enterprise-Attack-Malware" %}
<th><span class="fas fa-virus"></span>&nbsp;MITRE Enterprise Attack Malware [{{tag_value|length}}]</th>
{% elif tag_name == "Mitre-Malware" %}
<th><span class="fas fa-virus"></span>&nbsp;MITRE Malware [{{tag_value|length}}]</th>
{% elif tag_name == "Tool" %}
<th><span class="fas fa-screwdriver-wrench"></span>&nbsp; Tool(s) [{{tag_value|length}}]</th>
{% elif tag_name == "Incident-Classification" %}
<th><span class="fas fa-virus"></span>&nbsp; Incident Classification(s) [{{tag_value|length}}]</th>
{% elif tag_name == "Mitre-Enterprise-Attack-Attack-Pattern" %}
<th><span class="fas fa-triangle-exclamation"></span>&nbsp; MITRE Enterprise Attack Pattern(s) [{{tag_value|length}}]</th>
{% elif tag_name == "Mitre-Attack-Pattern" %}
<th><span class="fas fa-triangle-exclamation"></span>&nbsp; MITRE Attack Pattern(s) [{{tag_value|length}}]</th>
{% elif tag_name == "Rat" %}
<th><span class="fas fa-screwdriver-wrench"></span>&nbsp; Remote Access Tool(s) [{{tag_value|length}}]</th>
{% elif tag_name == "Confidence-In-Analytic-Judgment" %}
<th><span class="fas fa-eye"></span>&nbsp;Confidence in Analytic Judgment</th>
{% elif tag_name == "Sector" %}
<th><span class="fas fa-building"></span>&nbsp; Sectors Involved [{{tag_value|length}}]</th>
{% elif tag_name == "Country" %}
<th><span class="fas fa-flag"></span>&nbsp;Countries [{{tag_value|length}}]</th>
{% elif tag_name == "Target-Information" %}
<th><span class="fas fa-bullseye"></span>&nbsp;Target(s) Information [{{tag_value|length}}]</th>
{% elif tag_name == "Malpedia" %}
<th><span class="fas fa-globe"></span>&nbsp;Malpedia Archives Information [{{tag_value|length}}]</th>
{% elif tag_name == "Lifetime" %}
<th><span class="fas fa-clock"></span>&nbsp;Lifetime</th>
{% elif tag_name == "Certainty" %}
<th><span class="fas fa-star-half-stroke"></span>&nbsp;Certainty</th>
{% elif tag_name == "Backdoor" %}
<th><span class="fas fa-door-open"></span>&nbsp;Backdoor(s) [{{tag_value|length}}]</th>
{% else %}
<th>{{tag_name}}</th>
{% endif %}
<td>
<ul>
{% for event_tag, event_tag_value in tag_value.items %}
{% if 'str' in event_tag_value|gettype %}
<li><a href="{{file.misp.search_tag_link}}{{event_tag_value}}" target="_blank">{{event_tag}}</a></li>
{% else %}
{% if 'int' in event_tag_value.1|gettype %}
<li><a href="{{file.misp.search_tag_link}}{{event_tag_value.0}}" target="_blank">{{event_tag}}</a></li>
{% else %}
<li><a href="{{file.misp.search_tag_link}}{{event_tag_value.0}}" target="_blank" title="{{event_tag_value.1}}">{{event_tag}}</a></li>
{% endif %}
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
{% endif %}
{% if file.misp.links %}
<tr>
<th><span class="fas fa-external-link-alt"></span>External Analysis Link(s) [{{file.misp.links|length}}]</th>
<td>
<ul>
{% for link in file.misp.links %}
<li><a href="{{link}}" target="_blank">{{link}}</a></li>
{% endfor %}
</ul>
</td>
</tr>
{% endif %}
</table>
</div>
</div>
{% endif %}

0 comments on commit 2ec6377

Please sign in to comment.