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;
relevantTechniques:
- T1098
- T1562
name: GSA Enriched Office 365 - Office Policy Tampering
requiredDataConnectors:
- dataTypes:
  - EnrichedMicrosoft365AuditLogs
  connectorId: AzureActiveDirectory
- dataTypes:
  - OfficeActivity (Exchange)
  connectorId: Office365
entityMappings:
- fieldMappings:
  - identifier: FullName
    columnName: UserId
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: AccountUPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: ClientIP
  entityType: IP
triggerThreshold: 0
id: 0f1f2b17-f9d6-4d2a-a0fb-a7ae1659e3eb
tactics:
- Persistence
- DefenseEvasion
version: 2.0.6
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - office_policytampering.yaml
queryPeriod: 1d
kind: Scheduled
queryFrequency: 1d
severity: Medium
status: Available
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.  
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;  
triggerOperator: gt
{
  "$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"
    }
  ]
}