AWS Guard Duty Alert
Id | bf0cde21-0c41-48f6-a40c-6b5bd71fa106 |
Rulename | AWS Guard Duty Alert |
Description | Amazon GuardDuty is a threat detection service that continuously monitors your AWS accounts and workloads for malicious activity and delivers detailed security findings for visibility and remediation. This templates create an alert for each Amazon GuardDuty finding. |
Severity | Medium |
Required data connectors | AWSS3 |
Kind | Scheduled |
Query frequency | 5h |
Query period | 5h |
Trigger threshold | 0 |
Trigger operator | gt |
Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_GuardDuty_template.yaml |
Version | 1.0.6 |
Arm template | bf0cde21-0c41-48f6-a40c-6b5bd71fa106.json |
// https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings.html
AWSGuardDuty
// Parse the finding
// https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-format.html
// Example: "ThreatPurpose:ResourceTypeAffected/ThreatFamilyName.DetectionMechanism!Artifact"
| extend findingTokens = split(ActivityType, ":")
| extend ThreatPurpose=findingTokens[0], findingTokens=split(findingTokens[1], "/")
| extend ResourceTypeAffected=findingTokens[0], findingTokens= split(findingTokens[1], ".")
| extend ThreatFamilyName=findingTokens[0], findingTokens=split(findingTokens[1], "!")
| extend DetectionMechanism=findingTokens[0], Artifact=findingTokens[1]
// Assign severity level
// https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings.html#guardduty_findings-severity
| extend Severity =
case (
Severity >= 7.0, "High",
Severity between (4.0 .. 6.9), "Medium",
Severity between (1.0 .. 3.9), "Low",
"Unknown"
)
// Pull out any available resource details we can extract entities from. These may not exist in the alert.
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_Resource.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AccessKeyDetails.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RdsDbUserDetails.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_KubernetesDetails.html
| extend AccessKeyDetails=ResourceDetails.accessKeyDetails
| extend RdsDbUserDetails=ResourceDetails.rdsDbUserDetails
| extend KubernetesDetails=ResourceDetails.kubernetesDetails
// Pull out any available action details we can extract entities from. These may not exist in the alert.
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_Action.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AwsApiCallAction.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_KubernetesApiCallAction.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_NetworkConnectionAction.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RdsLoginAttemptAction.html
| extend ServiceAction =
case(
isnotempty(ServiceDetails.action.awsApiCallAction), ServiceDetails.action.awsApiCallAction,
isnotempty(ServiceDetails.action.kubernetesApiCallAction), ServiceDetails.action.kubernetesApiCallAction,
isnotempty(ServiceDetails.action.networkConnectionAction), ServiceDetails.action.networkConnectionAction,
isnotempty(ServiceDetails.action.rdsLoginAttemptAction), ServiceDetails.action.rdsLoginAttemptAction,
dynamic(null)
)
// The IPv4 remote address of the connection
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RemoteIpDetails.html
// or
// The IP of the Kubernetes API caller and the IPs of any proxies or load balancers between the caller and the API endpoint
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_KubernetesApiCallAction.html
| extend RemoteIpAddress =
coalesce(
tostring(ServiceAction.remoteIpDetails.ipAddressV4),
tostring(parse_json(ServiceAction.sourceIPs)[0])
)
// The IPv4 local address of the connection
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_LocalIpDetails.html
| extend LocalIpAddress = ServiceAction.localIpDetails.ipAddressV4
// The AWS account ID of the remote API caller.
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AwsApiCallAction.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RemoteAccountDetails.html
| extend RemoteAWSAccountId = ServiceAction.remoteAccountDetails.accountId
// The IAM access key details (user information) of a user that engaged in the activity that prompted GuardDuty to generate a finding
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AccessKeyDetails.html
| extend AccountUpn =
case(
AccessKeyDetails.userType == "IAMUser", AccessKeyDetails.userName,
AccessKeyDetails.userType == "AssumedRole", split(AccessKeyDetails.principalId, ":", 1)[0],
isnotempty(RdsDbUserDetails.user), RdsDbUserDetails.user,
isnotempty(KubernetesDetails.kubernetesUserDetails.username), KubernetesDetails.kubernetesUserDetails.username,
""
)
| extend AccountName = split(AccountUpn, "@", 0)[0]
| extend UPNSuffix = split(AccountUpn, "@", 1)[0]
// Clean up the output
| extend GuardDutyDetails =
bag_pack(
"DetectorId", ServiceDetails.detectorId,
"Partition", Partition,
"Region", Region
)
| extend FindingLink =
iff(
isnotempty(Region) and isnotempty(Id),
strcat("https://", Region, ".console.aws.amazon.com/guardduty/home?region=", Region, "#/findings?fId=", Id),
""
)
| extend FindingLinkDescription =
iff(
isnotempty(FindingLink),
strcat("Link to GuardDuty finding (AWS): ", FindingLink),
""
)
| project-rename
FindingArn=Arn,
FindingId=Id,
AWSAccountId=AccountId
| project-away
ActivityType,
findingTokens,
Partition,
Region,
SchemaVersion,
TimeGenerated,
Type
kind: Scheduled
relevantTechniques: []
description: Amazon GuardDuty is a threat detection service that continuously monitors your AWS accounts and workloads for malicious activity and delivers detailed security findings for visibility and remediation. This templates create an alert for each Amazon GuardDuty finding.
queryPeriod: 5h
queryFrequency: 5h
alertDetailsOverride:
alertSeverityColumnName: Severity
alertTacticsColumnName: ThreatPurpose
alertDisplayNameFormat: '{{Title}}'
alertDescriptionFormat: '{{Description}}'
tactics: []
name: AWS Guard Duty Alert
requiredDataConnectors:
- connectorId: AWSS3
dataTypes:
- AWSGuardDuty
customDetails:
ThreatPurpose: ThreatPurpose
DetectionMechanism: DetectionMechanism
ResourceTypeAffected: ResourceTypeAffected
ThreatFamilyName: ThreatFamilyName
Artifact: Artifact
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: UPNSuffix
- identifier: ObjectGuid
columnName: RemoteAWSAccountId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: RemoteIpAddress
- entityType: IP
fieldMappings:
- identifier: Address
columnName: LocalIpAddress
- entityType: URL
fieldMappings:
- identifier: Url
columnName: FindingLink
triggerThreshold: 0
version: 1.0.6
id: bf0cde21-0c41-48f6-a40c-6b5bd71fa106
query: |
// https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings.html
AWSGuardDuty
// Parse the finding
// https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-format.html
// Example: "ThreatPurpose:ResourceTypeAffected/ThreatFamilyName.DetectionMechanism!Artifact"
| extend findingTokens = split(ActivityType, ":")
| extend ThreatPurpose=findingTokens[0], findingTokens=split(findingTokens[1], "/")
| extend ResourceTypeAffected=findingTokens[0], findingTokens= split(findingTokens[1], ".")
| extend ThreatFamilyName=findingTokens[0], findingTokens=split(findingTokens[1], "!")
| extend DetectionMechanism=findingTokens[0], Artifact=findingTokens[1]
// Assign severity level
// https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings.html#guardduty_findings-severity
| extend Severity =
case (
Severity >= 7.0, "High",
Severity between (4.0 .. 6.9), "Medium",
Severity between (1.0 .. 3.9), "Low",
"Unknown"
)
// Pull out any available resource details we can extract entities from. These may not exist in the alert.
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_Resource.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AccessKeyDetails.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RdsDbUserDetails.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_KubernetesDetails.html
| extend AccessKeyDetails=ResourceDetails.accessKeyDetails
| extend RdsDbUserDetails=ResourceDetails.rdsDbUserDetails
| extend KubernetesDetails=ResourceDetails.kubernetesDetails
// Pull out any available action details we can extract entities from. These may not exist in the alert.
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_Action.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AwsApiCallAction.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_KubernetesApiCallAction.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_NetworkConnectionAction.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RdsLoginAttemptAction.html
| extend ServiceAction =
case(
isnotempty(ServiceDetails.action.awsApiCallAction), ServiceDetails.action.awsApiCallAction,
isnotempty(ServiceDetails.action.kubernetesApiCallAction), ServiceDetails.action.kubernetesApiCallAction,
isnotempty(ServiceDetails.action.networkConnectionAction), ServiceDetails.action.networkConnectionAction,
isnotempty(ServiceDetails.action.rdsLoginAttemptAction), ServiceDetails.action.rdsLoginAttemptAction,
dynamic(null)
)
// The IPv4 remote address of the connection
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RemoteIpDetails.html
// or
// The IP of the Kubernetes API caller and the IPs of any proxies or load balancers between the caller and the API endpoint
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_KubernetesApiCallAction.html
| extend RemoteIpAddress =
coalesce(
tostring(ServiceAction.remoteIpDetails.ipAddressV4),
tostring(parse_json(ServiceAction.sourceIPs)[0])
)
// The IPv4 local address of the connection
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_LocalIpDetails.html
| extend LocalIpAddress = ServiceAction.localIpDetails.ipAddressV4
// The AWS account ID of the remote API caller.
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AwsApiCallAction.html
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RemoteAccountDetails.html
| extend RemoteAWSAccountId = ServiceAction.remoteAccountDetails.accountId
// The IAM access key details (user information) of a user that engaged in the activity that prompted GuardDuty to generate a finding
// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AccessKeyDetails.html
| extend AccountUpn =
case(
AccessKeyDetails.userType == "IAMUser", AccessKeyDetails.userName,
AccessKeyDetails.userType == "AssumedRole", split(AccessKeyDetails.principalId, ":", 1)[0],
isnotempty(RdsDbUserDetails.user), RdsDbUserDetails.user,
isnotempty(KubernetesDetails.kubernetesUserDetails.username), KubernetesDetails.kubernetesUserDetails.username,
""
)
| extend AccountName = split(AccountUpn, "@", 0)[0]
| extend UPNSuffix = split(AccountUpn, "@", 1)[0]
// Clean up the output
| extend GuardDutyDetails =
bag_pack(
"DetectorId", ServiceDetails.detectorId,
"Partition", Partition,
"Region", Region
)
| extend FindingLink =
iff(
isnotempty(Region) and isnotempty(Id),
strcat("https://", Region, ".console.aws.amazon.com/guardduty/home?region=", Region, "#/findings?fId=", Id),
""
)
| extend FindingLinkDescription =
iff(
isnotempty(FindingLink),
strcat("Link to GuardDuty finding (AWS): ", FindingLink),
""
)
| project-rename
FindingArn=Arn,
FindingId=Id,
AWSAccountId=AccountId
| project-away
ActivityType,
findingTokens,
Partition,
Region,
SchemaVersion,
TimeGenerated,
Type
status: Available
triggerOperator: gt
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_GuardDuty_template.yaml
severity: Medium
{
"$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/bf0cde21-0c41-48f6-a40c-6b5bd71fa106')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/bf0cde21-0c41-48f6-a40c-6b5bd71fa106')]",
"properties": {
"alertDetailsOverride": {
"alertDescriptionFormat": "{{Description}}",
"alertDisplayNameFormat": "{{Title}}",
"alertSeverityColumnName": "Severity",
"alertTacticsColumnName": "ThreatPurpose"
},
"alertRuleTemplateName": "bf0cde21-0c41-48f6-a40c-6b5bd71fa106",
"customDetails": {
"Artifact": "Artifact",
"DetectionMechanism": "DetectionMechanism",
"ResourceTypeAffected": "ResourceTypeAffected",
"ThreatFamilyName": "ThreatFamilyName",
"ThreatPurpose": "ThreatPurpose"
},
"description": "Amazon GuardDuty is a threat detection service that continuously monitors your AWS accounts and workloads for malicious activity and delivers detailed security findings for visibility and remediation. This templates create an alert for each Amazon GuardDuty finding.",
"displayName": "AWS Guard Duty Alert",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "AccountName",
"identifier": "Name"
},
{
"columnName": "UPNSuffix",
"identifier": "UPNSuffix"
},
{
"columnName": "RemoteAWSAccountId",
"identifier": "ObjectGuid"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "RemoteIpAddress",
"identifier": "Address"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "LocalIpAddress",
"identifier": "Address"
}
]
},
{
"entityType": "URL",
"fieldMappings": [
{
"columnName": "FindingLink",
"identifier": "Url"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_GuardDuty_template.yaml",
"query": "// https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings.html \nAWSGuardDuty \n// Parse the finding\n// https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-format.html \n// Example: \"ThreatPurpose:ResourceTypeAffected/ThreatFamilyName.DetectionMechanism!Artifact\"\n| extend findingTokens = split(ActivityType, \":\")\n| extend ThreatPurpose=findingTokens[0], findingTokens=split(findingTokens[1], \"/\")\n| extend ResourceTypeAffected=findingTokens[0], findingTokens= split(findingTokens[1], \".\")\n| extend ThreatFamilyName=findingTokens[0], findingTokens=split(findingTokens[1], \"!\")\n| extend DetectionMechanism=findingTokens[0], Artifact=findingTokens[1]\n// Assign severity level\n// https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings.html#guardduty_findings-severity\n| extend Severity = \n case (\n Severity >= 7.0, \"High\",\n Severity between (4.0 .. 6.9), \"Medium\",\n Severity between (1.0 .. 3.9), \"Low\",\n \"Unknown\"\n )\n// Pull out any available resource details we can extract entities from. These may not exist in the alert.\n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_Resource.html \n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AccessKeyDetails.html \n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RdsDbUserDetails.html \n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_KubernetesDetails.html \n| extend AccessKeyDetails=ResourceDetails.accessKeyDetails\n| extend RdsDbUserDetails=ResourceDetails.rdsDbUserDetails\n| extend KubernetesDetails=ResourceDetails.kubernetesDetails\n// Pull out any available action details we can extract entities from. These may not exist in the alert.\n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_Action.html \n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AwsApiCallAction.html \n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_KubernetesApiCallAction.html \n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_NetworkConnectionAction.html \n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RdsLoginAttemptAction.html \n| extend ServiceAction = \n case(\n isnotempty(ServiceDetails.action.awsApiCallAction), ServiceDetails.action.awsApiCallAction,\n isnotempty(ServiceDetails.action.kubernetesApiCallAction), ServiceDetails.action.kubernetesApiCallAction,\n isnotempty(ServiceDetails.action.networkConnectionAction), ServiceDetails.action.networkConnectionAction,\n isnotempty(ServiceDetails.action.rdsLoginAttemptAction), ServiceDetails.action.rdsLoginAttemptAction,\n dynamic(null)\n )\n// The IPv4 remote address of the connection\n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RemoteIpDetails.html \n// or\n// The IP of the Kubernetes API caller and the IPs of any proxies or load balancers between the caller and the API endpoint \n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_KubernetesApiCallAction.html \n| extend RemoteIpAddress = \n coalesce(\n tostring(ServiceAction.remoteIpDetails.ipAddressV4),\n tostring(parse_json(ServiceAction.sourceIPs)[0])\n )\n// The IPv4 local address of the connection\n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_LocalIpDetails.html \n| extend LocalIpAddress = ServiceAction.localIpDetails.ipAddressV4\n// The AWS account ID of the remote API caller.\n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AwsApiCallAction.html \n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_RemoteAccountDetails.html \n| extend RemoteAWSAccountId = ServiceAction.remoteAccountDetails.accountId\n// The IAM access key details (user information) of a user that engaged in the activity that prompted GuardDuty to generate a finding\n// https://docs.aws.amazon.com/guardduty/latest/APIReference/API_AccessKeyDetails.html \n| extend AccountUpn = \n case(\n AccessKeyDetails.userType == \"IAMUser\", AccessKeyDetails.userName,\n AccessKeyDetails.userType == \"AssumedRole\", split(AccessKeyDetails.principalId, \":\", 1)[0],\n isnotempty(RdsDbUserDetails.user), RdsDbUserDetails.user,\n isnotempty(KubernetesDetails.kubernetesUserDetails.username), KubernetesDetails.kubernetesUserDetails.username,\n \"\"\n )\n| extend AccountName = split(AccountUpn, \"@\", 0)[0]\n| extend UPNSuffix = split(AccountUpn, \"@\", 1)[0]\n// Clean up the output\n| extend GuardDutyDetails =\n bag_pack( \n \"DetectorId\", ServiceDetails.detectorId,\n \"Partition\", Partition,\n \"Region\", Region\n )\n| extend FindingLink = \n iff(\n isnotempty(Region) and isnotempty(Id),\n strcat(\"https://\", Region, \".console.aws.amazon.com/guardduty/home?region=\", Region, \"#/findings?fId=\", Id),\n \"\"\n )\n| extend FindingLinkDescription = \n iff(\n isnotempty(FindingLink),\n strcat(\"Link to GuardDuty finding (AWS): \", FindingLink),\n \"\"\n )\n| project-rename \n FindingArn=Arn,\n FindingId=Id,\n AWSAccountId=AccountId\n| project-away \n ActivityType, \n findingTokens,\n Partition,\n Region, \n SchemaVersion,\n TimeGenerated,\n Type\n",
"queryFrequency": "PT5H",
"queryPeriod": "PT5H",
"severity": "Medium",
"status": "Available",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [],
"techniques": [],
"templateVersion": "1.0.6",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}