This commit is contained in:
overcuriousity 2025-07-30 21:49:54 +02:00
parent dfa3a9fc53
commit e97f8d3a70

View File

@ -124,10 +124,20 @@ class MispAnalyzer(interface.BaseAnalyzer):
return [] return []
try: try:
# For IP searches, query both ip-src and ip-dst
search_types = []
if attr.startswith("ip-"):
search_types = ["ip-src", "ip-dst"]
else:
search_types = [attr]
all_results = []
for search_type in search_types:
payload = { payload = {
"returnFormat": "json", "returnFormat": "json",
"value": value, "value": value,
"type": attr, "type": search_type,
"enforceWarninglist": False, "enforceWarninglist": False,
"includeEventTags": True, "includeEventTags": True,
"includeContext": True, "includeContext": True,
@ -141,10 +151,10 @@ class MispAnalyzer(interface.BaseAnalyzer):
"includeDecayScore": False, "includeDecayScore": False,
"includeFullModel": False, "includeFullModel": False,
}) })
logger.debug(f"Community search enabled for {value} ({attr})") logger.debug(f"Community search enabled for {value} ({search_type})")
else: else:
payload["distribution"] = [0] payload["distribution"] = [0]
logger.debug(f"Own org search only for {value} ({attr})") logger.debug(f"Own org search only for {value} ({search_type})")
self.stats['api_calls'] += 1 self.stats['api_calls'] += 1
@ -156,22 +166,25 @@ class MispAnalyzer(interface.BaseAnalyzer):
timeout=45, timeout=45,
) )
if response.status_code != 200: if response.status_code == 200:
logger.debug(f"MISP API returned status {response.status_code} for {value}")
return []
data = response.json() data = response.json()
attributes = data.get("response", {}).get("Attribute", []) attributes = data.get("response", {}).get("Attribute", [])
all_results.extend(attributes)
else:
logger.debug(f"MISP API returned status {response.status_code} for {value} ({search_type})")
if attributes and self.include_community: # Small delay between search types
time.sleep(0.1)
if all_results and self.include_community:
orgs = set() orgs = set()
for attr_data in attributes: for attr_data in all_results:
org = attr_data.get("Event", {}).get("Orgc", {}).get("name", "Unknown") org = attr_data.get("Event", {}).get("Orgc", {}).get("name", "Unknown")
orgs.add(org) orgs.add(org)
if len(orgs) > 1 or (orgs and list(orgs)[0] not in ["Unknown", "Your Org"]): if len(orgs) > 1 or (orgs and list(orgs)[0] not in ["Unknown", "Your Org"]):
logger.info(f"Community hit for {value}: {len(attributes)} matches from {', '.join(list(orgs)[:3])}") logger.info(f"Community hit for {value}: {len(all_results)} matches from {', '.join(list(orgs)[:3])}")
return attributes return all_results
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
self.stats['api_timeouts'] += 1 self.stats['api_timeouts'] += 1
@ -198,10 +211,8 @@ class MispAnalyzer(interface.BaseAnalyzer):
else: else:
msg = "MISP: Known indicator" msg = "MISP: Known indicator"
correlating_events = [] unique_events = {}
orgs = set() orgs = set()
event_ids = set()
event_links = []
for res in result: for res in result:
event_info = res.get("Event", {}) event_info = res.get("Event", {})
@ -209,23 +220,31 @@ class MispAnalyzer(interface.BaseAnalyzer):
event_desc = event_info.get("info", "Unknown") event_desc = event_info.get("info", "Unknown")
org_name = event_info.get("Orgc", {}).get("name", "Unknown") org_name = event_info.get("Orgc", {}).get("name", "Unknown")
if event_id and event_id not in event_ids: if event_id and event_id not in unique_events:
event_ids.add(event_id) unique_events[event_id] = {
short_desc = event_desc[:60] + "..." if len(event_desc) > 60 else event_desc 'description': event_desc,
correlating_events.append(short_desc) 'url': f"{self.misp_url}/events/view/{event_id}"
event_links.append(f"{self.misp_url}/events/view/{event_id}") }
if org_name != "Unknown": if org_name != "Unknown":
orgs.add(org_name) orgs.add(org_name)
if len(correlating_events) == 1: unique_event_list = list(unique_events.values())
msg += f" | Event: {correlating_events[0]}"
elif len(correlating_events) > 1: if len(unique_event_list) == 1:
msg += f" | Events: {correlating_events[0]}" event_data = unique_event_list[0]
if len(correlating_events) > 1: short_desc = event_data['description'][:50] + "..." if len(event_data['description']) > 50 else event_data['description']
msg += f" + {correlating_events[1]}" msg += f" | Event: {short_desc} | Link: {event_data['url']}"
if len(correlating_events) > 2: elif len(unique_event_list) > 1:
msg += f" + {len(correlating_events)-2} more" msg += f" | {len(unique_event_list)} Events:"
for i, event_data in enumerate(unique_event_list[:2]):
short_desc = event_data['description'][:40] + "..." if len(event_data['description']) > 40 else event_data['description']
msg += f" [{i+1}] {short_desc} ({event_data['url']})"
if i < len(unique_event_list) - 1 and i < 1:
msg += " |"
if len(unique_event_list) > 2:
msg += f" | +{len(unique_event_list)-2} more events"
if self.include_community and orgs: if self.include_community and orgs:
if len(orgs) > 1: if len(orgs) > 1:
@ -236,22 +255,12 @@ class MispAnalyzer(interface.BaseAnalyzer):
msg += f" | Source: {list(orgs)[0]}" msg += f" | Source: {list(orgs)[0]}"
if len(result) > 1: if len(result) > 1:
msg += f" | {len(result)} correlations" msg += f" | {len(result)} total correlations"
if event_links:
if len(event_links) == 1:
msg += f" | MISP Event: {event_links[0]}"
else:
msg += f" | MISP Events: {event_links[0]}"
if len(event_links) > 1:
msg += f", {event_links[1]}"
if len(event_links) > 2:
msg += f" +{len(event_links)-2} more"
tags = [f"MISP-{attr}", "threat-intel"] tags = [f"MISP-{attr}", "threat-intel"]
if self.include_community: if self.include_community:
tags.append("community-intel") tags.append("community-intel")
if len(correlating_events) > 1: if len(unique_event_list) > 1:
tags.append("multi-event-correlation") tags.append("multi-event-correlation")
event.add_comment(msg) event.add_comment(msg)
@ -260,7 +269,7 @@ class MispAnalyzer(interface.BaseAnalyzer):
self.stats['events_marked'] += 1 self.stats['events_marked'] += 1
logger.info(f"Marked event with {len(correlating_events)} correlating MISP events: {', '.join(correlating_events[:3])}") logger.info(f"Marked event with {len(unique_event_list)} unique MISP events")
except Exception as e: except Exception as e:
logger.error(f"Error marking event: {e}") logger.error(f"Error marking event: {e}")