Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Monitor AWS Credential abuse or hijacking

Back
Id32555639-b639-4c2b-afda-c0ae0abefa55
RulenameMonitor AWS Credential abuse or hijacking
DescriptionLooking for GetCallerIdentity Events where the UserID Type is AssumedRole

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
SeverityLow
TacticsDiscovery
TechniquesT1087
Required data connectorsAWS
AWSS3
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_CredentialHijack.yaml
Version1.0.3
Arm template32555639-b639-4c2b-afda-c0ae0abefa55.json
Deploy To Azure
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
relevantTechniques:
- T1087
name: Monitor AWS Credential abuse or hijacking
requiredDataConnectors:
- dataTypes:
  - AWSCloudTrail
  connectorId: AWS
- dataTypes:
  - AWSCloudTrail
  connectorId: AWSS3
entityMappings:
- fieldMappings:
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: AccountUPNSuffix
  - identifier: CloudAppAccountId
    columnName: RecipientAccountId
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: SourceIpAddress
  entityType: IP
triggerThreshold: 0
id: 32555639-b639-4c2b-afda-c0ae0abefa55
tactics:
- Discovery
version: 1.0.3
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_CredentialHijack.yaml
queryPeriod: 1d
kind: Scheduled
queryFrequency: 1d
severity: Low
status: Available
description: |
  'Looking for GetCallerIdentity Events where the UserID Type is AssumedRole
  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 '  
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  
triggerOperator: gt
{
  "$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": {
        "alertRuleTemplateName": "32555639-b639-4c2b-afda-c0ae0abefa55",
        "customDetails": null,
        "description": "'Looking for GetCallerIdentity Events where the UserID Type is AssumedRole\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": "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 Web Services/Analytic Rules/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,\nUserAgent, 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": [
          "T1087"
        ],
        "templateVersion": "1.0.3",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}