Analytic rule catalog
AWSCloudTrail - Monitor AWS Credential abuse or hijacking
Back
| Id | 32555639-b639-4c2b-afda-c0ae0abefa55 |
| Rulename | AWSCloudTrail - Monitor AWS Credential abuse or hijacking |
| Description | Identifies AWS STS `GetCallerIdentity` calls made by assumed-role sessions. An attacker who has assumed the role of a legitimate account can call the GetCallerIdentity function to determine what account they are using. A legitimate user using legitimate credentials would not need to call GetCallerIdentity since they should already know what account they are using. More Information: https://duo.com/decipher/trailblazer-hunts-compromised-credentials-in-aws AWS STS GetCallerIdentity API: https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html |
| Severity | Low |
| Tactics | Discovery |
| Techniques | T1580 |
| Required data connectors | AWS AWSS3 |
| Kind | Scheduled |
| Query frequency | 1d |
| Query period | 1d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon%20Web%20Services/Analytic%20Rules/AWS_CredentialHijack.yaml |
| Version | 1.0.4 |
| Arm template | 32555639-b639-4c2b-afda-c0ae0abefa55.json |
AWSCloudTrail
| where EventName =~ "GetCallerIdentity" and UserIdentityType =~ "AssumedRole"
| extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)
| extend UserName = tostring(split(UserIdentityArn, '/')[-1])
| extend AccountName = case(UserIdentityPrincipalid == "Anonymous", "Anonymous", isempty(UserIdentityUserName), UserName, UserIdentityUserName)
| extend AccountName = iif(AccountName contains "@", tostring(split(AccountName, '@', 0)[0]), AccountName),
AccountUPNSuffix = iif(AccountName contains "@", tostring(split(AccountName, '@', 1)[0]), "")
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by SourceIpAddress, EventName, EventTypeName, UserIdentityType, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityAccountId, UserIdentityPrincipalid,
UserAgent, UserIdentityUserName, SessionMfaAuthenticated, AWSRegion, EventSource, AdditionalEventData, ResponseElements
| extend timestamp = StartTime
| sort by EndTime desc nulls last
triggerThreshold: 0
version: 1.0.4
kind: Scheduled
description: |
Identifies AWS STS `GetCallerIdentity` calls made by assumed-role sessions.
An attacker who has assumed the role of a legitimate account can call the GetCallerIdentity function to determine what account they are using.
A legitimate user using legitimate credentials would not need to call GetCallerIdentity since they should already know what account they are using.
More Information: https://duo.com/decipher/trailblazer-hunts-compromised-credentials-in-aws
AWS STS GetCallerIdentity API: https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html
queryFrequency: 1d
triggerOperator: gt
relevantTechniques:
- T1580
entityMappings:
- fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- identifier: CloudAppAccountId
columnName: RecipientAccountId
entityType: Account
- fieldMappings:
- identifier: Address
columnName: SourceIpAddress
entityType: IP
id: 32555639-b639-4c2b-afda-c0ae0abefa55
query: |
AWSCloudTrail
| where EventName =~ "GetCallerIdentity" and UserIdentityType =~ "AssumedRole"
| extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)
| extend UserName = tostring(split(UserIdentityArn, '/')[-1])
| extend AccountName = case(UserIdentityPrincipalid == "Anonymous", "Anonymous", isempty(UserIdentityUserName), UserName, UserIdentityUserName)
| extend AccountName = iif(AccountName contains "@", tostring(split(AccountName, '@', 0)[0]), AccountName),
AccountUPNSuffix = iif(AccountName contains "@", tostring(split(AccountName, '@', 1)[0]), "")
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by SourceIpAddress, EventName, EventTypeName, UserIdentityType, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityAccountId, UserIdentityPrincipalid,
UserAgent, UserIdentityUserName, SessionMfaAuthenticated, AWSRegion, EventSource, AdditionalEventData, ResponseElements
| extend timestamp = StartTime
| sort by EndTime desc nulls last
alertDetailsOverride:
alertDisplayNameFormat: AWS credential hijack indicator from {{AccountName}}
alertDescriptionFormat: GetCallerIdentity invoked by {{AccountName}} from {{SourceIpAddress}} in {{AWSRegion}}.
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon%20Web%20Services/Analytic%20Rules/AWS_CredentialHijack.yaml
requiredDataConnectors:
- dataTypes:
- AWSCloudTrail
connectorId: AWS
- dataTypes:
- AWSCloudTrail
connectorId: AWSS3
customDetails:
EventSource: EventSource
EventType: EventTypeName
AWSRegion: AWSRegion
EventName: EventName
tactics:
- Discovery
queryPeriod: 1d
severity: Low
status: Available
name: AWSCloudTrail - Monitor AWS Credential abuse or hijacking
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/32555639-b639-4c2b-afda-c0ae0abefa55')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/32555639-b639-4c2b-afda-c0ae0abefa55')]",
"properties": {
"alertDetailsOverride": {
"alertDescriptionFormat": "GetCallerIdentity invoked by {{AccountName}} from {{SourceIpAddress}} in {{AWSRegion}}.",
"alertDisplayNameFormat": "AWS credential hijack indicator from {{AccountName}}"
},
"alertRuleTemplateName": "32555639-b639-4c2b-afda-c0ae0abefa55",
"customDetails": {
"AWSRegion": "AWSRegion",
"EventName": "EventName",
"EventSource": "EventSource",
"EventType": "EventTypeName"
},
"description": "Identifies AWS STS `GetCallerIdentity` calls made by assumed-role sessions.\nAn attacker who has assumed the role of a legitimate account can call the GetCallerIdentity function to determine what account they are using.\nA legitimate user using legitimate credentials would not need to call GetCallerIdentity since they should already know what account they are using.\nMore Information: https://duo.com/decipher/trailblazer-hunts-compromised-credentials-in-aws \nAWS STS GetCallerIdentity API: https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html\n",
"displayName": "AWSCloudTrail - Monitor AWS Credential abuse or hijacking",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "AccountName",
"identifier": "Name"
},
{
"columnName": "AccountUPNSuffix",
"identifier": "UPNSuffix"
},
{
"columnName": "RecipientAccountId",
"identifier": "CloudAppAccountId"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "SourceIpAddress",
"identifier": "Address"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon%20Web%20Services/Analytic%20Rules/AWS_CredentialHijack.yaml",
"query": "AWSCloudTrail\n| where EventName =~ \"GetCallerIdentity\" and UserIdentityType =~ \"AssumedRole\"\n| extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)\n| extend UserName = tostring(split(UserIdentityArn, '/')[-1])\n| extend AccountName = case(UserIdentityPrincipalid == \"Anonymous\", \"Anonymous\", isempty(UserIdentityUserName), UserName, UserIdentityUserName)\n| extend AccountName = iif(AccountName contains \"@\", tostring(split(AccountName, '@', 0)[0]), AccountName),\n AccountUPNSuffix = iif(AccountName contains \"@\", tostring(split(AccountName, '@', 1)[0]), \"\")\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by SourceIpAddress, EventName, EventTypeName, UserIdentityType, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityAccountId, UserIdentityPrincipalid,\n UserAgent, UserIdentityUserName, SessionMfaAuthenticated, AWSRegion, EventSource, AdditionalEventData, ResponseElements\n| extend timestamp = StartTime\n| sort by EndTime desc nulls last\n",
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"severity": "Low",
"status": "Available",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"Discovery"
],
"techniques": [
"T1580"
],
"templateVersion": "1.0.4",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}