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

External guest invitation followed by Microsoft Entra ID PowerShell signin

Back
Idacc4c247-aaf7-494b-b5da-17f18863878a
RulenameExternal guest invitation followed by Microsoft Entra ID PowerShell signin
DescriptionBy default guests have capability to invite more external guest users, guests also can do suspicious Microsoft Entra ID enumeration. This detection look at guests

users, who have been invited or have invited recently, who also are logging via various PowerShell CLI.

Ref : ‘https://danielchronlund.com/2021/11/18/scary-azure-ad-tenant-enumeration-using-regular-b2b-guest-accounts/
SeverityMedium
TacticsInitialAccess
Persistence
Discovery
TechniquesT1078.004
T1136.003
T1087.004
Required data connectorsAzureActiveDirectory
KindScheduled
Query frequency1h
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/UnusualGuestActivity.yaml
Version1.0.2
Arm templateacc4c247-aaf7-494b-b5da-17f18863878a.json
Deploy To Azure
let queryfrequency = 1h;
let queryperiod = 1d;
AuditLogs
| where TimeGenerated > ago(queryperiod)
| where OperationName in ("Invite external user", "Bulk invite users - started (bulk)", "Invite external user with reset invitation status")
| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))
| extend InitiatedBy = iff(isnotempty(InitiatingUserPrincipalName), InitiatingUserPrincipalName, InitiatingAppName)
// Uncomment the following line to filter events where the inviting user was a guest user
//| where InitiatedBy has_any ("live.com#", "#EXT#")
| mv-apply TargetResource = TargetResources on 
  (
      where TargetResource.type =~ "User"
      | extend InvitedUser = tostring(TargetResource.userPrincipalName)
  )
| mv-expand UserToCompare = pack_array(InitiatedBy, InvitedUser) to typeof(string)
| where UserToCompare has_any ("live.com#", "#EXT#")
| extend
    parsedUser = replace_string(tolower(iff(UserToCompare startswith "live.com#", tostring(split(UserToCompare, "#")[1]), tostring(split(UserToCompare, "#EXT#")[0]))), "@", "_"),
    InvitationTime = TimeGenerated
| join (
    (union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs)
    | where TimeGenerated > ago(queryfrequency)
    | where UserType != "Member"
    | where AppId has_any                       // This web may contain a list of these apps: https://msshells.net/
        ("1b730954-1685-4b74-9bfd-dac224a7b894",// Azure Active Directory PowerShell
         "04b07795-8ddb-461a-bbee-02f9e1bf7b46",// Microsoft Azure CLI
         "1950a258-227b-4e31-a9cf-717495945fc2",// Microsoft Azure PowerShell
         "a0c73c16-a7e3-4564-9a95-2bdf47383716",// Microsoft Exchange Online Remote PowerShell
         "fb78d390-0c51-40cd-8e17-fdbfab77341b",// Microsoft Exchange REST API Based Powershell
         "d1ddf0e4-d672-4dae-b554-9d5bdfd93547",// Microsoft Intune PowerShell
         "9bc3ab49-b65d-410a-85ad-de819febfddc",// Microsoft SharePoint Online Management Shell
         "12128f48-ec9e-42f0-b203-ea49fb6af367",// MS Teams Powershell Cmdlets
         "23d8f6bd-1eb0-4cc2-a08c-7bf525c67bcd",// Power BI PowerShell
         "31359c7f-bd7e-475c-86db-fdb8c937548e",// PnP Management Shell
         "90f610bf-206d-4950-b61d-37fa6fd1b224",// Aadrm Admin Powershell
         "14d82eec-204b-4c2f-b7e8-296a70dab67e",// Microsoft Graph PowerShell
         "9cee029c-6210-4654-90bb-17e6e9d36617" // Power Platform CLI - pac"
        )
    | summarize arg_min(TimeGenerated, *) by UserPrincipalName
    | extend
        parsedUser = replace_string(UserPrincipalName, "@", "_"),
        SigninTime = TimeGenerated
    )
    on parsedUser
| project InvitationTime, InitiatedBy, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingIpAddress, OperationName, InvitedUser, SigninTime, SigninCategory = Category1, SigninUserPrincipalName = UserPrincipalName, AppDisplayName, ResourceDisplayName, UserAgent, InvitationAdditionalDetails = AdditionalDetails, InvitationTargetResources = TargetResources
| extend InvitedUserName = tostring(split(InvitedUser,'@',0)[0]), InvitedUserUPNSuffix = tostring(split(InvitedUser,'@',1)[0]), 
         InitiatedByName = tostring(split(InitiatingUserPrincipalName,'@',0)[0]), InitiatedByUPNSuffix = tostring(split(InitiatingUserPrincipalName,'@',1)[0])
queryPeriod: 1d
version: 1.0.2
kind: Scheduled
triggerThreshold: 0
relevantTechniques:
- T1078.004
- T1136.003
- T1087.004
triggerOperator: gt
entityMappings:
- fieldMappings:
  - identifier: FullName
    columnName: InvitedUser
  - identifier: Name
    columnName: InvitedUserName
  - identifier: UPNSuffix
    columnName: InvitedUserUPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: FullName
    columnName: InitiatingUserPrincipalName
  - identifier: Name
    columnName: InitiatedByName
  - identifier: UPNSuffix
    columnName: InitiatedByUPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: AadUserId
    columnName: InitiatingAadUserId
  entityType: Account
- fieldMappings:
  - identifier: AadUserId
    columnName: InitiatingAppServicePrincipalId
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: InitiatingIpAddress
  entityType: IP
query: |
  let queryfrequency = 1h;
  let queryperiod = 1d;
  AuditLogs
  | where TimeGenerated > ago(queryperiod)
  | where OperationName in ("Invite external user", "Bulk invite users - started (bulk)", "Invite external user with reset invitation status")
  | extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
  | extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
  | extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
  | extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
  | extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))
  | extend InitiatedBy = iff(isnotempty(InitiatingUserPrincipalName), InitiatingUserPrincipalName, InitiatingAppName)
  // Uncomment the following line to filter events where the inviting user was a guest user
  //| where InitiatedBy has_any ("live.com#", "#EXT#")
  | mv-apply TargetResource = TargetResources on 
    (
        where TargetResource.type =~ "User"
        | extend InvitedUser = tostring(TargetResource.userPrincipalName)
    )
  | mv-expand UserToCompare = pack_array(InitiatedBy, InvitedUser) to typeof(string)
  | where UserToCompare has_any ("live.com#", "#EXT#")
  | extend
      parsedUser = replace_string(tolower(iff(UserToCompare startswith "live.com#", tostring(split(UserToCompare, "#")[1]), tostring(split(UserToCompare, "#EXT#")[0]))), "@", "_"),
      InvitationTime = TimeGenerated
  | join (
      (union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs)
      | where TimeGenerated > ago(queryfrequency)
      | where UserType != "Member"
      | where AppId has_any                       // This web may contain a list of these apps: https://msshells.net/
          ("1b730954-1685-4b74-9bfd-dac224a7b894",// Azure Active Directory PowerShell
           "04b07795-8ddb-461a-bbee-02f9e1bf7b46",// Microsoft Azure CLI
           "1950a258-227b-4e31-a9cf-717495945fc2",// Microsoft Azure PowerShell
           "a0c73c16-a7e3-4564-9a95-2bdf47383716",// Microsoft Exchange Online Remote PowerShell
           "fb78d390-0c51-40cd-8e17-fdbfab77341b",// Microsoft Exchange REST API Based Powershell
           "d1ddf0e4-d672-4dae-b554-9d5bdfd93547",// Microsoft Intune PowerShell
           "9bc3ab49-b65d-410a-85ad-de819febfddc",// Microsoft SharePoint Online Management Shell
           "12128f48-ec9e-42f0-b203-ea49fb6af367",// MS Teams Powershell Cmdlets
           "23d8f6bd-1eb0-4cc2-a08c-7bf525c67bcd",// Power BI PowerShell
           "31359c7f-bd7e-475c-86db-fdb8c937548e",// PnP Management Shell
           "90f610bf-206d-4950-b61d-37fa6fd1b224",// Aadrm Admin Powershell
           "14d82eec-204b-4c2f-b7e8-296a70dab67e",// Microsoft Graph PowerShell
           "9cee029c-6210-4654-90bb-17e6e9d36617" // Power Platform CLI - pac"
          )
      | summarize arg_min(TimeGenerated, *) by UserPrincipalName
      | extend
          parsedUser = replace_string(UserPrincipalName, "@", "_"),
          SigninTime = TimeGenerated
      )
      on parsedUser
  | project InvitationTime, InitiatedBy, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingIpAddress, OperationName, InvitedUser, SigninTime, SigninCategory = Category1, SigninUserPrincipalName = UserPrincipalName, AppDisplayName, ResourceDisplayName, UserAgent, InvitationAdditionalDetails = AdditionalDetails, InvitationTargetResources = TargetResources
  | extend InvitedUserName = tostring(split(InvitedUser,'@',0)[0]), InvitedUserUPNSuffix = tostring(split(InvitedUser,'@',1)[0]), 
           InitiatedByName = tostring(split(InitiatingUserPrincipalName,'@',0)[0]), InitiatedByUPNSuffix = tostring(split(InitiatingUserPrincipalName,'@',1)[0])  
name: External guest invitation followed by Microsoft Entra ID PowerShell signin
queryFrequency: 1h
requiredDataConnectors:
- connectorId: AzureActiveDirectory
  dataTypes:
  - AuditLogs
- connectorId: AzureActiveDirectory
  dataTypes:
  - SigninLogs
description: |
  'By default guests have capability to invite more external guest users, guests also can do suspicious Microsoft Entra ID enumeration. This detection look at guests
  users, who have been invited or have invited recently, who also are logging via various PowerShell CLI.
  Ref : 'https://danielchronlund.com/2021/11/18/scary-azure-ad-tenant-enumeration-using-regular-b2b-guest-accounts/'  
status: Available
id: acc4c247-aaf7-494b-b5da-17f18863878a
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/UnusualGuestActivity.yaml
tactics:
- InitialAccess
- Persistence
- Discovery
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": "2023-02-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/acc4c247-aaf7-494b-b5da-17f18863878a')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/acc4c247-aaf7-494b-b5da-17f18863878a')]",
      "properties": {
        "alertRuleTemplateName": "acc4c247-aaf7-494b-b5da-17f18863878a",
        "customDetails": null,
        "description": "'By default guests have capability to invite more external guest users, guests also can do suspicious Microsoft Entra ID enumeration. This detection look at guests\nusers, who have been invited or have invited recently, who also are logging via various PowerShell CLI.\nRef : 'https://danielchronlund.com/2021/11/18/scary-azure-ad-tenant-enumeration-using-regular-b2b-guest-accounts/'\n",
        "displayName": "External guest invitation followed by Microsoft Entra ID PowerShell signin",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "InvitedUser",
                "identifier": "FullName"
              },
              {
                "columnName": "InvitedUserName",
                "identifier": "Name"
              },
              {
                "columnName": "InvitedUserUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "InitiatingUserPrincipalName",
                "identifier": "FullName"
              },
              {
                "columnName": "InitiatedByName",
                "identifier": "Name"
              },
              {
                "columnName": "InitiatedByUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "InitiatingAadUserId",
                "identifier": "AadUserId"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "InitiatingAppServicePrincipalId",
                "identifier": "AadUserId"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "InitiatingIpAddress",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/UnusualGuestActivity.yaml",
        "query": "let queryfrequency = 1h;\nlet queryperiod = 1d;\nAuditLogs\n| where TimeGenerated > ago(queryperiod)\n| where OperationName in (\"Invite external user\", \"Bulk invite users - started (bulk)\", \"Invite external user with reset invitation status\")\n| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)\n| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)\n| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)\n| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)\n| extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))\n| extend InitiatedBy = iff(isnotempty(InitiatingUserPrincipalName), InitiatingUserPrincipalName, InitiatingAppName)\n// Uncomment the following line to filter events where the inviting user was a guest user\n//| where InitiatedBy has_any (\"live.com#\", \"#EXT#\")\n| mv-apply TargetResource = TargetResources on \n  (\n      where TargetResource.type =~ \"User\"\n      | extend InvitedUser = tostring(TargetResource.userPrincipalName)\n  )\n| mv-expand UserToCompare = pack_array(InitiatedBy, InvitedUser) to typeof(string)\n| where UserToCompare has_any (\"live.com#\", \"#EXT#\")\n| extend\n    parsedUser = replace_string(tolower(iff(UserToCompare startswith \"live.com#\", tostring(split(UserToCompare, \"#\")[1]), tostring(split(UserToCompare, \"#EXT#\")[0]))), \"@\", \"_\"),\n    InvitationTime = TimeGenerated\n| join (\n    (union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs)\n    | where TimeGenerated > ago(queryfrequency)\n    | where UserType != \"Member\"\n    | where AppId has_any                       // This web may contain a list of these apps: https://msshells.net/\n        (\"1b730954-1685-4b74-9bfd-dac224a7b894\",// Azure Active Directory PowerShell\n         \"04b07795-8ddb-461a-bbee-02f9e1bf7b46\",// Microsoft Azure CLI\n         \"1950a258-227b-4e31-a9cf-717495945fc2\",// Microsoft Azure PowerShell\n         \"a0c73c16-a7e3-4564-9a95-2bdf47383716\",// Microsoft Exchange Online Remote PowerShell\n         \"fb78d390-0c51-40cd-8e17-fdbfab77341b\",// Microsoft Exchange REST API Based Powershell\n         \"d1ddf0e4-d672-4dae-b554-9d5bdfd93547\",// Microsoft Intune PowerShell\n         \"9bc3ab49-b65d-410a-85ad-de819febfddc\",// Microsoft SharePoint Online Management Shell\n         \"12128f48-ec9e-42f0-b203-ea49fb6af367\",// MS Teams Powershell Cmdlets\n         \"23d8f6bd-1eb0-4cc2-a08c-7bf525c67bcd\",// Power BI PowerShell\n         \"31359c7f-bd7e-475c-86db-fdb8c937548e\",// PnP Management Shell\n         \"90f610bf-206d-4950-b61d-37fa6fd1b224\",// Aadrm Admin Powershell\n         \"14d82eec-204b-4c2f-b7e8-296a70dab67e\",// Microsoft Graph PowerShell\n         \"9cee029c-6210-4654-90bb-17e6e9d36617\" // Power Platform CLI - pac\"\n        )\n    | summarize arg_min(TimeGenerated, *) by UserPrincipalName\n    | extend\n        parsedUser = replace_string(UserPrincipalName, \"@\", \"_\"),\n        SigninTime = TimeGenerated\n    )\n    on parsedUser\n| project InvitationTime, InitiatedBy, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingIpAddress, OperationName, InvitedUser, SigninTime, SigninCategory = Category1, SigninUserPrincipalName = UserPrincipalName, AppDisplayName, ResourceDisplayName, UserAgent, InvitationAdditionalDetails = AdditionalDetails, InvitationTargetResources = TargetResources\n| extend InvitedUserName = tostring(split(InvitedUser,'@',0)[0]), InvitedUserUPNSuffix = tostring(split(InvitedUser,'@',1)[0]), \n         InitiatedByName = tostring(split(InitiatingUserPrincipalName,'@',0)[0]), InitiatedByUPNSuffix = tostring(split(InitiatingUserPrincipalName,'@',1)[0])\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "status": "Available",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Discovery",
          "InitialAccess",
          "Persistence"
        ],
        "techniques": [
          "T1078",
          "T1087",
          "T1136"
        ],
        "templateVersion": "1.0.2",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}