Detection rules › Panther
Panther rules: greynoise
| Rule | Severity |
|---|---|
| GreyNoise V3 Malicious IP Activity | high |
GreyNoise V3 Malicious IP Activity
#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.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Reconnaissance |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| 1Password | any: Sign-in attempt (catch-all) |
Detection logic
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
Rule specification
AnalysisType: rule
Filename: greynoise_malicious_ip.py
RuleID: "Standard.GreyNoiseV3.MaliciousIP"
DisplayName: "GreyNoise V3 Malicious IP Activity"
Enabled: true
Severity: High
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.
Runbook: |
1. Review the alert context and open the GreyNoise URL to assess the IP's classification,
associated CVEs, tags, and scanning behavior.
2. Query the data lake for all events involving this IP to determine what assets or services
were contacted and whether any connections were successful.
3. 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.
Reference: https://docs.panther.com/enrichment/greynoise
DedupPeriodMinutes: 60
Reports:
MITRE ATT&CK:
- TA0043:T1595.001
Tags:
- Reconnaissance:Active Scanning
- GreyNoise
- Threat Intelligence
SummaryAttributes:
- p_any_ip_addresses
- p_source_label
LogTypes:
- Amazon.EKS.Audit
- Asana.Audit
- Atlassian.Audit
- AWS.ALB
- AWS.CloudTrail
- AWS.VPCFlow
- Azure.Audit
- Azure.MonitorActivity
- Box.Event
- Cloudflare.Firewall
- Cloudflare.HttpRequest
- Crowdstrike.FDREvent
- GCP.AuditLog
- GSuite.ActivityEvent
- Notion.AuditLogs
- Okta.SystemLog
- OneLogin.Events
- OnePassword.SignInAttempt
- Zendesk.Audit
- Zoom.Activity
Stages and Predicates
Rule logic imperative Python
The parser could not express this rule's Python logic as a structured condition; the complete logic is under Detection logic above.
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
p_log_type |
Response runbook
1. Review the alert context and open the GreyNoise URL to assess the IP's classification,
associated CVEs, tags, and scanning behavior.
2. Query the data lake for all events involving this IP to determine what assets or services
were contacted and whether any connections were successful.
3. 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.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"p_any_ip_addresses": [
"142.93.204.250"
],
"p_enrichment": {
"greynoise_noise": {
"142.93.204.250": {
"business_service_intelligence": {
"found": false
},
"internet_scanner_intelligence": {
"actor": "alphastrike",
"bot": false,
"classification": "malicious",
"cves": [
"CVE-2021-44228"
],
"found": true,
"metadata": {
"asn": "AS14061",
"organization": "DigitalOcean, LLC",
"os": "Linux",
"source_country": "United States"
},
"spoofable": false,
"tags": [
{
"category": "activity",
"id": "tag1",
"intention": "malicious",
"name": "Log4j Scanner"
}
],
"tor": false,
"vpn": false,
"vpn_service": ""
},
"ip": "142.93.204.250"
}
}
},
"p_log_type": "AWS.CloudTrail"
}