Detection rules › Panther

Panther rules: brute

RuleSeverity
Brute Force By IPinformational
Brute Force By Userinformational

Brute Force By IP

#
Severity
informational
Log types
Asana.Audit, Atlassian.Audit, AWS.CloudTrail, Box.Event, GSuite.ActivityEvent, Okta.SystemLog, OneLogin.Events, OnePassword.SignInAttempt
Tags
DataModel, Credential Access:Brute Force
Reference
owasp.org
Source
github.com/panther-labs/panther-analysis

An actor user was denied login access more times than the configured threshold.

MITRE ATT&CK Coverage

TacticTechniques
Credential Access

Telemetry Coverage

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_type is failed_login
Alert cadence
alerts after 20 matches within 1h

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event_typeeq
  • failed_login corpus 2 (panther 2)
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

#
Severity
informational
Log types
Asana.Audit, Atlassian.Audit, AWS.CloudTrail, Box.Event, GSuite.ActivityEvent, Okta.SystemLog, OneLogin.Events, OnePassword.SignInAttempt
Tags
DataModel, Credential Access:Brute Force
Reference
owasp.org
Source
github.com/panther-labs/panther-analysis

An actor user was denied login access more times than the configured threshold.

MITRE ATT&CK Coverage

TacticTechniques
Credential Access

Telemetry Coverage

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_type is failed_login
Alert cadence
alerts after 20 matches within 1h

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event_typeeq
  • failed_login corpus 2 (panther 2)
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"
  }
}

Back to all Panther rules