Back
Idb442b9e2-5cc4-4129-a85b-a5ef38a9e5f0
RulenameAWSCloudTrail - S3 bucket suspicious ransomware activity
DescriptionDetects a ransomware-like sequence where objects are read from an S3 bucket and then overwritten using an

external KMS key. This pattern can indicate malicious encryption and potential data denial in the bucket.
SeverityHigh
TacticsImpact
TechniquesT1486
Required data connectorsAWS
KindScheduled
Query frequency1h
Query period1h
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon%20Web%20Services/Analytic%20Rules/AWS_S3Ransomware.yaml
Version1.0.2
Arm templateb442b9e2-5cc4-4129-a85b-a5ef38a9e5f0.json
Deploy To Azure
let timeframe = 1h;
let lookback = 2h;
// The attacker downloads the object(s) from the compromised bucket
let GetObject = AWSCloudTrail
| where TimeGenerated >= ago(lookback)
| where EventName == "GetObject" and isempty(ErrorCode) and isempty(ErrorMessage)
| extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)
| project-rename StartTime = TimeGenerated;
// Then, the attacker overwrites the same object(s) but encrypted with his own key
let PutObject = AWSCloudTrail
| where TimeGenerated >= ago(timeframe)
| where EventName == "PutObject" and isempty(ErrorCode) and isempty(ErrorMessage)
| extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)
| extend kmsId = tostring(parse_json(RequestParameters).["x-amz-server-side-encryption-aws-kms-key-id"])
| where tostring(kmsId) !has tostring(RecipientAccountId) and kmsId <> "";
PutObject
| join kind=inner 
(
   GetObject
)
on $left.bucketName == $right.bucketName, $left.keyName == $right.keyName
| where TimeGenerated > StartTime
| extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)
| extend UserName = tostring(split(UserIdentityArn, '/')[-1])
| extend AccountName = case( UserIdentityPrincipalid == "Anonymous", "Anonymous", isempty(UserIdentityUserName), UserName, UserIdentityUserName)
| extend AccountName = iif(AccountName contains "@", tostring(split(AccountName, '@', 0)[0]), AccountName),
  AccountUPNSuffix = iif(AccountName contains "@", tostring(split(AccountName, '@', 1)[0]), "")
name: AWSCloudTrail - S3 bucket suspicious ransomware activity
triggerOperator: gt
query: |
  let timeframe = 1h;
  let lookback = 2h;
  // The attacker downloads the object(s) from the compromised bucket
  let GetObject = AWSCloudTrail
  | where TimeGenerated >= ago(lookback)
  | where EventName == "GetObject" and isempty(ErrorCode) and isempty(ErrorMessage)
  | extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)
  | project-rename StartTime = TimeGenerated;
  // Then, the attacker overwrites the same object(s) but encrypted with his own key
  let PutObject = AWSCloudTrail
  | where TimeGenerated >= ago(timeframe)
  | where EventName == "PutObject" and isempty(ErrorCode) and isempty(ErrorMessage)
  | extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)
  | extend kmsId = tostring(parse_json(RequestParameters).["x-amz-server-side-encryption-aws-kms-key-id"])
  | where tostring(kmsId) !has tostring(RecipientAccountId) and kmsId <> "";
  PutObject
  | join kind=inner 
  (
     GetObject
  )
  on $left.bucketName == $right.bucketName, $left.keyName == $right.keyName
  | where TimeGenerated > StartTime
  | extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)
  | extend UserName = tostring(split(UserIdentityArn, '/')[-1])
  | extend AccountName = case( UserIdentityPrincipalid == "Anonymous", "Anonymous", isempty(UserIdentityUserName), UserName, UserIdentityUserName)
  | extend AccountName = iif(AccountName contains "@", tostring(split(AccountName, '@', 0)[0]), AccountName),
    AccountUPNSuffix = iif(AccountName contains "@", tostring(split(AccountName, '@', 1)[0]), "")
queryFrequency: 1h
description: |
  Detects a ransomware-like sequence where objects are read from an S3 bucket and then overwritten using an
  external KMS key. This pattern can indicate malicious encryption and potential data denial in the bucket.
id: b442b9e2-5cc4-4129-a85b-a5ef38a9e5f0
triggerThreshold: 0
queryPeriod: 1h
version: 1.0.2
kind: Scheduled
customDetails:
  RecipientAccountId: RecipientAccountId
  kmsId: kmsId
  bucketName: bucketName
  keyName: keyName
status: Available
severity: High
requiredDataConnectors:
- connectorId: AWS
  dataTypes:
  - AWSCloudTrail
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon%20Web%20Services/Analytic%20Rules/AWS_S3Ransomware.yaml
alertDetailsOverride:
  alertDescriptionFormat: Detected GetObject followed by encrypted PutObject activity in bucket {{bucketName}} from {{SourceIpAddress}} for account {{RecipientAccountId}}.
  alertDisplayNameFormat: AWS S3 ransomware-like overwrite activity by {{AccountName}}
relevantTechniques:
- T1486
tactics:
- Impact
entityMappings:
- fieldMappings:
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: AccountUPNSuffix
  - identifier: CloudAppAccountId
    columnName: RecipientAccountId
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: SourceIpAddress
  entityType: IP
{
  "$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/b442b9e2-5cc4-4129-a85b-a5ef38a9e5f0')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/b442b9e2-5cc4-4129-a85b-a5ef38a9e5f0')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "Detected GetObject followed by encrypted PutObject activity in bucket {{bucketName}} from {{SourceIpAddress}} for account {{RecipientAccountId}}.",
          "alertDisplayNameFormat": "AWS S3 ransomware-like overwrite activity by {{AccountName}}"
        },
        "alertRuleTemplateName": "b442b9e2-5cc4-4129-a85b-a5ef38a9e5f0",
        "customDetails": {
          "bucketName": "bucketName",
          "keyName": "keyName",
          "kmsId": "kmsId",
          "RecipientAccountId": "RecipientAccountId"
        },
        "description": "Detects a ransomware-like sequence where objects are read from an S3 bucket and then overwritten using an\nexternal KMS key. This pattern can indicate malicious encryption and potential data denial in the bucket.\n",
        "displayName": "AWSCloudTrail - S3 bucket suspicious ransomware activity",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "AccountUPNSuffix",
                "identifier": "UPNSuffix"
              },
              {
                "columnName": "RecipientAccountId",
                "identifier": "CloudAppAccountId"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SourceIpAddress",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon%20Web%20Services/Analytic%20Rules/AWS_S3Ransomware.yaml",
        "query": "let timeframe = 1h;\nlet lookback = 2h;\n// The attacker downloads the object(s) from the compromised bucket\nlet GetObject = AWSCloudTrail\n| where TimeGenerated >= ago(lookback)\n| where EventName == \"GetObject\" and isempty(ErrorCode) and isempty(ErrorMessage)\n| extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)\n| project-rename StartTime = TimeGenerated;\n// Then, the attacker overwrites the same object(s) but encrypted with his own key\nlet PutObject = AWSCloudTrail\n| where TimeGenerated >= ago(timeframe)\n| where EventName == \"PutObject\" and isempty(ErrorCode) and isempty(ErrorMessage)\n| extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)\n| extend kmsId = tostring(parse_json(RequestParameters).[\"x-amz-server-side-encryption-aws-kms-key-id\"])\n| where tostring(kmsId) !has tostring(RecipientAccountId) and kmsId <> \"\";\nPutObject\n| join kind=inner \n(\n   GetObject\n)\non $left.bucketName == $right.bucketName, $left.keyName == $right.keyName\n| where TimeGenerated > StartTime\n| extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)\n| extend UserName = tostring(split(UserIdentityArn, '/')[-1])\n| extend AccountName = case( UserIdentityPrincipalid == \"Anonymous\", \"Anonymous\", isempty(UserIdentityUserName), UserName, UserIdentityUserName)\n| extend AccountName = iif(AccountName contains \"@\", tostring(split(AccountName, '@', 0)[0]), AccountName),\n  AccountUPNSuffix = iif(AccountName contains \"@\", tostring(split(AccountName, '@', 1)[0]), \"\")\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "PT1H",
        "severity": "High",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Impact"
        ],
        "techniques": [
          "T1486"
        ],
        "templateVersion": "1.0.2",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}