AnalysisType: rule
Filename: aws_console_getsignintoken.py
RuleID: "AWS.Console.GetSigninToken.Abuse"
DisplayName: "AWS Console GetSigninToken Potential Abuse"
Enabled: true
LogTypes:
- AWS.CloudTrail
Tags:
- AWS
- AWS STS
- Lateral Movement:Remote Services
- Defense Evasion:Use Alternate Authentication Material
Reports:
MITRE ATT&CK:
- TA0008:T1021.007
- TA0005:T1550.001
Status: Experimental
Severity: Medium
Description: >
Detects GetSigninToken calls from non-SSO user agents. An adversary can use tools
like aws_consoler to convert compromised CLI credentials into a federated console
session, bypassing MFA requirements and obscuring the original access key. The
GetSigninToken API creates temporary console access from STS temporary credentials.
Runbook: |
1. Query CloudTrail for all API calls by userIdentity:arn in the 6 hours before and after this alert, focusing on ConsoleLogin and console-based actions that may indicate the federated session was used
2. Check if sourceIPAddress and userAgent are associated with known internal tooling or if they match patterns of attacker tools like aws_consoler
3. Find all other alerts from this userIdentity:accessKeyId in the past 7 days to determine if the underlying credentials are compromised
Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html
SummaryAttributes:
- userAgent
- sourceIpAddress
- recipientAccountId
- p_any_aws_arns
DedupPeriodMinutes: 60
Threshold: 1
Tests:
- Name: Suspicious GetSigninToken
ExpectedResult: true
Log:
{
"awsRegion": "us-east-1",
"eventName": "GetSigninToken",
"eventSource": "signin.amazonaws.com",
"eventTime": "2024-01-15T10:30:00Z",
"eventType": "AwsApiCall",
"recipientAccountId": "123456789012",
"sourceIPAddress": "203.0.113.50",
"userAgent": "python-requests/2.28.0",
"userIdentity": {
"accessKeyId": "ASIAIOSFODNN7EXAMPLE",
"accountId": "123456789012",
"arn": "arn:aws:sts::123456789012:assumed-role/MyRole/session",
"type": "AssumedRole"
}
}
- Name: Legitimate SSO Portal GetSigninToken
ExpectedResult: false
Log:
{
"awsRegion": "us-east-1",
"eventName": "GetSigninToken",
"eventSource": "signin.amazonaws.com",
"eventTime": "2024-01-15T10:30:00Z",
"eventType": "AwsApiCall",
"recipientAccountId": "123456789012",
"sourceIPAddress": "10.0.0.1",
"userAgent": "Jersey/${project.version}",
"userIdentity": {
"type": "AssumedRole",
"arn": "arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_Admin/user@example.com"
}
}
- Name: Legitimate SSO Portal GetSigninToken (Go client)
ExpectedResult: false
Log:
{
"awsRegion": "us-east-1",
"eventName": "GetSigninToken",
"eventSource": "signin.amazonaws.com",
"eventTime": "2024-01-15T10:30:00Z",
"eventType": "AwsApiCall",
"recipientAccountId": "123456789012",
"sourceIPAddress": "10.0.0.1",
"userAgent": "Go-http-client/2.0",
"userIdentity": {
"type": "AssumedRole",
"arn": "arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_Admin/user@example.com"
}
}
- Name: Unrelated Signin Event
ExpectedResult: false
Log:
{
"awsRegion": "us-east-1",
"eventName": "ConsoleLogin",
"eventSource": "signin.amazonaws.com",
"eventTime": "2024-01-15T10:30:00Z",
"eventType": "AwsConsoleSignIn",
"recipientAccountId": "123456789012",
"sourceIPAddress": "203.0.113.50",
"userAgent": "Mozilla/5.0",
"userIdentity": {
"type": "IAMUser",
"userName": "admin"
}
}
# ------ paired body: aws_console_getsignintoken.py ------
from panther_aws_helpers import aws_rule_context
# User agents associated with legitimate AWS SSO portal sign-in token requests
SSO_USER_AGENTS = ["Jersey/${project.version}", "Go-http-client/2.0"]
def rule(event):
if event.get("eventSource") != "signin.amazonaws.com":
return False
if event.get("eventName") != "GetSigninToken":
return False
# Exclude legitimate AWS SSO portal traffic
user_agent = event.get("userAgent", "")
for sso_ua in SSO_USER_AGENTS:
if sso_ua in user_agent:
return False
return True
def title(event):
arn = event.deep_get("userIdentity", "arn", default="<unknown>")
ip_addr = event.get("sourceIPAddress", "<unknown>")
user_agent = event.get("userAgent", "<unknown>")
return (
f"Suspicious GetSigninToken call from [{ip_addr}] "
f"as [{arn}] with user agent [{user_agent}]"
)
def alert_context(event):
return aws_rule_context(event)