Root Console Login


Description

The root account has been logged into.

Query · python

from panther_ipinfo_helpers import geoinfo_from_ip_formatted


def rule(event):
    return (
        event.get("eventName") == "ConsoleLogin"
        and event.deep_get("userIdentity", "type") == "Root"
        and event.deep_get("responseElements", "ConsoleLogin") == "Success"
    )


def title(event):
    return (
        "AWS root login detected from "
        f"({geoinfo_from_ip_formatted(event, 'sourceIPAddress')}) "
        f"in account "
        f"[{event.get('recipientAccountId')}]"
    )


def dedup(event):
    # Each Root login should generate a unique alert
    return "-".join(
        [event.get("recipientAccountId"), event.get("eventName"), event.get("eventTime")]
    )


def alert_context(event):
    return {
        "sourceIPAddress": event.get("sourceIPAddress"),
        "userIdentityAccountId": event.deep_get("userIdentity", "accountId"),
        "userIdentityArn": event.deep_get("userIdentity", "arn"),
        "eventTime": event.get("eventTime"),
        "mfaUsed": event.deep_get("additionalEventData", "MFAUsed"),
    }

Analyst notes

Investigate the usage of the root account. If this root activity was not authorized, immediately change the root credentials and investigate what actions the root account took.

Raw source Root Console Login · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: aws_console_root_login.py
RuleID: "AWS.Console.RootLogin"
DisplayName: "Root Console Login"
Enabled: true
DedupPeriodMinutes: 15
LogTypes:
  - AWS.CloudTrail
Tags:
  - AWS
  - Identity & Access Management
  - Authentication
  - DemoThreatHunting
  - Privilege Escalation:Valid Accounts
Reports:
  CIS:
    - 3.6
  MITRE ATT&CK:
    - TA0004:T1078
Severity: High
Description: The root account has been logged into.
Runbook: >
  Investigate the usage of the root account. If this root activity was not authorized, immediately change the root credentials and investigate what actions the root account took.
Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html
SummaryAttributes:
  - userAgent
  - sourceIpAddress
  - recipientAccountId
  - p_any_aws_arns
Tests:
  - Name: Successful Root Login
    ExpectedResult: true
    Mocks:
      - objectName: geoinfo_from_ip_formatted
        returnValue: "111.111.111.111 in SF, California in USA"
    Log:
      {
        "eventVersion": "1.05",
        "userIdentity":
          {
            "type": "Root",
            "principalId": "1111",
            "arn": "arn:aws:iam::123456789012:root",
            "accountId": "123456789012",
            "userName": "root",
          },
        "eventTime": "2019-01-01T00:00:00Z",
        "eventSource": "signin.amazonaws.com",
        "eventName": "ConsoleLogin",
        "awsRegion": "us-east-1",
        "sourceIPAddress": "111.111.111.111",
        "userAgent": "Mozilla",
        "requestParameters": null,
        "responseElements": { "ConsoleLogin": "Success" },
        "additionalEventData":
          {
            "LoginTo": "https://console.aws.amazon.com/console/",
            "MobileVersion": "No",
            "MFAUsed": "No",
          },
        "eventID": "1",
        "eventType": "AwsConsoleSignIn",
        "recipientAccountId": "123456789012",
      }
  - Name: Non-Login Event
    ExpectedResult: false
    Log:
      {
        "eventVersion": "1.06",
        "userIdentity":
          {
            "type": "AssumedRole",
            "principalId": "1111:tester",
            "arn": "arn:aws:sts::123456789012:user/tester",
            "accountId": "123456789012",
            "accessKeyId": "1",
            "sessionContext":
              {
                "sessionIssuer":
                  {
                    "type": "Role",
                    "principalId": "1111",
                    "arn": "arn:aws:iam::123456789012:user/tester",
                    "accountId": "123456789012",
                    "userName": "tester",
                  },
                "attributes":
                  {
                    "creationDate": "2019-01-01T00:00:00Z",
                    "mfaAuthenticated": "true",
                  },
              },
          },
        "eventTime": "2019-01-01T00:00:00Z",
        "eventSource": "dynamodb.amazonaws.com",
        "eventName": "DescribeTable",
        "awsRegion": "us-west-2",
        "sourceIPAddress": "111.111.111.111",
        "userAgent": "console.amazonaws.com",
        "requestParameters": { "tableName": "table" },
        "responseElements": null,
        "requestID": "1",
        "eventID": "1",
        "readOnly": true,
        "resources":
          [
            {
              "accountId": "123456789012",
              "type": "AWS::DynamoDB::Table",
              "ARN": "arn::::table/table",
            },
          ],
        "eventType": "AwsApiCall",
        "apiVersion": "2012-08-10",
        "managementEvent": true,
        "recipientAccountId": "123456789012",
      }


# ------ paired body: aws_console_root_login.py ------

from panther_ipinfo_helpers import geoinfo_from_ip_formatted


def rule(event):
    return (
        event.get("eventName") == "ConsoleLogin"
        and event.deep_get("userIdentity", "type") == "Root"
        and event.deep_get("responseElements", "ConsoleLogin") == "Success"
    )


def title(event):
    return (
        "AWS root login detected from "
        f"({geoinfo_from_ip_formatted(event, 'sourceIPAddress')}) "
        f"in account "
        f"[{event.get('recipientAccountId')}]"
    )


def dedup(event):
    # Each Root login should generate a unique alert
    return "-".join(
        [event.get("recipientAccountId"), event.get("eventName"), event.get("eventTime")]
    )


def alert_context(event):
    return {
        "sourceIPAddress": event.get("sourceIPAddress"),
        "userIdentityAccountId": event.deep_get("userIdentity", "accountId"),
        "userIdentityArn": event.deep_get("userIdentity", "arn"),
        "eventTime": event.get("eventTime"),
        "mfaUsed": event.deep_get("additionalEventData", "MFAUsed"),
    }

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.