GreyNoise V3 Malicious IP Activity
Description
Detects when an IP address in any log event is classified as malicious or unknown by GreyNoise V3 internet scanner intelligence. Known business services and benign IPs are excluded.
Query · python
from panther_greynoise_helpers import (
get_greynoise_v3_business_service_object,
get_greynoise_v3_object,
greynoise_severity_decode,
greynoise_v3_alert_context,
severity_greater_than,
)
CLASSIFICATIONS_TO_ALERT = {"malicious", "unknown"}
MATCHED_IPS = {} # {ip: classification}
def _alerting_classification(classification):
"""Collapse a possibly list-shaped classification (multiple LUT hits) to the
single alertable classification, preferring 'malicious' over 'unknown'."""
values = classification if isinstance(classification, list) else [classification]
matches = [value for value in values if value in CLASSIFICATIONS_TO_ALERT]
if not matches:
return None
return "malicious" if "malicious" in matches else matches[0]
def rule(event):
global MATCHED_IPS # pylint: disable=global-statement
MATCHED_IPS = {}
scanner = get_greynoise_v3_object(event)
if not scanner:
return False
bsi = get_greynoise_v3_business_service_object(event)
for ip_addr in event.get("p_any_ip_addresses", []):
if bsi and bsi.found(ip_addr):
continue
classification = _alerting_classification(scanner.classification(ip_addr))
if classification:
MATCHED_IPS[ip_addr] = classification
return bool(MATCHED_IPS)
def title(event):
log_type = event.get("p_log_type", "Unknown")
if len(MATCHED_IPS) == 1:
ip_addr, classification = next(iter(MATCHED_IPS.items()))
return f"GreyNoise: {classification.title()} IP [{ip_addr}] detected in {log_type}"
return f"GreyNoise: {len(MATCHED_IPS)} suspicious IPs detected in {log_type}"
def severity(event): # pylint: disable=unused-argument
highest = None
for classification in MATCHED_IPS.values():
sev = greynoise_severity_decode(classification, "DEFAULT")
if highest is None or severity_greater_than(sev, highest):
highest = sev
return highest or "DEFAULT"
def alert_context(event):
if not MATCHED_IPS:
return {}
ctx = {}
for ip_addr, classification in MATCHED_IPS.items():
ip_ctx = greynoise_v3_alert_context(event, ip_addr)
ip_ctx["MatchedClassification"] = classification
ctx[ip_addr] = ip_ctx
return ctx
Analyst notes
- Review the alert context and open the GreyNoise URL to assess the IP's classification, associated CVEs, tags, and scanning behavior.
- Query the data lake for all events involving this IP to determine what assets or services were contacted and whether any connections were successful.
- If the IP is confirmed malicious and interaction was successful, block the IP, isolate affected hosts, and reset any credentials that may have been exposed.