Detection: AWS IAM Role Created with External Trust

Description

Detects a successful AWS IAM CreateRole event whose trust policy allows sts:AssumeRole by a principal in another AWS account or by a wildcard principal. This configuration may provide persistent access if the principal can assume the role. The event alone does not establish that the role was assumed or that its creation was unauthorized.

  1`cloudtrail`
  2eventSource="iam.amazonaws.com"
  3eventName="CreateRole"
  4
  5
  6| where isnull(errorCode) OR errorCode="" OR lower(errorCode)="success"
  7
  8
  9| eval policy_raw='requestParameters.assumeRolePolicyDocument',
 10       role_name='requestParameters.roleName',
 11       role_arn='responseElements.role.arn',
 12       user_arn=coalesce(user_arn, 'userIdentity.arn'),
 13       src=coalesce(src, sourceIPAddress)
 14
 15
 16| where isnotnull(policy_raw)
 17
 18
 19| eval policy=if(match(policy_raw, "(?i)^%7b"), urldecode(policy_raw), policy_raw)
 20
 21
 22| rex field=role_arn "^arn:[^:]+:iam::(?<account_from_role_arn>[0-9]{12}):role/"
 23
 24
 25| eval role_account_id=coalesce(account_from_role_arn, recipientAccountId)
 26
 27| eval statements_json=json_extract(policy, "Statement")
 28
 29| eval statements=if(match(statements_json, "^\s*\["), json_array_to_mv(statements_json), statements_json)
 30
 31
 32| mvexpand statements
 33
 34
 35| eval effect=json_extract(statements, "Effect"),
 36       actions_json=json_extract(statements, "Action"),
 37       principal_json=json_extract(statements, "Principal")
 38
 39
 40| eval actions=if(match(actions_json, "^\s*\["), json_array_to_mv(actions_json), actions_json)
 41
 42
 43| mvexpand actions
 44
 45| mvexpand actions
 46
 47
 48| eval trust_action=actions
 49
 50| eval action_pattern=replace(replace(lower(trust_action), "[*]", "%"), "[?]", "_")
 51
 52
 53| where effect="Allow" AND like("sts:assumerole", action_pattern)
 54
 55| eval aws_json=json_extract(principal_json, "AWS")
 56
 57
 58| eval principals=case(
 59    match(aws_json, "^\s*\["), json_array_to_mv(aws_json),
 60    isnotnull(aws_json), aws_json,
 61    principal_json="*", "*"
 62  )
 63
 64
 65| mvexpand principals
 66
 67
 68| eval trust_principal=principals
 69
 70
 71| rex field=trust_principal "^arn:[^:]+:iam::(?<principal_account_from_arn>[0-9]{12}):"
 72
 73
 74| eval principal_account_id=if(
 75    match(trust_principal, "^[0-9]{12}$"),
 76    trust_principal,
 77    principal_account_from_arn
 78  )
 79
 80
 81| eval trust_type=case(
 82    trust_principal="*", "wildcard",
 83    isnotnull(role_account_id) AND isnotnull(principal_account_id)
 84      AND principal_account_id!=role_account_id, "external"
 85  )
 86
 87
 88| where trust_type="wildcard" OR trust_type="external"
 89
 90
 91| eval event_key=coalesce(eventID, md5(_raw))
 92
 93
 94| dedup event_key trust_principal
 95
 96
 97| table _time eventID user_arn src role_name role_arn role_account_id
 98        trust_type trust_principal principal_account_id trust_action
 99
100
101| `aws_iam_role_created_with_external_trust_filter`

Data Source

Name Platform Sourcetype Source
AWS CloudTrail AWS icon AWS 'aws:cloudtrail' 'aws_cloudtrail'

Macros Used

Name Value
cloudtrail sourcetype=aws:cloudtrail
aws_iam_role_created_with_external_trust_filter search *
aws_iam_role_created_with_external_trust_filter is an empty macro by default. It allows the user to filter out any results (false positives) without editing the SPL.

Annotations

- MITRE ATT&CK
+ Kill Chain Phases
+ NIST
+ CIS
- Threat Actors
ID Technique Tactic
T1098.003 Additional Cloud Roles Persistence
Installation
Exploitation
DE.CM
CIS 10

Default Configuration

This detection is configured by default in Splunk Enterprise Security to run with the following settings:

Setting Value
Disabled true
Cron Schedule 0 * * * *
Earliest Time -70m@m
Latest Time -10m@m
Schedule Window auto
Creates Finding (Notable) Yes
Rule Title %name%
Rule Description %description%
Notable Event Fields user, dest
Creates Intermediate Finding (Risk Event) No
TTP detections generate a Finding (Notable) and may generate Intermediate Findings (Risk Events) for associated entities.

Implementation

You must install Splunk AWS Add on and enable CloudTrail logs in your AWS Environment.

Known False Positives

Approved cross-account integrations and deliberately configured wildcard trust may match. Review the role owner, trust-policy conditions, role permissions, and whether the principal is expected.

Associated Analytic Story

Finding

Title Entity Field Entity Type Risk Score
The AWS IAM role [$role_name$] created with [$trust_type$] trust user_arn user 50

Threat Objects

Field Type
src ip_address

References

Detection Testing

Test Type Status Dataset Source Sourcetype
Validation ✅ Passing N/A N/A N/A
Unit ✅ Passing Dataset aws_cloudtrail aws:cloudtrail
Integration ✅ Passing Dataset aws_cloudtrail aws:cloudtrail

Replay any dataset to Splunk Enterprise by using our replay.py tool or the UI. Alternatively you can replay a dataset into a Splunk Attack Range


Source: GitHub |

Version: 1