Detection rules › Panther
Panther rules: anomalous
| Rule | Severity |
|---|---|
| Anomalous AccessDenied Requests | |
| Anomalous VPC Traffic to Destination Port | |
| RoleAssumes by Multiple Useragents | |
| VPC Flow Port Scanning | medium |
| VPC Flow Port Scanning |
Anomalous AccessDenied Requests
#ARNs with a high Access Denied error rate could indicate an error or compromised credentials attempting to perform reconnaissance.
Rule specification
AnalysisType: scheduled_query
Description: ARNs with a high Access Denied error rate could indicate an error or compromised credentials attempting to perform reconnaissance.
Enabled: false
SnowflakeQuery: |
SELECT
userIdentity:arn as arn,
count(DISTINCT eventName) as distinctEventNames
FROM
panther_logs.public.aws_cloudtrail
WHERE
errorCode = 'AccessDenied'
and p_occurs_since('1 day')
GROUP BY userIdentity:arn
HAVING count(DISTINCT eventName) > 10
DatabricksQuery: |
SELECT
userIdentity:arn as arn,
count(DISTINCT eventName) as distinctEventNames
FROM
panther_logs.aws_cloudtrail
WHERE
errorCode = 'AccessDenied'
and p_occurs_since('1 day')
GROUP BY userIdentity:arn
HAVING count(DISTINCT eventName) > 10
QueryName: "Anomalous AccessDenied Requests"
Schedule:
RateMinutes: 1440
TimeoutMinutes: 5
Stages and Predicates
Stage 1: source
Stage 2: filter
errorCodeisAccessDenied
Stage 3: having
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
errorCode | eq |
| field:"aws::errorCode" kind:eq value:"AccessDenied" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
arn | userIdentity:arn |
distinctEventNames | count ( DISTINCT eventName ) |
Anomalous VPC Traffic to Destination Port
#Look at which VPC hosts have been sending a lot of traffic over the past hour
Rule specification
AnalysisType: saved_query
QueryName: "Anomalous VPC Traffic to Destination Port"
Description: Look at which VPC hosts have been sending a lot of traffic over the past hour
Tags:
- Anomaly Detection
- Example
- Statistical Anomaly
Query: |-
-- pragma: template
{% import 'anomalies' statistical_anomaly %}
with subquery as (
SELECT *
FROM panther_logs.public.aws_vpcflow
WHERE
p_occurs_since('7 day')
AND dstAddr not like '10.%'
AND dstPort < 1024
AND flowDirection = 'egress'
AND pktDstAwsService is null
),
{{ statistical_anomaly('subquery', 'srcAddr', 'bytes', 'sum', '1', 'hour', 10) }}
RoleAssumes by Multiple Useragents
#RoleAssumes with multiple Useragents could indicate compromised credentials.
Telemetry coverage
Rules detecting the same action
These rules filter on the same operation.
- AWS STS AssumeRole with New MFA Device (Elastic)
- AWS STS Role Assumption by Service (Elastic)
- AWS STS Role Assumption by User (Elastic)
- AWS STS Role Chaining (Elastic)
Rule specification
AnalysisType: scheduled_query
Description: RoleAssumes with multiple Useragents could indicate compromised credentials.
Enabled: false
SnowflakeQuery: |
SELECT
requestParameters:roleArn as roleArn,
userIdentity:principalId as principalId,
count(DISTINCT userAgent) as distinctUserAgents
FROM
panther_logs.public.aws_cloudtrail
WHERE
eventSource = 'sts.amazonaws.com'
and eventName = 'AssumeRole'
and p_occurs_since('1 days')
and userIdentity:principalId != 'null'
and userAgent != 'AWS Internal'
and requestParameters:roleArn != 'null'
GROUP BY requestParameters:roleArn, userIdentity:principalId
HAVING count(DISTINCT userAgent) > 1
ORDER BY count(DISTINCT userAgent) DESC
DatabricksQuery: |
SELECT
requestParameters:roleArn as roleArn,
userIdentity:principalId as principalId,
count(DISTINCT userAgent) as distinctUserAgents
FROM
panther_logs.aws_cloudtrail
WHERE
eventSource = 'sts.amazonaws.com'
and eventName = 'AssumeRole'
and p_occurs_since('1 days')
and userIdentity:principalId != 'null'
and userAgent != 'AWS Internal'
and requestParameters:roleArn != 'null'
GROUP BY requestParameters:roleArn, userIdentity:principalId
HAVING count(DISTINCT userAgent) > 1
ORDER BY count(DISTINCT userAgent) DESC
QueryName: "RoleAssumes by Multiple Useragents"
Schedule:
RateMinutes: 1440
TimeoutMinutes: 5
Stages and Predicates
Stage 1: source
Stage 2: filter
eventSourceissts.amazonaws.comeventNameisAssumeRoleuserIdentity:principalIdis notnulluserAgentis notAWS InternalrequestParameters:roleArnis notnull
Stage 3: having
Indicators
These rows show field, operator, and value matches.
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
roleArn | requestParameters:roleArn |
principalId | userIdentity:principalId |
distinctUserAgents | count ( DISTINCT userAgent ) |
VPC Flow Port Scanning
#Searches for potential port scanning activity in VPC Flow logs
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Discovery |
Detection logic
def rule(_):
return True
Rule specification
AnalysisType: scheduled_rule
Filename: anomalous_vpc_port_activity.py
RuleID: "VPCFlow.Port.Scanning"
DisplayName: "VPC Flow Port Scanning"
Reports:
MITRE ATT&CK:
- TA0007:T1046
Tags:
- Discovery:Network Service Discovery
Description: >
Searches for potential port scanning activity in VPC Flow logs
Enabled: false
Status: Deprecated
Runbook: >
Analyze VPC Flow logs of suspicious IPs and see what ports are being accessed. A sequence of ports may be suspicious
ScheduledQueries:
- VPC Flow Port Scanning
Severity: Medium
Stages and Predicates
Rule logic
This rule alerts on rows returned by its scheduled query VPC Flow Port Scanning; its Python module (Detection logic above) shapes the alert rather than filtering.
Response runbook
Analyze VPC Flow logs of suspicious IPs and see what ports are being accessed. A sequence of ports may be suspicious
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"Anything": "any value"
}
VPC Flow Port Scanning
#Instances of a srcAddr communicating with multiple ports on a dstAddr could indicate port scanning activity.
Rule specification
AnalysisType: scheduled_query
Description: Instances of a srcAddr communicating with multiple ports on a dstAddr could indicate port scanning activity.
Enabled: false
SnowflakeQuery: |
SELECT
srcAddr,
dstAddr,
COUNT(DISTINCT dstPort) as distinctDstPorts,
vpcId,
region,
subNetId
FROM panther_logs.public.aws_vpcflow
WHERE p_occurs_since('1 hour')
and srcAddr != 'null'
and srcPort not in (443, 80, 2049, 123, 445, 53, 853)
and dstPort not in (443, 80, 2049, 123, 445, 53, 853)
and flowDirection = 'egress'
GROUP BY srcAddr, dstAddr, vpcId, region, subNetId
HAVING COUNT(DISTINCT dstPort) >= 10
ORDER BY COUNT(DISTINCT dstPort) DESC
DatabricksQuery: |
SELECT
srcAddr,
dstAddr,
COUNT(DISTINCT dstPort) as distinctDstPorts,
vpcId,
region,
subNetId
FROM panther_logs.aws_vpcflow
WHERE p_occurs_since('1 hour')
and srcAddr != 'null'
and srcPort not in (443, 80, 2049, 123, 445, 53, 853)
and dstPort not in (443, 80, 2049, 123, 445, 53, 853)
and flowDirection = 'egress'
GROUP BY srcAddr, dstAddr, vpcId, region, subNetId
HAVING COUNT(DISTINCT dstPort) >= 10
ORDER BY COUNT(DISTINCT dstPort) DESC
QueryName: "VPC Flow Port Scanning"
Schedule:
RateMinutes: 60
TimeoutMinutes: 5
Stages and Predicates
Stage 1: source
Stage 2: filter
srcAddris notnullsrcPortis not one of443,80,2049,123,445dstPortis not one of443,80,2049,123,445flowDirectionisegress
Stage 3: having
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
dstPort | in | 123, 2049, 443, 445, 53, 80, 853 | excludes:dstPort |
srcPort | in | 123, 2049, 443, 445, 53, 80, 853 | excludes:srcPort |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
flowDirection | eq |
| field:"flowDirection" kind:eq value:"egress" |
srcAddr | ne |
| field:"srcAddr" kind:ne value:"null" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
srcAddr | |
dstAddr | |
distinctDstPorts | COUNT ( DISTINCT dstPort ) |
vpcId | |
region | |
subNetId |