T1484

Domain or Tenant Policy Modification

Defense Evasion Privilege Escalation Last updated:

Adversaries may modify the configuration settings of a domain or identity tenant to evade defenses and/or escalate privileges in centrally managed environments. This includes altering Group Policy Objects (GPOs) in Active Directory to push malicious configurations to domain-joined endpoints, modifying domain trust relationships to allow adversary-controlled domains to forge access tokens accepted by victim resources, and adding rogue federated identity providers to cloud tenants (Azure AD, Okta) to authenticate as any managed user. Nation-state actors including those behind the SolarWinds (SUNBURST) campaign abused federation trust settings to achieve persistent, stealthy access across cloud environments. Attackers may temporarily modify policy, complete their objective, and revert changes to remove indicators.

What is T1484 Domain or Tenant Policy Modification?

Domain or Tenant Policy Modification (T1484) maps to the Defense Evasion and Privilege Escalation tactics — the adversary is trying to avoid being detected in MITRE ATT&CK.

This page provides production-ready detection logic for Domain or Tenant Policy Modification, covering the data sources and telemetry it touches: Active Directory: Active Directory Object Modification, Active Directory: Active Directory Object Creation, Active Directory: Active Directory Object Deletion, Cloud Service: Cloud Service Modification, Process: Process Creation, Command: Command Execution, Windows Security Event Log, Azure Active Directory Audit Logs. The queries below are rated high severity at high confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Defense Evasion Privilege Escalation
Technique
T1484 Domain or Tenant Policy Modification
Canonical reference
https://attack.mitre.org/techniques/T1484/
Microsoft Sentinel / Defender
kusto
// T1484 — Domain or Tenant Policy Modification
// Covers: GPO creation/modification, domain trust changes, Azure AD federation abuse
let GPOModificationEvents = SecurityEvent
| where TimeGenerated > ago(24h)
| where EventID in (5136, 5137, 5141)
| extend ObjectClass_ = tostring(EventData.ObjectClass)
| extend ObjectDN_ = tostring(EventData.ObjectDN)
| extend AttributeName_ = tostring(EventData.AttributeLDAPDisplayName)
| extend AttributeValue_ = tostring(EventData.AttributeValue)
| extend SubjectAccount = tostring(EventData.SubjectUserName)
| extend SubjectDomain = tostring(EventData.SubjectDomainName)
| where ObjectClass_ =~ "groupPolicyContainer" or ObjectDN_ has "Policies"
| extend EventType = case(
    EventID == 5137, "GPO Created",
    EventID == 5136, "GPO Modified",
    EventID == 5141, "GPO Deleted",
    "Unknown"
  )
| project TimeGenerated, EventID, EventType, SubjectAccount, SubjectDomain,
          ObjectDN_, ObjectClass_, AttributeName_, AttributeValue_, Computer;
let DomainTrustEvents = SecurityEvent
| where TimeGenerated > ago(24h)
| where EventID in (4706, 4707, 4716, 4865, 4866, 4867)
| extend TargetDomain_ = tostring(EventData.TargetDomainName)
| extend TrustType_ = tostring(EventData.TrustType)
| extend TrustDirection_ = tostring(EventData.TrustDirection)
| extend TrustAttributes_ = tostring(EventData.TrustAttributes)
| extend SubjectAccount = tostring(EventData.SubjectUserName)
| extend SubjectDomain = tostring(EventData.SubjectDomainName)
| extend EventType = case(
    EventID == 4706, "Trust Created",
    EventID == 4707, "Trust Removed",
    EventID == 4716, "Trust Modified",
    EventID == 4865, "Forest Trust Entry Added",
    EventID == 4866, "Forest Trust Entry Removed",
    EventID == 4867, "Forest Trust Entry Modified",
    "Unknown"
  )
| project TimeGenerated, EventID, EventType, SubjectAccount, SubjectDomain,
          TargetDomain_, TrustType_, TrustDirection_, TrustAttributes_, Computer;
let AzureADFederationEvents = AuditLogs
| where TimeGenerated > ago(24h)
| where Category in ("Policy", "Application", "DirectoryManagement")
| where OperationName in (
    "Set federation settings on domain",
    "Set domain authentication",
    "Add unverified domain to company",
    "Add verified domain to company",
    "Remove verified domain from company",
    "Update domain",
    "Set company information",
    "Add policy to service principal",
    "Delete policy from service principal",
    "Update policy"
  )
| extend ActorUPN = tostring(InitiatedBy.user.userPrincipalName)
| extend ActorApp = tostring(InitiatedBy.app.displayName)
| extend ActorIP = tostring(InitiatedBy.user.ipAddress)
| extend TargetResource = tostring(TargetResources[0].displayName)
| extend EventType = strcat("Azure AD: ", OperationName)
| project TimeGenerated, OperationName, EventType, Result, ActorUPN, ActorApp,
          ActorIP, TargetResource, CorrelationId;
// GPO Modification via PowerShell (process-based detection)
let GPOPowerShellEvents = DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName =~ "powershell.exe" or FileName =~ "pwsh.exe"
| where ProcessCommandLine has_any (
    "New-GPO", "Set-GPLink", "Set-GPPermission", "Set-GPRegistryValue",
    "Import-GPO", "Copy-GPO", "Restore-GPO", "New-GPLink",
    "Set-ADObject", "New-ADObject",
    "gpupdate", "gpscript",
    "LDAP://CN=Policies"
  )
| project Timestamp, DeviceName, AccountName, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine,
          EventType = "GPO PowerShell Activity";
union isfuzzy=true
    (GPOModificationEvents | extend Source = "Windows Security Log"),
    (DomainTrustEvents | extend Source = "Windows Security Log - Trust"),
    (AzureADFederationEvents | extend Source = "Azure AD Audit Log"),
    (GPOPowerShellEvents | extend Source = "MDE Process Events")
| sort by TimeGenerated desc

Detects domain and tenant policy modifications across four signal sources: (1) Windows Security Event IDs 5136/5137/5141 for Group Policy Object creation, modification, and deletion in Active Directory; (2) Windows Security Event IDs 4706/4707/4716/4865-4867 for domain and forest trust relationship changes; (3) Azure AD AuditLogs for federation trust configuration changes including 'Set federation settings on domain' and identity provider additions; (4) Microsoft Defender for Endpoint DeviceProcessEvents for PowerShell cmdlets that modify Group Policy (New-GPO, Set-GPLink, Import-GPO). The union of all four sources provides broad coverage of on-premises AD and cloud identity policy abuse.

high severity high confidence

Data Sources

Active Directory: Active Directory Object Modification Active Directory: Active Directory Object Creation Active Directory: Active Directory Object Deletion Cloud Service: Cloud Service Modification Process: Process Creation Command: Command Execution Windows Security Event Log Azure Active Directory Audit Logs

Required Tables

SecurityEvent AuditLogs DeviceProcessEvents

False Positives

  • Legitimate Group Policy administration by IT staff using GPMC or Group Policy PowerShell module during scheduled maintenance windows
  • Domain controllers joining or leaving forests creating legitimate trust modification events (4706/4716) during infrastructure changes
  • Azure AD Connect or ADFS deployment/reconfiguration generating federation settings events during sanctioned identity synchronization projects
  • Automated configuration management tools (Desired State Configuration, Ansible, PingCastle) that enumerate or validate GPO settings as part of compliance checking
  • Domain trust events generated during disaster recovery exercises, domain migrations, or AD restructuring projects authorized by IT leadership

Sigma rule & cross-platform mapping

The detection logic for Domain or Tenant Policy Modification (T1484) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: process_creation
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 5 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Create and Link a Malicious GPO via PowerShell

    Expected signal: Windows Security Event ID 5137 on the domain controller: Directory Service Object Created, ObjectClass=groupPolicyContainer, ObjectDN=CN={<GUID>},CN=Policies,CN=System,DC=<domain>. Security Event ID 5136: gPCFileSysPath attribute set to \\<domain>\SYSVOL\<domain>\Policies\{<GUID>}. Sysmon Event ID 1 on the initiating workstation: powershell.exe with 'New-GPO' and 'New-GPLink' in CommandLine. PowerShell ScriptBlock Event ID 4104 with full cmdlet execution.

  2. Test 2Modify GPO to Deploy a Scheduled Task via XML Injection

    Expected signal: Sysmon Event ID 11 (File Create) on the DC or management host: ScheduledTasks.xml created in SYSVOL path. Windows Security Event ID 5136 on DC: gPCFileSysPath or versionNumber attribute of the groupPolicyContainer modified, SubjectAccountName=<modifying account>. Event ID 4104 (ScriptBlock) capturing Set-GPRegistryValue invocation. On domain clients, Sysmon Event ID 1 for schtasks.exe or Task Scheduler Event 106/200 for task registration/execution.

  3. Test 3Create New Domain Trust (Simulated via Set-ADObject)

    Expected signal: Windows Security Event ID 4706 on domain controllers: A new trust was created to a domain. SubjectAccountName=<admin account>, TargetDomainName=df00tech-test.local, TrustType=2 (Windows), TrustDirection=1 (Inbound), TrustAttributes=8. Active Directory Event ID 5137: trustedDomain object created in CN=System. Replication events (4928/4929) as the new object replicates to other DCs.

  4. Test 4Azure AD Federation Settings Modification via PowerShell

    Expected signal: Azure AD AuditLogs entry: OperationName='Set federation settings on domain', Category='Policy', Result='success', TargetResources=[{DisplayName: <domain>}], InitiatedBy.user.userPrincipalName=<admin UPN>, InitiatedBy.user.ipAddress=<source IP>. The modified IssuerUri appears in the ModifiedProperties array of the audit event. Azure AD Sign-in Logs may show subsequent authentication attempts using the modified federation settings.

  5. Test 5Enumerate and Identify Vulnerable GPO Permissions (Pre-Attack Reconnaissance)

    Expected signal: Sysmon Event ID 1: powershell.exe with 'Get-GPPermission' and 'Get-ACL' in CommandLine. PowerShell ScriptBlock Event ID 4104 capturing the enumeration loop. Sysmon Event ID 5 (Process Terminated) when enumeration completes. LDAP query telemetry visible in network captures — the GroupPolicy module issues LDAP searches for groupPolicyContainer objects against the domain controller.


Response Playbook

Triage

  1. Identify the account that made the change — query the SubjectAccountName from the security event. Is this a known domain admin, a service account used by configuration management (SCCM, Azure AD Connect), or an unexpected user? Cross-reference against the organization's privileged access management system.
  2. Determine which specific policy object was modified — for GPO events (5136), examine the ObjectDN field to identify which GPO was altered and the AttributeLDAPDisplayName to understand what attribute changed (e.g., 'gPCFileSysPath' indicates the GPO file system path was modified, a common indicator of GPO hijacking).
  3. For trust modification events (4706/4716/4865-4867): immediately identify the TargetDomainName — is this a known partner domain, or an unknown/adversary-controlled domain? Any new trust to an unrecognized domain should be treated as critical.
  4. For Azure AD federation events: retrieve the full audit log entry to identify what identity provider was added or modified. Use 'Get-MsolDomainFederationSettings -DomainName <domain>' or 'Get-AzureADDomain' to enumerate current federation configuration and compare against known-good baseline.
  5. Correlate the modification timestamp with the operator's working hours and any open change management tickets. Changes made outside business hours or without associated change requests are high-priority indicators of unauthorized modification.
  6. Check for evidence of privilege escalation preceding the change — search for privileged logon events (4672, 4648) from the same account in the 30 minutes before the GPO/trust modification. Was there a recent password reset, token theft, or privilege escalation attempt associated with this account?

Containment

  1. If an unauthorized GPO modification is confirmed: immediately use 'Restore-GPO' or GPMC to revert the GPO to its previous version from backup. If no backup exists, delete the malicious GPO settings manually. Block 'gpupdate /force' from running on domain clients until the GPO is verified clean.
  2. If a rogue domain trust was created (4706): remove the trust immediately using 'Remove-ADTrust' or via Active Directory Domains and Trusts console. Document the target domain for threat intelligence.
  3. If Azure AD federation settings were modified: revert federation settings using 'Set-MsolDomainAuthentication' to restore managed authentication, or use the Azure portal to remove the rogue identity provider. Revoke all tokens issued after the modification time using 'Revoke-AzureADUserAllRefreshToken' for all users.
  4. Disable or reset credentials for the account that performed the modification. If a service account was used, rotate its credentials and review which systems authenticate with it.
  5. Force a Group Policy refresh across the domain ('Invoke-GPUpdate -Computer * -RandomDelayInMinutes 0') to ensure any malicious GPO-deployed scheduled tasks, startup scripts, or registry settings are cleared after reverting the GPO.
  6. Initiate a forest-wide password reset if a domain or forest trust was abused — existing Kerberos tickets may have been forged using the compromised trust key and remain valid until their TGT expiry.

Evidence Collection

  1. Windows Security Event Log — Event ID 5136 entries showing the full LDAP attribute changes, before/after values (OldValue/NewValue), and the ObjectDN identifying which GPO was modified. Collect from all domain controllers.
  2. SYSVOL and NETLOGON share snapshots — GPO files are stored in \\<domain>\SYSVOL\<domain>\Policies\{GUID}\. Capture file system metadata (timestamps, ACLs) and contents of all modified GPO XML files (Registry.pol, scheduledtasks.xml, etc.).
  3. Active Directory replication metadata — use 'repadmin /showmeta <ObjectDN>' to see the USN, timestamp, and originating DC for each attribute change. This identifies which DC the modification originated from.
  4. Domain controller security and system event logs — collect 4624/4648/4672 logon events and 5136/5137 directory events from all DCs for the relevant time window.
  5. Azure AD Audit Logs — export all audit events for the relevant time period via 'Get-AzureADAuditDirectoryLogs' or the Azure portal. Focus on Category=Policy and Category=DirectoryManagement.
  6. PowerShell ScriptBlock Logging (Event ID 4104) — if GPO cmdlets were used, ScriptBlock logs capture the full script content including parameters. Check Microsoft-Windows-PowerShell/Operational on the attacking workstation.
  7. Kerberos ticket logs (Event ID 4768/4769) — if trust abuse is suspected, collect TGT and service ticket issuance events from domain controllers to identify abnormal cross-domain ticket requests.
  8. Network captures (if available) — LDAP traffic to domain controllers around the modification time can reveal the source IP and bind DN used, even if logs were cleared.

Escalation Criteria

  • ! Any new domain trust created to an unrecognized domain — this is a critical indicator of a 'Golden SAML' or pass-the-token setup and requires immediate escalation to the incident response team.
  • ! Federation settings modified in Azure AD — SAML/WS-Fed federation changes can enable persistent, stealthy access and constitute a critical security incident regardless of the claimed justification.
  • ! GPO modification containing scheduled task XML, startup scripts, or software installation directives pointing to external URLs or UNC paths not owned by the organization.
  • ! Evidence that the account performing the modification was itself compromised (concurrent logon from unusual geography, impossible travel, or recent credential-exposure incident).
  • ! Modifications occurred on a domain controller directly (LDAP bind from the DC itself rather than a management workstation) — this may indicate the DC itself is compromised.
  • ! Multiple GPO or trust modifications within a short time window across different objects — automated modification at scale suggests a scripted attack rather than a single unauthorized administrative action.

Investigation Guide

Forensic Artifacts

  • > SYSVOL: \\<domain>\SYSVOL\<domain>\Policies\{GPO-GUID}\ — GPO XML files including Registry.pol, scheduledtasks.xml, scripts.ini, and GptTmpl.inf. Modified timestamps reveal when malicious content was placed.
  • > Active Directory attribute: gPCFileSysPath on the groupPolicyContainer object — if this path was changed to an adversary-controlled share, all computers applying the GPO will execute malicious content.
  • > Active Directory attribute: nTSecurityDescriptor on GPO objects — ACL changes granting non-admin accounts write access to GPOs indicate GPO permission abuse (ADSecurity GPO hijacking technique).
  • > Registry: HKLM\SOFTWARE\Policies\ and HKCU\SOFTWARE\Policies\ on domain-joined endpoints — GPO settings are applied here; malicious entries persist until GPO is reverted and 'gpupdate /force' is run.
  • > Windows Event Log: Microsoft-Windows-GroupPolicy/Operational (Event ID 4016, 4017, 5016, 5017) on domain clients — records which GPOs were applied and their version numbers, useful for identifying when a malicious GPO was deployed.
  • > ADFS configuration database (AdfsConfiguration on Windows Internal Database or SQL Server) — stores federation trust configuration. Compare against known-good backup using 'Export-AdfsConfiguration'.
  • > Azure AD: 'Get-MsolFederationProperty -DomainName <domain>' output — shows current token signing certificate thumbprint, issuer URI, and endpoints. Compare against baseline to detect rogue IDP additions.
  • > Kerberos inter-realm TGTs in memory on domain controllers — if cross-domain trust was abused, forged inter-realm tickets may be cached. Memory acquisition with volatility can reveal these.

Tuning Guidance

Begin by establishing a baseline of legitimate GPO administrators in your environment. Event ID 5136 will generate high volume in environments with active configuration management — filter to the specific ObjectClass 'groupPolicyContainer' and focus on changes to high-impact attributes (gPCFileSysPath, gPCMachineExtensionNames) rather than routine version number increments. Build an allowlist of SCCM/MECM service accounts, Azure AD Connect sync accounts, and known admin workstations from which GPO changes are expected. For trust modification events (4706/4716), these should be extremely rare — even in large enterprises, new domain trusts are created only during planned AD projects. Any 4706 event not matching an open change ticket should be treated as high-priority. For Azure AD federation events in AuditLogs, the OperationName 'Set federation settings on domain' should only fire during ADFS provisioning or token-signing certificate renewals — establish a list of expected maintenance windows and use the CorrelationId to link related events. Consider creating a separate high-severity alert specifically for trust creation events (4706, 4865) with no correlation to open change management tickets, as these have near-zero legitimate false positive rate outside of planned infrastructure projects.


Hunting Queries

Hunt for Group Policy Object modifications that occur outside business hours (before 7am or after 7pm) or on weekends. Legitimate GPO administration is typically performed during business hours in change windows. After-hours modifications are a strong indicator of unauthorized access, especially when combined with no change management ticket.

Hunting — KQL
kql
// Hunt for GPO modifications outside business hours or from non-admin workstations
SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID in (5136, 5137)
| extend ObjectClass_ = tostring(EventData.ObjectClass)
| where ObjectClass_ =~ "groupPolicyContainer"
| extend SubjectAccount = tostring(EventData.SubjectUserName)
| extend SubjectDomain = tostring(EventData.SubjectDomainName)
| extend AttributeName_ = tostring(EventData.AttributeLDAPDisplayName)
| extend ObjectDN_ = tostring(EventData.ObjectDN)
| extend HourOfDay = hourofday(TimeGenerated)
| extend IsOutsideHours = HourOfDay < 7 or HourOfDay > 19
| extend IsWeekend = dayofweek(TimeGenerated) in (0d, 6d)
| where IsOutsideHours or IsWeekend
| summarize GPOModCount=count(), Accounts=make_set(SubjectAccount), ModifiedGPOs=make_set(ObjectDN_), ChangedAttributes=make_set(AttributeName_), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated) by Computer, bin(TimeGenerated, 1h)
| where GPOModCount > 0
| sort by LastSeen desc
Hunting — SPL
spl
index=wineventlog sourcetype="WinEventLog:Security" (EventCode=5136 OR EventCode=5137) ObjectClass="groupPolicyContainer"
| eval HourOfDay=strftime(_time, "%H")
| eval DayOfWeek=strftime(_time, "%w")
| eval IsOutsideHours=if(HourOfDay < "07" OR HourOfDay > "19", 1, 0)
| eval IsWeekend=if(DayOfWeek="0" OR DayOfWeek="6", 1, 0)
| where IsOutsideHours=1 OR IsWeekend=1
| stats count as GPOModCount, values(SubjectAccountName) as Accounts, values(ObjectDN) as ModifiedGPOs, values(AttributeLDAPDisplayName) as ChangedAttributes, earliest(_time) as FirstSeen, latest(_time) as LastSeen by host
| sort - GPOModCount

Hunt for modifications to high-value GPO attributes, particularly gPCFileSysPath (file system path of the GPO templates) which if redirected to an adversary-controlled share enables code execution on all domain computers applying the GPO. Also detects changes to extension names that control which client-side extensions process the GPO. This pattern is distinct from the main detection which looks at all GPO modifications.

Hunting — KQL
kql
// Hunt for accounts that modified GPOs but are not in typical privileged admin groups
// Also detect gPCFileSysPath changes which indicate GPO file path redirection (hijacking)
SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 5136
| extend ObjectClass_ = tostring(EventData.ObjectClass)
| extend AttributeName_ = tostring(EventData.AttributeLDAPDisplayName)
| extend ObjectDN_ = tostring(EventData.ObjectDN)
| extend NewValue_ = tostring(EventData.AttributeValue)
| extend SubjectAccount = tostring(EventData.SubjectUserName)
| where ObjectClass_ =~ "groupPolicyContainer"
| where AttributeName_ in ("gPCFileSysPath", "gPCMachineExtensionNames", "gPCUserExtensionNames", "versionNumber", "flags")
| summarize ModCount=count(), ModifiedAttributes=make_set(AttributeName_), NewValues=make_set(NewValue_), AffectedGPOs=make_set(ObjectDN_) by SubjectAccount, Computer, bin(TimeGenerated, 15m)
| extend SuspiciousFilePath = NewValues has "\\\\" and not (NewValues has "SYSVOL")
| sort by ModCount desc
Hunting — SPL
spl
index=wineventlog sourcetype="WinEventLog:Security" EventCode=5136 ObjectClass="groupPolicyContainer"
  (AttributeLDAPDisplayName="gPCFileSysPath" OR AttributeLDAPDisplayName="gPCMachineExtensionNames" OR AttributeLDAPDisplayName="gPCUserExtensionNames" OR AttributeLDAPDisplayName="versionNumber")
| eval SuspiciousPath=if(match(AttributeValue, "^\\\\\\\\(?!.*SYSVOL)"), 1, 0)
| stats count as ModCount, values(AttributeLDAPDisplayName) as ModifiedAttributes, values(AttributeValue) as NewValues, values(ObjectDN) as AffectedGPOs by SubjectAccountName, host
| sort - ModCount

Hunt for accounts that had a privileged logon (Event ID 4672 — special privileges assigned, 4648 — explicit credential logon) followed within 30 minutes by a domain policy modification event. This sequence is characteristic of adversaries who first escalate privileges (via credential theft, token impersonation, or lateral movement to a privileged workstation) and then immediately make policy changes. This cross-correlation pattern is not covered by the main alert which looks at individual modification events.

Hunting — KQL
kql
// Hunt for correlated sequences: privilege escalation followed by domain/tenant policy modification
let PrivilegedLogons = SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID in (4672, 4648)
| extend SubjectAccount = tostring(EventData.SubjectUserName)
| extend LogonType = tostring(EventData.LogonType)
| project PrivLogonTime=TimeGenerated, SubjectAccount, Computer;
let PolicyChanges = SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID in (5136, 5137, 4706, 4716, 4865)
| extend SubjectAccount = tostring(EventData.SubjectUserName)
| extend ObjectDN_ = tostring(EventData.ObjectDN)
| project ChangeTime=TimeGenerated, SubjectAccount, Computer, ObjectDN_, EventID;
PrivilegedLogons
| join kind=inner PolicyChanges on SubjectAccount
| where ChangeTime > PrivLogonTime and datetime_diff('minute', ChangeTime, PrivLogonTime) < 30
| project PrivLogonTime, ChangeTime, SubjectAccount, Computer, Computer1, ObjectDN_, EventID
| summarize PrivLogonCount=count(), AffectedObjects=make_set(ObjectDN_), ChangeEvents=make_set(EventID) by SubjectAccount, bin(PrivLogonTime, 1h)
| sort by PrivLogonCount desc
Hunting — SPL
spl
index=wineventlog sourcetype="WinEventLog:Security" (EventCode=4672 OR EventCode=4648 OR EventCode=5136 OR EventCode=5137 OR EventCode=4706 OR EventCode=4716)
| eval EventCategory=case(
    EventCode=4672 OR EventCode=4648, "PrivilegedLogon",
    EventCode=5136 OR EventCode=5137 OR EventCode=4706 OR EventCode=4716, "PolicyChange",
    true(), "Other"
  )
| eval Actor=coalesce(SubjectAccountName, src_user)
| stats values(EventCategory) as EventTypes, min(_time) as FirstEvent, max(_time) as LastEvent, values(EventCode) as EventCodes, values(ObjectDN) as AffectedObjects by Actor, host
| where mvcount(EventTypes) > 1
| eval TimeWindowMinutes=round((LastEvent-FirstEvent)/60,1)
| where TimeWindowMinutes < 30
| sort - TimeWindowMinutes

Atomic Red Team Tests

Test 1 Create and Link a Malicious GPO via PowerShell
windows

Simulates adversary creation of a new Group Policy Object and linking it to an Active Directory OU. This is the foundational step in GPO-based persistence attacks where attackers push malicious scheduled tasks, startup scripts, or registry settings to domain-joined computers. Requires Domain Admin or delegated GPO creation rights. The GPO itself is benign in this test (no payload), but the creation and link events match real attack telemetry.

Command

powershell
Import-Module GroupPolicy
$GPO = New-GPO -Name 'DF00Tech-Test-GPO' -Comment 'Atomic Red Team Test T1484'
$OUPath = (Get-ADDomain).DistinguishedName
New-GPLink -Name 'DF00Tech-Test-GPO' -Target $OUPath -LinkEnabled Yes
Write-Host "GPO Created: $($GPO.Id) linked to $OUPath"

Cleanup

powershell
Remove-GPLink -Name 'DF00Tech-Test-GPO' -Target (Get-ADDomain).DistinguishedName -ErrorAction SilentlyContinue
Remove-GPO -Name 'DF00Tech-Test-GPO' -ErrorAction SilentlyContinue

Expected Telemetry

Windows Security Event ID 5137 on the domain controller: Directory Service Object Created, ObjectClass=groupPolicyContainer, ObjectDN=CN={<GUID>},CN=Policies,CN=System,DC=<domain>. Security Event ID 5136: gPCFileSysPath attribute set to \\<domain>\SYSVOL\<domain>\Policies\{<GUID>}. Sysmon Event ID 1 on the initiating workstation: powershell.exe with 'New-GPO' and 'New-GPLink' in CommandLine. PowerShell ScriptBlock Event ID 4104 with full cmdlet execution.

Expected Detection

KQL: GPOModificationEvents branch fires on EventID 5137 with ObjectClass=groupPolicyContainer. GPOPowerShellEvents fires on 'New-GPO' and 'New-GPLink' patterns. SPL: EventCode=5137 with ObjectClass=groupPolicyContainer and Sysmon EventCode=1 with 'New-GPO' in CommandLine.

Test 2 Modify GPO to Deploy a Scheduled Task via XML Injection
windows

Simulates the advanced GPO abuse technique where attackers inject a scheduled task XML into an existing GPO's file system path, causing all computers in the linked OU to create a scheduled task executing adversary-controlled code. This is the technique used by threat actors post-SolarWinds to maintain persistence. The test uses a benign task (calc.exe) and requires write access to the SYSVOL GPO directory.

Command

powershell
$GPOName = 'Default Domain Policy'
$GPO = Get-GPO -Name $GPOName
$GPOGuid = $GPO.Id.ToString().ToUpper()
$SysvolPath = "\\$env:USERDNSDOMAIN\SYSVOL\$env:USERDNSDOMAIN\Policies\{$GPOGuid}\Machine\Preferences\ScheduledTasks"
New-Item -Path $SysvolPath -ItemType Directory -Force
$TaskXML = @'
<?xml version="1.0" encoding="utf-8"?>
<ScheduledTasks clsid="{CC63F200-7309-4ba0-B154-A0424D91DE4E}">
  <ImmediateTaskV2 clsid="{9756B581-76EC-4169-9AFC-0CA8D43ADB5F}" name="DF00Tech-Test" image="0" changed="2026-03-15 00:00:00" uid="{12345678-1234-1234-1234-123456789012}">
    <Properties action="C" name="DF00Tech-Test" runAs="NT AUTHORITY\System" logonType="S4U">
      <Task version="1.3"><RegistrationInfo/><Triggers><TimeTrigger><StartBoundary>2000-01-01T00:00:00</StartBoundary><Enabled>true</Enabled></TimeTrigger></Triggers><Actions><Exec><Command>calc.exe</Command></Exec></Actions></Task>
    </Properties>
  </ImmediateTaskV2>
</ScheduledTasks>
'@
$TaskXML | Out-File "$SysvolPath\ScheduledTasks.xml" -Encoding UTF8
Set-GPRegistryValue -Name $GPOName -Key 'HKLM\Software\Policies\DF00Tech' -ValueName 'TestKey' -Type String -Value 'AtomicTest' -Server $env:LOGONSERVER.TrimStart('\\')

Cleanup

powershell
Remove-Item "\\$env:USERDNSDOMAIN\SYSVOL\$env:USERDNSDOMAIN\Policies\{$(((Get-GPO -Name 'Default Domain Policy').Id.ToString().ToUpper()))}\Machine\Preferences\ScheduledTasks\ScheduledTasks.xml" -ErrorAction SilentlyContinue
Remove-GPRegistryValue -Name 'Default Domain Policy' -Key 'HKLM\Software\Policies\DF00Tech' -ValueName 'TestKey' -ErrorAction SilentlyContinue

Expected Telemetry

Sysmon Event ID 11 (File Create) on the DC or management host: ScheduledTasks.xml created in SYSVOL path. Windows Security Event ID 5136 on DC: gPCFileSysPath or versionNumber attribute of the groupPolicyContainer modified, SubjectAccountName=<modifying account>. Event ID 4104 (ScriptBlock) capturing Set-GPRegistryValue invocation. On domain clients, Sysmon Event ID 1 for schtasks.exe or Task Scheduler Event 106/200 for task registration/execution.

Expected Detection

KQL: GPOPowerShellEvents fires on 'Set-GPRegistryValue'. SecurityEvent 5136 fires for the GPO versionNumber increment. Hunting query 2 specifically detects gPCFileSysPath and extension attribute changes. SPL: EventCode=5136 with AttributeLDAPDisplayName=versionNumber, and Sysmon EventCode=11 for ScheduledTasks.xml file creation.

Test 3 Create New Domain Trust (Simulated via Set-ADObject)
windows

Simulates the domain trust modification phase of a Golden SAML attack by creating a trust object in Active Directory. In real attacks (SolarWinds/SUNBURST), adversaries add a new federated trust to allow a rogue identity provider to authenticate as any user in the tenant. This test creates a non-functional trust object to generate the requisite security event telemetry without establishing an actual network trust relationship. Requires Domain Admin privileges.

Command

powershell
$TrustProperties = @{
    trustDirection = 1
    trustType = 2
    trustAttributes = 8
    flatName = 'DF00TECHTEST'
    trustPartner = 'df00tech-test.local'
    securityIdentifier = [byte[]](0x01,0x04,0x00,0x00,0x00,0x00,0x00,0x05,0x15,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00)
}
$DomainDN = (Get-ADDomain).DistinguishedName
# Note: This requires Domain Admin. In a test lab only.
New-ADObject -Name 'df00tech-test.local' -Type 'trustedDomain' -Path "CN=System,$DomainDN" -OtherAttributes $TrustProperties
Write-Host "Trust object created — check Security Event ID 4706 on domain controller"

Cleanup

powershell
Remove-ADObject -Identity "CN=df00tech-test.local,CN=System,$((Get-ADDomain).DistinguishedName)" -Confirm:$false -ErrorAction SilentlyContinue

Expected Telemetry

Windows Security Event ID 4706 on domain controllers: A new trust was created to a domain. SubjectAccountName=<admin account>, TargetDomainName=df00tech-test.local, TrustType=2 (Windows), TrustDirection=1 (Inbound), TrustAttributes=8. Active Directory Event ID 5137: trustedDomain object created in CN=System. Replication events (4928/4929) as the new object replicates to other DCs.

Expected Detection

KQL: DomainTrustEvents branch fires on EventID 4706, EventType='Trust Created', TargetDomain_='df00tech-test.local'. SPL: EventCode=4706 with TargetDomainName='df00tech-test.local', RiskScore=90. The hunting query 3 (privilege escalation correlation) fires if a 4672 event preceded this by <30 minutes.

Test 4 Azure AD Federation Settings Modification via PowerShell
windows

Simulates the cloud-based component of a Golden SAML attack where adversaries modify Azure AD federation settings to inject a rogue SAML token signing certificate. In the 2020 SolarWinds compromise, attackers used this technique to forge SAML tokens accepted by Azure AD for any user. This test modifies a federated domain's IssuerUri to an adversary-controlled value, generating the AuditLogs entry that should trigger the detection. Requires Global Administrator privileges in Azure AD. ONLY run against a non-production tenant in a lab environment.

Command

powershell
# Requires AzureAD or MSOnline module and Global Admin credentials
# ONLY RUN IN A LAB/DEV TENANT
Connect-MsolService
$Domain = (Get-MsolDomain | Where-Object {$_.Authentication -eq 'Federated'} | Select-Object -First 1).Name
if ($Domain) {
    $CurrentSettings = Get-MsolDomainFederationSettings -DomainName $Domain
    Write-Host "Current IssuerUri: $($CurrentSettings.IssuerUri)"
    # Modify to simulate adversary-controlled IDP
    Set-MsolDomainFederationSettings -DomainName $Domain -IssuerUri "http://df00tech-test-attacker.com/adfs/services/trust"
    Write-Host "Federation IssuerUri modified for domain: $Domain"
} else {
    Write-Host 'No federated domain found — configure ADFS first or use Get-MsolDomain to verify domain list'
}

Cleanup

powershell
# Revert to original IssuerUri (captured above)
# Set-MsolDomainFederationSettings -DomainName $Domain -IssuerUri $CurrentSettings.IssuerUri
Write-Host 'Revert IssuerUri manually using the value captured before modification'

Expected Telemetry

Azure AD AuditLogs entry: OperationName='Set federation settings on domain', Category='Policy', Result='success', TargetResources=[{DisplayName: <domain>}], InitiatedBy.user.userPrincipalName=<admin UPN>, InitiatedBy.user.ipAddress=<source IP>. The modified IssuerUri appears in the ModifiedProperties array of the audit event. Azure AD Sign-in Logs may show subsequent authentication attempts using the modified federation settings.

Expected Detection

KQL: AzureADFederationEvents branch fires on OperationName='Set federation settings on domain', EventType='Azure AD: Set federation settings on domain', Source='Azure AD Audit Log'. SPL: Would require Azure AD audit log ingestion via azure:aad:auditlogs sourcetype. Alert severity=high, warrants immediate investigation of whether any SAML tokens were forged using the rogue IssuerUri.

Test 5 Enumerate and Identify Vulnerable GPO Permissions (Pre-Attack Reconnaissance)
windows

Simulates the reconnaissance phase of GPO hijacking attacks where adversaries identify GPOs with overly permissive ACLs that allow non-admin accounts to write to them. This is the technique documented by harmj0y as 'Abusing GPO Permissions' — attackers use Get-GPPermission and Get-ACL to find GPOs writable by their current user context before modifying them. Detection of this enumeration pattern can provide early warning before modification occurs.

Command

powershell
Import-Module GroupPolicy
$AllGPOs = Get-GPO -All
foreach ($GPO in $AllGPOs) {
    $Perms = Get-GPPermission -Guid $GPO.Id -All
    $WritableBy = $Perms | Where-Object {$_.Permission -in @('GpoEditDeleteModifySecurity','GpoEdit','GpoCustom')}
    if ($WritableBy) {
        Write-Host "[WRITABLE] $($GPO.DisplayName) ($($GPO.Id)):"
        $WritableBy | ForEach-Object { Write-Host "  - $($_.Trustee.Name): $($_.Permission)" }
    }
}
# Also check via Get-ACL on SYSVOL
$Domain = (Get-ADDomain).DNSRoot
Get-ChildItem "\\$Domain\SYSVOL\$Domain\Policies" | ForEach-Object {
    $ACL = Get-ACL $_.FullName
    $ACL.Access | Where-Object {$_.FileSystemRights -match 'Write' -and $_.IdentityReference -notmatch 'Domain Admins|SYSTEM|Enterprise Admins|CREATOR OWNER'} |
    Select-Object @{N='GPOPath';E={$_.FullName}}, IdentityReference, FileSystemRights
}

Expected Telemetry

Sysmon Event ID 1: powershell.exe with 'Get-GPPermission' and 'Get-ACL' in CommandLine. PowerShell ScriptBlock Event ID 4104 capturing the enumeration loop. Sysmon Event ID 5 (Process Terminated) when enumeration completes. LDAP query telemetry visible in network captures — the GroupPolicy module issues LDAP searches for groupPolicyContainer objects against the domain controller.

Expected Detection

KQL: GPOPowerShellEvents fires on 'Get-GPPermission' pattern (note: this cmdlet is not in the main detection list — consider adding it as a hunting signal). The process-based detection catches 'Import-Module GroupPolicy' combined with enumeration. This test is best caught by the hunting query looking for PowerShell Group Policy cmdlet usage.

Related Detections