progress
This commit is contained in:
		
							parent
							
								
									dfa3a9fc53
								
							
						
					
					
						commit
						e97f8d3a70
					
				
							
								
								
									
										143
									
								
								misp_analyzer.py
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								misp_analyzer.py
									
									
									
									
									
								
							@ -124,54 +124,67 @@ class MispAnalyzer(interface.BaseAnalyzer):
 | 
			
		||||
            return []
 | 
			
		||||
            
 | 
			
		||||
        try:
 | 
			
		||||
            payload = {
 | 
			
		||||
                "returnFormat": "json", 
 | 
			
		||||
                "value": value, 
 | 
			
		||||
                "type": attr,
 | 
			
		||||
                "enforceWarninglist": False,
 | 
			
		||||
                "includeEventTags": True,
 | 
			
		||||
                "includeContext": True,
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            if self.include_community:
 | 
			
		||||
                payload.update({
 | 
			
		||||
                    "distribution": [0, 1, 2, 3, 5],
 | 
			
		||||
                    "includeEventUuid": True,
 | 
			
		||||
                    "includeCorrelations": True,
 | 
			
		||||
                    "includeDecayScore": False,
 | 
			
		||||
                    "includeFullModel": False,
 | 
			
		||||
                })
 | 
			
		||||
                logger.debug(f"Community search enabled for {value} ({attr})")
 | 
			
		||||
            # For IP searches, query both ip-src and ip-dst
 | 
			
		||||
            search_types = []
 | 
			
		||||
            if attr.startswith("ip-"):
 | 
			
		||||
                search_types = ["ip-src", "ip-dst"]
 | 
			
		||||
            else:
 | 
			
		||||
                payload["distribution"] = [0]
 | 
			
		||||
                logger.debug(f"Own org search only for {value} ({attr})")
 | 
			
		||||
                search_types = [attr]
 | 
			
		||||
            
 | 
			
		||||
            self.stats['api_calls'] += 1
 | 
			
		||||
            all_results = []
 | 
			
		||||
            
 | 
			
		||||
            response = requests.post(
 | 
			
		||||
                f"{self.misp_url}/attributes/restSearch/",
 | 
			
		||||
                json=payload,
 | 
			
		||||
                headers={"Authorization": self.misp_api_key},
 | 
			
		||||
                verify=False,
 | 
			
		||||
                timeout=45,
 | 
			
		||||
            )
 | 
			
		||||
            for search_type in search_types:
 | 
			
		||||
                payload = {
 | 
			
		||||
                    "returnFormat": "json", 
 | 
			
		||||
                    "value": value, 
 | 
			
		||||
                    "type": search_type,
 | 
			
		||||
                    "enforceWarninglist": False,
 | 
			
		||||
                    "includeEventTags": True,
 | 
			
		||||
                    "includeContext": True,
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                if self.include_community:
 | 
			
		||||
                    payload.update({
 | 
			
		||||
                        "distribution": [0, 1, 2, 3, 5],
 | 
			
		||||
                        "includeEventUuid": True,
 | 
			
		||||
                        "includeCorrelations": True,
 | 
			
		||||
                        "includeDecayScore": False,
 | 
			
		||||
                        "includeFullModel": False,
 | 
			
		||||
                    })
 | 
			
		||||
                    logger.debug(f"Community search enabled for {value} ({search_type})")
 | 
			
		||||
                else:
 | 
			
		||||
                    payload["distribution"] = [0]
 | 
			
		||||
                    logger.debug(f"Own org search only for {value} ({search_type})")
 | 
			
		||||
                
 | 
			
		||||
                self.stats['api_calls'] += 1
 | 
			
		||||
                
 | 
			
		||||
                response = requests.post(
 | 
			
		||||
                    f"{self.misp_url}/attributes/restSearch/",
 | 
			
		||||
                    json=payload,
 | 
			
		||||
                    headers={"Authorization": self.misp_api_key},
 | 
			
		||||
                    verify=False,
 | 
			
		||||
                    timeout=45,
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            if response.status_code != 200:
 | 
			
		||||
                logger.debug(f"MISP API returned status {response.status_code} for {value}")
 | 
			
		||||
                return []
 | 
			
		||||
                if response.status_code == 200:
 | 
			
		||||
                    data = response.json()
 | 
			
		||||
                    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})")
 | 
			
		||||
                
 | 
			
		||||
                # Small delay between search types
 | 
			
		||||
                time.sleep(0.1)
 | 
			
		||||
            
 | 
			
		||||
            data = response.json()
 | 
			
		||||
            attributes = data.get("response", {}).get("Attribute", [])
 | 
			
		||||
            
 | 
			
		||||
            if attributes and self.include_community:
 | 
			
		||||
            if all_results and self.include_community:
 | 
			
		||||
                orgs = set()
 | 
			
		||||
                for attr_data in attributes:
 | 
			
		||||
                for attr_data in all_results:
 | 
			
		||||
                    org = attr_data.get("Event", {}).get("Orgc", {}).get("name", "Unknown")
 | 
			
		||||
                    orgs.add(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:
 | 
			
		||||
            self.stats['api_timeouts'] += 1
 | 
			
		||||
@ -198,10 +211,8 @@ class MispAnalyzer(interface.BaseAnalyzer):
 | 
			
		||||
            else:
 | 
			
		||||
                msg = "MISP: Known indicator"
 | 
			
		||||
            
 | 
			
		||||
            correlating_events = []
 | 
			
		||||
            unique_events = {}
 | 
			
		||||
            orgs = set()
 | 
			
		||||
            event_ids = set()
 | 
			
		||||
            event_links = []
 | 
			
		||||
            
 | 
			
		||||
            for res in result:
 | 
			
		||||
                event_info = res.get("Event", {})
 | 
			
		||||
@ -209,23 +220,31 @@ class MispAnalyzer(interface.BaseAnalyzer):
 | 
			
		||||
                event_desc = event_info.get("info", "Unknown")
 | 
			
		||||
                org_name = event_info.get("Orgc", {}).get("name", "Unknown")
 | 
			
		||||
                
 | 
			
		||||
                if event_id and event_id not in event_ids:
 | 
			
		||||
                    event_ids.add(event_id)
 | 
			
		||||
                    short_desc = event_desc[:60] + "..." if len(event_desc) > 60 else event_desc
 | 
			
		||||
                    correlating_events.append(short_desc)
 | 
			
		||||
                    event_links.append(f"{self.misp_url}/events/view/{event_id}")
 | 
			
		||||
                if event_id and event_id not in unique_events:
 | 
			
		||||
                    unique_events[event_id] = {
 | 
			
		||||
                        'description': event_desc,
 | 
			
		||||
                        'url': f"{self.misp_url}/events/view/{event_id}"
 | 
			
		||||
                    }
 | 
			
		||||
                
 | 
			
		||||
                if org_name != "Unknown":
 | 
			
		||||
                    orgs.add(org_name)
 | 
			
		||||
            
 | 
			
		||||
            if len(correlating_events) == 1:
 | 
			
		||||
                msg += f" | Event: {correlating_events[0]}"
 | 
			
		||||
            elif len(correlating_events) > 1:
 | 
			
		||||
                msg += f" | Events: {correlating_events[0]}"
 | 
			
		||||
                if len(correlating_events) > 1:
 | 
			
		||||
                    msg += f" + {correlating_events[1]}"
 | 
			
		||||
                if len(correlating_events) > 2:
 | 
			
		||||
                    msg += f" + {len(correlating_events)-2} more"
 | 
			
		||||
            unique_event_list = list(unique_events.values())
 | 
			
		||||
            
 | 
			
		||||
            if len(unique_event_list) == 1:
 | 
			
		||||
                event_data = unique_event_list[0]
 | 
			
		||||
                short_desc = event_data['description'][:50] + "..." if len(event_data['description']) > 50 else event_data['description']
 | 
			
		||||
                msg += f" | Event: {short_desc} | Link: {event_data['url']}"
 | 
			
		||||
            elif len(unique_event_list) > 1:
 | 
			
		||||
                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 len(orgs) > 1:
 | 
			
		||||
@ -236,22 +255,12 @@ class MispAnalyzer(interface.BaseAnalyzer):
 | 
			
		||||
                    msg += f" | Source: {list(orgs)[0]}"
 | 
			
		||||
            
 | 
			
		||||
            if len(result) > 1:
 | 
			
		||||
                msg += f" | {len(result)} 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"
 | 
			
		||||
                msg += f" | {len(result)} total correlations"
 | 
			
		||||
 | 
			
		||||
            tags = [f"MISP-{attr}", "threat-intel"]
 | 
			
		||||
            if self.include_community:
 | 
			
		||||
                tags.append("community-intel")
 | 
			
		||||
            if len(correlating_events) > 1:
 | 
			
		||||
            if len(unique_event_list) > 1:
 | 
			
		||||
                tags.append("multi-event-correlation")
 | 
			
		||||
            
 | 
			
		||||
            event.add_comment(msg)
 | 
			
		||||
@ -260,7 +269,7 @@ class MispAnalyzer(interface.BaseAnalyzer):
 | 
			
		||||
            
 | 
			
		||||
            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:
 | 
			
		||||
            logger.error(f"Error marking event: {e}")
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user