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

AWS Guard Duty Alert

Back
Idbf0cde21-0c41-48f6-a40c-6b5bd71fa106
RulenameAWS Guard Duty Alert
DescriptionAmazon 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.
SeverityMedium
Required data connectorsAWSS3
KindScheduled
Query frequency5h
Query period5h
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_GuardDuty_template.yaml
Version1.0.6
Arm templatebf0cde21-0c41-48f6-a40c-6b5bd71fa106.json
Deploy To Azure
// 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
relevantTechniques: []
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_GuardDuty_template.yaml
triggerOperator: gt
kind: Scheduled
entityMappings:
- fieldMappings:
  - columnName: AccountName
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
  - columnName: RemoteAWSAccountId
    identifier: ObjectGuid
  entityType: Account
- fieldMappings:
  - columnName: RemoteIpAddress
    identifier: Address
  entityType: IP
- fieldMappings:
  - columnName: LocalIpAddress
    identifier: Address
  entityType: IP
- fieldMappings:
  - columnName: FindingLink
    identifier: Url
  entityType: URL
requiredDataConnectors:
- dataTypes:
  - AWSGuardDuty
  connectorId: AWSS3
queryPeriod: 5h
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  
alertDetailsOverride:
  alertSeverityColumnName: Severity
  alertDisplayNameFormat: '{{Title}}'
  alertDescriptionFormat: '{{Description}}'
  alertTacticsColumnName: ThreatPurpose
version: 1.0.6
customDetails:
  Artifact: Artifact
  ThreatFamilyName: ThreatFamilyName
  DetectionMechanism: DetectionMechanism
  ThreatPurpose: ThreatPurpose
  ResourceTypeAffected: ResourceTypeAffected
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.
tactics: []
severity: Medium
name: AWS Guard Duty Alert
queryFrequency: 5h
triggerThreshold: 0
status: Available
id: bf0cde21-0c41-48f6-a40c-6b5bd71fa106
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2023-02-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",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [],
        "techniques": [],
        "templateVersion": "1.0.6",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}