Detection rules › Panther
Panther rules: brute
| Rule | Severity |
|---|---|
| Brute Force By IP | informational |
| Brute Force By User | informational |
Brute Force By IP
#An actor user was denied login access more times than the configured threshold.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| 1Password | any: Sign-in attempt (catch-all) |
Detection logic
from json import loads
import panther_event_type_helpers as event_type
from panther_base_helpers import add_parse_delay
from panther_ipinfo_helpers import PantherIPInfoException, geoinfo_from_ip
def rule(event):
# filter events on unified data model field
return event.udm("event_type") == event_type.FAILED_LOGIN
def title(event):
# use unified data model field in title
log_type = event.get("p_log_type")
title_str = (
f"{log_type}: Login attempts from IP [{event.udm('source_ip')}] "
"have exceeded the failed logins threshold"
)
if log_type == "AWS.CloudTrail":
title_str += f" in [{event.get('recipientAccountId')}]"
return title_str
def alert_context(event):
try:
geoinfo = geoinfo_from_ip(event=event, match_field=event.udm_path("source_ip"))
except PantherIPInfoException:
geoinfo = {}
if isinstance(geoinfo, str):
geoinfo = loads(geoinfo)
context = {}
context["geolocation"] = (
f"{geoinfo.get('city')}, {geoinfo.get('region')} in " f"{geoinfo.get('country')}"
)
context["ip"] = geoinfo.get("ip")
context["reverse_lookup"] = geoinfo.get("hostname", "No reverse lookup hostname")
context["ip_org"] = geoinfo.get("org", "No organization listed")
try:
context = add_parse_delay(event, context)
except TypeError:
pass
except AttributeError:
pass
return context
Rule specification
AnalysisType: rule
Filename: brute_force_by_ip.py
RuleID: "Standard.BruteForceByIP"
DedupPeriodMinutes: 60
DisplayName: "Brute Force By IP"
Enabled: true
LogTypes:
- Asana.Audit
- Atlassian.Audit
- AWS.CloudTrail
- Box.Event
- GSuite.ActivityEvent
- Okta.SystemLog
- OneLogin.Events
- OnePassword.SignInAttempt
Severity: Info
Tags:
- DataModel
- Credential Access:Brute Force
Threshold: 20
Reports:
MITRE ATT&CK:
- TA0006:T1110
Description: An actor user was denied login access more times than the configured threshold.
Runbook: Analyze the IP they came from, and other actions taken before/after. Check if a user from this ip eventually authenticated successfully.
Reference: https://owasp.org/www-community/controls/Blocking_Brute_Force_Attacks
SummaryAttributes:
- p_any_ip_addresses
Stages and Predicates
Fires on Asana.Audit, Atlassian.Audit, AWS.CloudTrail (and 5 more) events when the condition below holds.
Condition
event_typeisfailed_login
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | eq |
| field:"event_type" kind:eq value:"failed_login" |
Response runbook
Analyze the IP they came from, and other actions taken before/after. Check if a user from this ip eventually authenticated successfully.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additionalEventData": {
"LoginTo": "https://console.aws.amazon.com/console/",
"MFAUsed": "No",
"MobileVersion": "No"
},
"awsRegion": "us-east-1",
"eventID": "1",
"eventName": "ConsoleLogin",
"eventSource": "signin.amazonaws.com",
"eventTime": "2019-01-01T00:00:00Z",
"eventType": "AwsConsoleSignIn",
"eventVersion": "1.05",
"p_event_time": "2021-06-04 09:59:53.650807",
"p_log_type": "AWS.CloudTrail",
"p_parse_time": "2021-06-04 10:02:33.650807",
"recipientAccountId": "123456789012",
"requestParameters": null,
"responseElements": {
"ConsoleLogin": "Failure"
},
"sourceIPAddress": "111.111.111.111",
"userAgent": "Mozilla",
"userIdentity": {
"accountId": "123456789012",
"arn": "arn:aws:iam::123456789012:user/tester",
"principalId": "1111",
"type": "IAMUser",
"userName": "tester"
}
}
Brute Force By User
#An actor user was denied login access more times than the configured threshold.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| 1Password | any: Sign-in attempt (catch-all) |
Detection logic
from json import loads
import panther_event_type_helpers as event_type
from panther_base_helpers import add_parse_delay
from panther_ipinfo_helpers import PantherIPInfoException, geoinfo_from_ip
def rule(event):
# filter events on unified data model field
return event.udm("event_type") == event_type.FAILED_LOGIN
def title(event):
# use unified data model field in title
log_type = event.get("p_log_type")
title_str = (
f"{log_type}: User [{event.udm('actor_user')}] has exceeded the failed logins threshold"
)
if log_type == "AWS.CloudTrail":
title_str += f" in [{event.get('recipientAccountId')}]"
return title_str
def alert_context(event):
try:
geoinfo = geoinfo_from_ip(event=event, match_field=event.udm_path("source_ip"))
except PantherIPInfoException:
geoinfo = {}
if isinstance(geoinfo, str):
geoinfo = loads(geoinfo)
context = {}
context["geolocation"] = (
f"{geoinfo.get('city')}, {geoinfo.get('region')} in " f"{geoinfo.get('country')}"
)
context["ip"] = geoinfo.get("ip")
context["reverse_lookup"] = geoinfo.get("hostname", "No reverse lookup hostname")
context["ip_org"] = geoinfo.get("org", "No organization listed")
try:
context = add_parse_delay(event, context)
except TypeError:
pass
except AttributeError:
pass
return context
Rule specification
AnalysisType: rule
Filename: brute_force_by_user.py
RuleID: "Standard.BruteForceByUser"
DisplayName: "Brute Force By User"
Enabled: true
LogTypes:
- Asana.Audit
- Atlassian.Audit
- AWS.CloudTrail
- Box.Event
- GSuite.ActivityEvent
- Okta.SystemLog
- OneLogin.Events
- OnePassword.SignInAttempt
Severity: Info
Reports:
MITRE ATT&CK:
- TA0006:T1110
Description: An actor user was denied login access more times than the configured
threshold.
DedupPeriodMinutes: 60
Threshold: 20
Reference: https://owasp.org/www-community/controls/Blocking_Brute_Force_Attacks
Runbook: Analyze the user ID who failed to login, and other actions taken before/after.
Check if this user eventually authenticated successfully.
SummaryAttributes:
- p_any_usernames
Tags:
- DataModel
- Credential Access:Brute Force
Stages and Predicates
Fires on Asana.Audit, Atlassian.Audit, AWS.CloudTrail (and 5 more) events when the condition below holds.
Condition
event_typeisfailed_login
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | eq |
| field:"event_type" kind:eq value:"failed_login" |
Response runbook
Analyze the user ID who failed to login, and other actions taken before/after. Check if this user eventually authenticated successfully.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additionalEventData": {
"LoginTo": "https://console.aws.amazon.com/console/",
"MFAUsed": "No",
"MobileVersion": "No"
},
"awsRegion": "us-east-1",
"eventID": "1",
"eventName": "ConsoleLogin",
"eventSource": "signin.amazonaws.com",
"eventTime": "2019-01-01T00:00:00Z",
"eventType": "AwsConsoleSignIn",
"eventVersion": "1.05",
"p_event_time": "2021-06-04 09:59:53.650807",
"p_log_type": "AWS.CloudTrail",
"p_parse_time": "2021-06-04 10:02:33.650807",
"recipientAccountId": "123456789012",
"requestParameters": null,
"responseElements": {
"ConsoleLogin": "Failure"
},
"sourceIPAddress": "111.111.111.111",
"userAgent": "Mozilla",
"userIdentity": {
"accountId": "123456789012",
"arn": "arn:aws:iam::123456789012:user/tester",
"principalId": "1111",
"type": "IAMUser",
"userName": "tester"
}
}