Account Created and Deleted in Short Timeframe
| Id | bb616d82-108f-47d3-9dec-9652ea0d3bf6 | 
| Rulename | Account Created and Deleted in Short Timeframe | 
| Description | Search for user principal name (UPN) events. Look for accounts created and then deleted in under 24 hours. Attackers may create an account for their use, and then remove the account when no longer needed. Ref : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#short-lived-account  | 
| Severity | High | 
| Tactics | InitialAccess | 
| Techniques | T1078.004 | 
| Required data connectors | AzureActiveDirectory | 
| Kind | Scheduled | 
| Query frequency | 1h | 
| Query period | 1d | 
| Trigger threshold | 0 | 
| Trigger operator | gt | 
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedandDeletedinShortTimeframe.yaml | 
| Version | 1.1.0 | 
| Arm template | bb616d82-108f-47d3-9dec-9652ea0d3bf6.json | 
let queryfrequency = 1h;
let queryperiod = 1d;
AuditLogs
| where TimeGenerated > ago(queryfrequency)
| where OperationName =~ "Delete user"
| mv-apply TargetResource = TargetResources on 
  (
      where TargetResource.type == "User"
      | extend TargetUserPrincipalName = extract(@'([a-f0-9]{32})?(.*)', 2, tostring(TargetResource.userPrincipalName))
  )
| extend DeletedByApp = tostring(InitiatedBy.app.displayName),
DeletedByAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId),
DeletedByUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName),
DeletedByAadUserId = tostring(InitiatedBy.user.id),
DeletedByIPAddress = tostring(InitiatedBy.user.ipAddress)
| project Deletion_TimeGenerated = TimeGenerated, TargetUserPrincipalName, DeletedByApp, DeletedByAppServicePrincipalId, DeletedByUserPrincipalName, DeletedByAadUserId, DeletedByIPAddress, 
Deletion_AdditionalDetails = AdditionalDetails, Deletion_InitiatedBy = InitiatedBy, Deletion_TargetResources = TargetResources
| join kind=inner (
    AuditLogs
    | where TimeGenerated > ago(queryperiod)
    | where OperationName =~ "Add user"      
    | mv-apply TargetResource = TargetResources on 
      (
          where TargetResource.type == "User"
          | extend TargetUserPrincipalName = trim(@'"',tostring(TargetResource.userPrincipalName))
      )
    | project-rename Creation_TimeGenerated = TimeGenerated
) on TargetUserPrincipalName
| extend TimeDelta = Deletion_TimeGenerated - Creation_TimeGenerated
| where  TimeDelta between (time(0s) .. queryperiod)
| extend CreatedByApp = tostring(InitiatedBy.app.displayName),
CreatedByAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId),
CreatedByUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName),
CreatedByAadUserId = tostring(InitiatedBy.user.id),
CreatedByIPAddress = tostring(InitiatedBy.user.ipAddress)
| project Creation_TimeGenerated, Deletion_TimeGenerated, TimeDelta, TargetUserPrincipalName, DeletedByApp, DeletedByAppServicePrincipalId, DeletedByUserPrincipalName, DeletedByAadUserId, DeletedByIPAddress, 
CreatedByApp, CreatedByAppServicePrincipalId, CreatedByUserPrincipalName, CreatedByAadUserId, CreatedByIPAddress, Creation_AdditionalDetails = AdditionalDetails, Creation_InitiatedBy = InitiatedBy, Creation_TargetResources = TargetResources, Deletion_AdditionalDetails, Deletion_InitiatedBy, Deletion_TargetResources
| extend TargetName = tostring(split(TargetUserPrincipalName,'@',0)[0]), TargetUPNSuffix = tostring(split(TargetUserPrincipalName,'@',1)[0])
| extend CreatedByName = tostring(split(CreatedByUserPrincipalName,'@',0)[0]), CreatedByUPNSuffix = tostring(split(CreatedByUserPrincipalName,'@',1)[0])
| extend DeletedByName = tostring(split(DeletedByUserPrincipalName,'@',0)[0]), DeletedByUPNSuffix = tostring(split(DeletedByUserPrincipalName,'@',1)[0])
kind: Scheduled
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: TargetUserPrincipalName
    identifier: FullName
  - columnName: TargetName
    identifier: Name
  - columnName: TargetUPNSuffix
    identifier: UPNSuffix
- entityType: Account
  fieldMappings:
  - columnName: CreatedByUserPrincipalName
    identifier: FullName
  - columnName: CreatedByName
    identifier: Name
  - columnName: CreatedByUPNSuffix
    identifier: UPNSuffix
- entityType: Account
  fieldMappings:
  - columnName: CreatedByAadUserId
    identifier: AadUserId
- entityType: Account
  fieldMappings:
  - columnName: DeletedByUserPrincipalName
    identifier: FullName
  - columnName: DeletedByName
    identifier: Name
  - columnName: DeletedByUPNSuffix
    identifier: UPNSuffix
- entityType: Account
  fieldMappings:
  - columnName: DeletedByAadUserId
    identifier: AadUserId
- entityType: IP
  fieldMappings:
  - columnName: CreatedByIPAddress
    identifier: Address
- entityType: IP
  fieldMappings:
  - columnName: DeletedByIPAddress
    identifier: Address
description: |
  'Search for user principal name (UPN) events. Look for accounts created and then deleted in under 24 hours. Attackers may create an account for their use, and then remove the account when no longer needed.
  Ref : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#short-lived-account'  
severity: High
queryFrequency: 1h
triggerThreshold: 0
relevantTechniques:
- T1078.004
tags:
- AADSecOpsGuide
status: Available
tactics:
- InitialAccess
name: Account Created and Deleted in Short Timeframe
id: bb616d82-108f-47d3-9dec-9652ea0d3bf6
query: |
  let queryfrequency = 1h;
  let queryperiod = 1d;
  AuditLogs
  | where TimeGenerated > ago(queryfrequency)
  | where OperationName =~ "Delete user"
  | mv-apply TargetResource = TargetResources on 
    (
        where TargetResource.type == "User"
        | extend TargetUserPrincipalName = extract(@'([a-f0-9]{32})?(.*)', 2, tostring(TargetResource.userPrincipalName))
    )
  | extend DeletedByApp = tostring(InitiatedBy.app.displayName),
  DeletedByAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId),
  DeletedByUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName),
  DeletedByAadUserId = tostring(InitiatedBy.user.id),
  DeletedByIPAddress = tostring(InitiatedBy.user.ipAddress)
  | project Deletion_TimeGenerated = TimeGenerated, TargetUserPrincipalName, DeletedByApp, DeletedByAppServicePrincipalId, DeletedByUserPrincipalName, DeletedByAadUserId, DeletedByIPAddress, 
  Deletion_AdditionalDetails = AdditionalDetails, Deletion_InitiatedBy = InitiatedBy, Deletion_TargetResources = TargetResources
  | join kind=inner (
      AuditLogs
      | where TimeGenerated > ago(queryperiod)
      | where OperationName =~ "Add user"      
      | mv-apply TargetResource = TargetResources on 
        (
            where TargetResource.type == "User"
            | extend TargetUserPrincipalName = trim(@'"',tostring(TargetResource.userPrincipalName))
        )
      | project-rename Creation_TimeGenerated = TimeGenerated
  ) on TargetUserPrincipalName
  | extend TimeDelta = Deletion_TimeGenerated - Creation_TimeGenerated
  | where  TimeDelta between (time(0s) .. queryperiod)
  | extend CreatedByApp = tostring(InitiatedBy.app.displayName),
  CreatedByAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId),
  CreatedByUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName),
  CreatedByAadUserId = tostring(InitiatedBy.user.id),
  CreatedByIPAddress = tostring(InitiatedBy.user.ipAddress)
  | project Creation_TimeGenerated, Deletion_TimeGenerated, TimeDelta, TargetUserPrincipalName, DeletedByApp, DeletedByAppServicePrincipalId, DeletedByUserPrincipalName, DeletedByAadUserId, DeletedByIPAddress, 
  CreatedByApp, CreatedByAppServicePrincipalId, CreatedByUserPrincipalName, CreatedByAadUserId, CreatedByIPAddress, Creation_AdditionalDetails = AdditionalDetails, Creation_InitiatedBy = InitiatedBy, Creation_TargetResources = TargetResources, Deletion_AdditionalDetails, Deletion_InitiatedBy, Deletion_TargetResources
  | extend TargetName = tostring(split(TargetUserPrincipalName,'@',0)[0]), TargetUPNSuffix = tostring(split(TargetUserPrincipalName,'@',1)[0])
  | extend CreatedByName = tostring(split(CreatedByUserPrincipalName,'@',0)[0]), CreatedByUPNSuffix = tostring(split(CreatedByUserPrincipalName,'@',1)[0])
  | extend DeletedByName = tostring(split(DeletedByUserPrincipalName,'@',0)[0]), DeletedByUPNSuffix = tostring(split(DeletedByUserPrincipalName,'@',1)[0])  
requiredDataConnectors:
- dataTypes:
  - SigninLogs
  connectorId: AzureActiveDirectory
version: 1.1.0
triggerOperator: gt
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedandDeletedinShortTimeframe.yaml
queryPeriod: 1d
{
  "$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/bb616d82-108f-47d3-9dec-9652ea0d3bf6')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/bb616d82-108f-47d3-9dec-9652ea0d3bf6')]",
      "properties": {
        "alertRuleTemplateName": "bb616d82-108f-47d3-9dec-9652ea0d3bf6",
        "customDetails": null,
        "description": "'Search for user principal name (UPN) events. Look for accounts created and then deleted in under 24 hours. Attackers may create an account for their use, and then remove the account when no longer needed.\nRef : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#short-lived-account'\n",
        "displayName": "Account Created and Deleted in Short Timeframe",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "TargetUserPrincipalName",
                "identifier": "FullName"
              },
              {
                "columnName": "TargetName",
                "identifier": "Name"
              },
              {
                "columnName": "TargetUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "CreatedByUserPrincipalName",
                "identifier": "FullName"
              },
              {
                "columnName": "CreatedByName",
                "identifier": "Name"
              },
              {
                "columnName": "CreatedByUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "CreatedByAadUserId",
                "identifier": "AadUserId"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "DeletedByUserPrincipalName",
                "identifier": "FullName"
              },
              {
                "columnName": "DeletedByName",
                "identifier": "Name"
              },
              {
                "columnName": "DeletedByUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "DeletedByAadUserId",
                "identifier": "AadUserId"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "CreatedByIPAddress",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "DeletedByIPAddress",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedandDeletedinShortTimeframe.yaml",
        "query": "let queryfrequency = 1h;\nlet queryperiod = 1d;\nAuditLogs\n| where TimeGenerated > ago(queryfrequency)\n| where OperationName =~ \"Delete user\"\n| mv-apply TargetResource = TargetResources on \n  (\n      where TargetResource.type == \"User\"\n      | extend TargetUserPrincipalName = extract(@'([a-f0-9]{32})?(.*)', 2, tostring(TargetResource.userPrincipalName))\n  )\n| extend DeletedByApp = tostring(InitiatedBy.app.displayName),\nDeletedByAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId),\nDeletedByUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName),\nDeletedByAadUserId = tostring(InitiatedBy.user.id),\nDeletedByIPAddress = tostring(InitiatedBy.user.ipAddress)\n| project Deletion_TimeGenerated = TimeGenerated, TargetUserPrincipalName, DeletedByApp, DeletedByAppServicePrincipalId, DeletedByUserPrincipalName, DeletedByAadUserId, DeletedByIPAddress, \nDeletion_AdditionalDetails = AdditionalDetails, Deletion_InitiatedBy = InitiatedBy, Deletion_TargetResources = TargetResources\n| join kind=inner (\n    AuditLogs\n    | where TimeGenerated > ago(queryperiod)\n    | where OperationName =~ \"Add user\"      \n    | mv-apply TargetResource = TargetResources on \n      (\n          where TargetResource.type == \"User\"\n          | extend TargetUserPrincipalName = trim(@'\"',tostring(TargetResource.userPrincipalName))\n      )\n    | project-rename Creation_TimeGenerated = TimeGenerated\n) on TargetUserPrincipalName\n| extend TimeDelta = Deletion_TimeGenerated - Creation_TimeGenerated\n| where  TimeDelta between (time(0s) .. queryperiod)\n| extend CreatedByApp = tostring(InitiatedBy.app.displayName),\nCreatedByAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId),\nCreatedByUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName),\nCreatedByAadUserId = tostring(InitiatedBy.user.id),\nCreatedByIPAddress = tostring(InitiatedBy.user.ipAddress)\n| project Creation_TimeGenerated, Deletion_TimeGenerated, TimeDelta, TargetUserPrincipalName, DeletedByApp, DeletedByAppServicePrincipalId, DeletedByUserPrincipalName, DeletedByAadUserId, DeletedByIPAddress, \nCreatedByApp, CreatedByAppServicePrincipalId, CreatedByUserPrincipalName, CreatedByAadUserId, CreatedByIPAddress, Creation_AdditionalDetails = AdditionalDetails, Creation_InitiatedBy = InitiatedBy, Creation_TargetResources = TargetResources, Deletion_AdditionalDetails, Deletion_InitiatedBy, Deletion_TargetResources\n| extend TargetName = tostring(split(TargetUserPrincipalName,'@',0)[0]), TargetUPNSuffix = tostring(split(TargetUserPrincipalName,'@',1)[0])\n| extend CreatedByName = tostring(split(CreatedByUserPrincipalName,'@',0)[0]), CreatedByUPNSuffix = tostring(split(CreatedByUserPrincipalName,'@',1)[0])\n| extend DeletedByName = tostring(split(DeletedByUserPrincipalName,'@',0)[0]), DeletedByUPNSuffix = tostring(split(DeletedByUserPrincipalName,'@',1)[0])\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P1D",
        "severity": "High",
        "status": "Available",
        "subTechniques": [
          "T1078.004"
        ],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "InitialAccess"
        ],
        "tags": [
          "AADSecOpsGuide"
        ],
        "techniques": [
          "T1078"
        ],
        "templateVersion": "1.1.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}