47 строки
2.7 KiB
YAML
47 строки
2.7 KiB
YAML
id: 5b6ee21d-da53-46eb-827c-eab2a9ba3d2f
|
|
name: Suspicious credential token access of valid IAM Roles
|
|
description: |
|
|
'Adversaries may generate temporary credentials of existing privileged IAM roles to access AWS resources that were not previously accessible to perform malicious actions. The credentials may be generated by trusted IAM user or via AWS Cloud Instance Metadata API.
|
|
This query will look for AWS STS API Assume Role operations for RoleArn (Role Amazon Resource Names) which was not historically seen.
|
|
You can also limit the query to only sensitive IAM Roles which needs to be monitored.
|
|
Read more about ingest custom logs using Logstash at https://github.com/Azure/Azure-Sentinel/wiki/Ingest-Custom-Logs-LogStash
|
|
AWS API AssumeRole at https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html and AWS Instance Metadata API at https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html '
|
|
requiredDataConnectors:
|
|
- connectorId: AWS
|
|
dataTypes:
|
|
- AWSCloudTrail
|
|
tactics:
|
|
- InitialAccess
|
|
- DefenseEvasion
|
|
relevantTechniques:
|
|
- T1078
|
|
query: |
|
|
|
|
let starttime = todatetime('{{StartTimeISO}}');
|
|
let endtime = todatetime('{{EndTimeISO}}');
|
|
let lookback = starttime - 14d;
|
|
let midtime = starttime - 1d;
|
|
// Generating historical table of AssumeRole operations for IAM Roles to be compared with last 24 hour
|
|
AWSCloudTrail
|
|
| where TimeGenerated between (starttime..endtime)
|
|
| where EventName == "AssumeRole" | extend RoleArn = tostring(parse_json(RequestParameters).roleArn)
|
|
| project TimeGenerated, EventSource, EventName, UserIdentityType, UserIdentityInvokedBy , SourceIpAddress, RoleArn
|
|
// Doing Leftanti join to find new AssumeRole operation for IAM role which was not seen historically generated from previous table.
|
|
| join kind= leftanti
|
|
(
|
|
AWSCloudTrail
|
|
| where TimeGenerated between (lookback..midtime)
|
|
| where EventName == "AssumeRole" | extend RoleArn = tostring(parse_json(RequestParameters).roleArn)
|
|
| project TimeGenerated, EventSource, EventName, UserIdentityType, UserIdentityInvokedBy , SourceIpAddress, RoleArn
|
|
) on RoleArn, UserIdentityInvokedBy
|
|
| summarize EventCount = count(), StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by RoleArn, EventSource, EventName, UserIdentityType, UserIdentityInvokedBy, SourceIpAddress
|
|
| extend timestamp = StartTimeUtc, IPCustomEntity = SourceIpAddress, AccountCustomEntity = tostring(split(RoleArn, "/")[1])
|
|
entityMappings:
|
|
- entityType: Account
|
|
fieldMappings:
|
|
- identifier: FullName
|
|
columnName: AccountCustomEntity
|
|
- entityType: IP
|
|
fieldMappings:
|
|
- identifier: Address
|
|
columnName: IPCustomEntity |