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

GSA Enriched Office 365 - Office Policy Tampering

Back
Id0f1f2b17-f9d6-4d2a-a0fb-a7ae1659e3eb
RulenameGSA Enriched Office 365 - Office Policy Tampering
DescriptionIdentifies if any tampering is done to either audit log, ATP Safelink, SafeAttachment, AntiPhish, or Dlp policy.

An adversary may use this technique to evade detection or avoid other policy-based defenses.

References: https://docs.microsoft.com/powershell/module/exchange/advanced-threat-protection/remove-antiphishrule?view=exchange-ps.
SeverityMedium
TacticsPersistence
DefenseEvasion
TechniquesT1098
T1562
Required data connectorsAzureActiveDirectory
Office365
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - office_policytampering.yaml
Version2.0.6
Arm template0f1f2b17-f9d6-4d2a-a0fb-a7ae1659e3eb.json
Deploy To Azure
// Query for EnrichedMicrosoft365AuditLogs
let enrichedOpList = EnrichedMicrosoft365AuditLogs 
    | summarize by Operation
    | where Operation has_any ("Remove", "Disable")
    | where Operation contains "AntiPhish" 
        or Operation contains "SafeAttachment" 
        or Operation contains "SafeLinks" 
        or Operation contains "Dlp" 
        or Operation contains "Audit"
    | summarize make_set(Operation, 500);

let enrichedLogs = EnrichedMicrosoft365AuditLogs
    | where RecordType == "ExchangeAdmin"
    | where UserType in~ ("Admin", "DcAdmin")
    | where Operation in~ (enrichedOpList)
    | extend ClientIPOnly = case( 
        ClientIp has ".", tostring(split(ClientIp, ":")[0]), 
        ClientIp has "[", tostring(trim_start(@'[[]', tostring(split(ClientIp, "]")[0]))),
        ClientIp
      )  
    | extend Port = case(
        ClientIp has ".", tostring(split(ClientIp, ":")[1]),
        ClientIp has "[", tostring(split(ClientIp, "]:")[1]),
        ""
      )
    | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), OperationCount = count() 
        by Operation, UserType, UserId, ClientIP = ClientIPOnly, Port, ResultStatus, Parameters = tostring(AdditionalProperties.Parameters)
    | extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1]);

// Query for OfficeActivity
let officeOpList = OfficeActivity 
    | summarize by Operation
    | where Operation has_any ("Remove", "Disable")
    | where Operation contains "AntiPhish" 
        or Operation contains "SafeAttachment" 
        or Operation contains "SafeLinks" 
        or Operation contains "Dlp" 
        or Operation contains "Audit"
    | summarize make_set(Operation, 500);

let officeLogs = OfficeActivity
    | where RecordType =~ "ExchangeAdmin"
    | where UserType in~ ("Admin","DcAdmin")
    | where Operation in~ (officeOpList)
    | extend ClientIPOnly = case( 
        ClientIP has ".", tostring(split(ClientIP,":")[0]), 
        ClientIP has "[", tostring(trim_start(@'[[]', tostring(split(ClientIP,"]")[0]))),
        ClientIP
      )  
    | extend Port = case(
        ClientIP has ".", tostring(split(ClientIP,":")[1]),
        ClientIP has "[", tostring(split(ClientIP, "]:")[1]),
        ""
      )
    | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), OperationCount = count() 
        by Operation, UserType, UserId, ClientIP = ClientIPOnly, Port, ResultStatus, Parameters
    | extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1]);

// Combine Enriched Logs and Office Activity Logs
union isfuzzy=true enrichedLogs, officeLogs
| summarize StartTimeUtc = min(StartTimeUtc), EndTimeUtc = max(EndTimeUtc), TotalOperationCount = sum(OperationCount) 
    by Operation, UserType, UserId, ClientIP, Port, ResultStatus, Parameters, AccountName, AccountUPNSuffix
| order by StartTimeUtc desc;
status: Available
triggerOperator: gt
triggerThreshold: 0
name: GSA Enriched Office 365 - Office Policy Tampering
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - office_policytampering.yaml
queryPeriod: 1d
severity: Medium
kind: Scheduled
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: UserId
    identifier: FullName
  - columnName: AccountName
    identifier: Name
  - columnName: AccountUPNSuffix
    identifier: UPNSuffix
- entityType: IP
  fieldMappings:
  - columnName: ClientIP
    identifier: Address
queryFrequency: 1d
relevantTechniques:
- T1098
- T1562
requiredDataConnectors:
- dataTypes:
  - EnrichedMicrosoft365AuditLogs
  connectorId: AzureActiveDirectory
- dataTypes:
  - OfficeActivity (Exchange)
  connectorId: Office365
description: |
  Identifies if any tampering is done to either audit log, ATP Safelink, SafeAttachment, AntiPhish, or Dlp policy. 
  An adversary may use this technique to evade detection or avoid other policy-based defenses.
  References: https://docs.microsoft.com/powershell/module/exchange/advanced-threat-protection/remove-antiphishrule?view=exchange-ps.  
tactics:
- Persistence
- DefenseEvasion
query: |
  // Query for EnrichedMicrosoft365AuditLogs
  let enrichedOpList = EnrichedMicrosoft365AuditLogs 
      | summarize by Operation
      | where Operation has_any ("Remove", "Disable")
      | where Operation contains "AntiPhish" 
          or Operation contains "SafeAttachment" 
          or Operation contains "SafeLinks" 
          or Operation contains "Dlp" 
          or Operation contains "Audit"
      | summarize make_set(Operation, 500);

  let enrichedLogs = EnrichedMicrosoft365AuditLogs
      | where RecordType == "ExchangeAdmin"
      | where UserType in~ ("Admin", "DcAdmin")
      | where Operation in~ (enrichedOpList)
      | extend ClientIPOnly = case( 
          ClientIp has ".", tostring(split(ClientIp, ":")[0]), 
          ClientIp has "[", tostring(trim_start(@'[[]', tostring(split(ClientIp, "]")[0]))),
          ClientIp
        )  
      | extend Port = case(
          ClientIp has ".", tostring(split(ClientIp, ":")[1]),
          ClientIp has "[", tostring(split(ClientIp, "]:")[1]),
          ""
        )
      | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), OperationCount = count() 
          by Operation, UserType, UserId, ClientIP = ClientIPOnly, Port, ResultStatus, Parameters = tostring(AdditionalProperties.Parameters)
      | extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1]);

  // Query for OfficeActivity
  let officeOpList = OfficeActivity 
      | summarize by Operation
      | where Operation has_any ("Remove", "Disable")
      | where Operation contains "AntiPhish" 
          or Operation contains "SafeAttachment" 
          or Operation contains "SafeLinks" 
          or Operation contains "Dlp" 
          or Operation contains "Audit"
      | summarize make_set(Operation, 500);

  let officeLogs = OfficeActivity
      | where RecordType =~ "ExchangeAdmin"
      | where UserType in~ ("Admin","DcAdmin")
      | where Operation in~ (officeOpList)
      | extend ClientIPOnly = case( 
          ClientIP has ".", tostring(split(ClientIP,":")[0]), 
          ClientIP has "[", tostring(trim_start(@'[[]', tostring(split(ClientIP,"]")[0]))),
          ClientIP
        )  
      | extend Port = case(
          ClientIP has ".", tostring(split(ClientIP,":")[1]),
          ClientIP has "[", tostring(split(ClientIP, "]:")[1]),
          ""
        )
      | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), OperationCount = count() 
          by Operation, UserType, UserId, ClientIP = ClientIPOnly, Port, ResultStatus, Parameters
      | extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1]);

  // Combine Enriched Logs and Office Activity Logs
  union isfuzzy=true enrichedLogs, officeLogs
  | summarize StartTimeUtc = min(StartTimeUtc), EndTimeUtc = max(EndTimeUtc), TotalOperationCount = sum(OperationCount) 
      by Operation, UserType, UserId, ClientIP, Port, ResultStatus, Parameters, AccountName, AccountUPNSuffix
  | order by StartTimeUtc desc;  
id: 0f1f2b17-f9d6-4d2a-a0fb-a7ae1659e3eb
version: 2.0.6
{
  "$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/0f1f2b17-f9d6-4d2a-a0fb-a7ae1659e3eb')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/0f1f2b17-f9d6-4d2a-a0fb-a7ae1659e3eb')]",
      "properties": {
        "alertRuleTemplateName": "0f1f2b17-f9d6-4d2a-a0fb-a7ae1659e3eb",
        "customDetails": null,
        "description": "Identifies if any tampering is done to either audit log, ATP Safelink, SafeAttachment, AntiPhish, or Dlp policy. \nAn adversary may use this technique to evade detection or avoid other policy-based defenses.\nReferences: https://docs.microsoft.com/powershell/module/exchange/advanced-threat-protection/remove-antiphishrule?view=exchange-ps.\n",
        "displayName": "GSA Enriched Office 365 - Office Policy Tampering",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UserId",
                "identifier": "FullName"
              },
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "AccountUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "ClientIP",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - office_policytampering.yaml",
        "query": "// Query for EnrichedMicrosoft365AuditLogs\nlet enrichedOpList = EnrichedMicrosoft365AuditLogs \n    | summarize by Operation\n    | where Operation has_any (\"Remove\", \"Disable\")\n    | where Operation contains \"AntiPhish\" \n        or Operation contains \"SafeAttachment\" \n        or Operation contains \"SafeLinks\" \n        or Operation contains \"Dlp\" \n        or Operation contains \"Audit\"\n    | summarize make_set(Operation, 500);\n\nlet enrichedLogs = EnrichedMicrosoft365AuditLogs\n    | where RecordType == \"ExchangeAdmin\"\n    | where UserType in~ (\"Admin\", \"DcAdmin\")\n    | where Operation in~ (enrichedOpList)\n    | extend ClientIPOnly = case( \n        ClientIp has \".\", tostring(split(ClientIp, \":\")[0]), \n        ClientIp has \"[\", tostring(trim_start(@'[[]', tostring(split(ClientIp, \"]\")[0]))),\n        ClientIp\n      )  \n    | extend Port = case(\n        ClientIp has \".\", tostring(split(ClientIp, \":\")[1]),\n        ClientIp has \"[\", tostring(split(ClientIp, \"]:\")[1]),\n        \"\"\n      )\n    | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), OperationCount = count() \n        by Operation, UserType, UserId, ClientIP = ClientIPOnly, Port, ResultStatus, Parameters = tostring(AdditionalProperties.Parameters)\n    | extend AccountName = tostring(split(UserId, \"@\")[0]), AccountUPNSuffix = tostring(split(UserId, \"@\")[1]);\n\n// Query for OfficeActivity\nlet officeOpList = OfficeActivity \n    | summarize by Operation\n    | where Operation has_any (\"Remove\", \"Disable\")\n    | where Operation contains \"AntiPhish\" \n        or Operation contains \"SafeAttachment\" \n        or Operation contains \"SafeLinks\" \n        or Operation contains \"Dlp\" \n        or Operation contains \"Audit\"\n    | summarize make_set(Operation, 500);\n\nlet officeLogs = OfficeActivity\n    | where RecordType =~ \"ExchangeAdmin\"\n    | where UserType in~ (\"Admin\",\"DcAdmin\")\n    | where Operation in~ (officeOpList)\n    | extend ClientIPOnly = case( \n        ClientIP has \".\", tostring(split(ClientIP,\":\")[0]), \n        ClientIP has \"[\", tostring(trim_start(@'[[]', tostring(split(ClientIP,\"]\")[0]))),\n        ClientIP\n      )  \n    | extend Port = case(\n        ClientIP has \".\", tostring(split(ClientIP,\":\")[1]),\n        ClientIP has \"[\", tostring(split(ClientIP, \"]:\")[1]),\n        \"\"\n      )\n    | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), OperationCount = count() \n        by Operation, UserType, UserId, ClientIP = ClientIPOnly, Port, ResultStatus, Parameters\n    | extend AccountName = tostring(split(UserId, \"@\")[0]), AccountUPNSuffix = tostring(split(UserId, \"@\")[1]);\n\n// Combine Enriched Logs and Office Activity Logs\nunion isfuzzy=true enrichedLogs, officeLogs\n| summarize StartTimeUtc = min(StartTimeUtc), EndTimeUtc = max(EndTimeUtc), TotalOperationCount = sum(OperationCount) \n    by Operation, UserType, UserId, ClientIP, Port, ResultStatus, Parameters, AccountName, AccountUPNSuffix\n| order by StartTimeUtc desc;\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "DefenseEvasion",
          "Persistence"
        ],
        "techniques": [
          "T1098",
          "T1562"
        ],
        "templateVersion": "2.0.6",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}