Awscloudtrail Aws Iam Accessdenied Discovery Events
KQL detection rule by ep3p · MIT
No description provided
let query_frequency = 1h;
let query_period = 2h;
let threshold = 5;
let _ExpectedErrorCodes = dynamic(["AccessDenied", "InvalidAccessException", "Client.UnauthorizedOperation", "AuthorizerConfigurationException"]);
let _ExpectedRoleIdentityRegex = toscalar(
_GetWatchlist("Activity-ExpectedSignificantActivity")
| where Activity == "AWSAssumedRoleIdentityEventName_Regex" and Auxiliar has_any (_ExpectedErrorCodes)
| summarize RegEx = make_set(strcat(SourceResource, ActorPrincipalName))
| extend RegEx = strcat(@"^(", strcat_array(RegEx, "|"), @")$")
);
let _ExpectedUsers = toscalar(
_GetWatchlist("Activity-ExpectedSignificantActivity")
| where Activity == "AWSIAMUser" and Auxiliar has_any (_ExpectedErrorCodes)
| summarize make_list(ActorPrincipalName)
);
let _ExpectedIPAddresses = toscalar(
_GetWatchlist("IP-Vendors")
| where Notes has "[Proxy]"
| summarize make_list(IPAddress)
);
AWSCloudTrail
| where TimeGenerated > ago(query_period)
| where ErrorCode in ("AccessDenied", "InvalidAccessException", "Client.UnauthorizedOperation", "AuthorizerConfigurationException")
| where not(UserIdentityArn in (_ExpectedUsers))
| extend UserIdentityUserName = tostring(split(UserIdentityPrincipalid, ":")[1])
| where not(ErrorCode in (_ExpectedErrorCodes) and strcat(SessionIssuerUserName, UserIdentityUserName) matches regex _ExpectedRoleIdentityRegex)
| summarize arg_min(TimeGenerated, *) by UserIdentityArn, EventName, ErrorCode
| as _Events
| join kind=leftsemi (
_Events
// query_period should be 2 * query_frequency
| evaluate activity_counts_metrics(Type, TimeGenerated, ago(query_period), now(), query_frequency, UserIdentityArn)
| summarize
arg_min(PreviousTimeGenerated = TimeGenerated, PreviousCount = ["count"]),
arg_max(CurrentTimeGenerated = TimeGenerated, CurrentCount = ["count"])
by UserIdentityArn
| where CurrentTimeGenerated > ago(query_period)
| extend PreviousCount = iff(PreviousTimeGenerated == CurrentTimeGenerated, 0, PreviousCount)
| where (not(PreviousCount > threshold) and CurrentCount > threshold)
or ((CurrentCount - PreviousCount) > threshold)
) on UserIdentityArn
| where not(isnotempty(parse_ipv4(SourceIpAddress)) and ipv4_is_in_any_range(SourceIpAddress, _ExpectedIPAddresses))
| invoke AWSIdentityRole()
| project
TimeGenerated,
UserIdentityType,
Identity,
ActorRole,
UserIdentityAccountId,
UserIdentityAccountName,
RecipientAccountId,
RecipientAccountName,
AWSRegion,
SessionCreationDate,
UserIdentityPrincipalid,
UserIdentityArn,
SourceIpAddress,
EventSource,
EventTypeName,
EventName,
ManagementEvent,
ReadOnly,
ErrorCode,
ErrorMessage,
RequestParameters,
ResponseElements,
Resources,
SessionMfaAuthenticated,
UserAgent,
AwsEventId