Monitor AD group changes

Ever wanted to monitor group changes in AD? This is a script I came up with to do just that. It will collect the security log events from the last hour on all your domain controllers.

In order to use this script, just create a new scheduled task on a machine with the Active Directory module for Windows PowerShell installed and run this script every hour (or whatever you changed $time to). !! Note that the scheduled task needs to be run with an account which has domain admin privileges to be able to read from the security logs of all your domain controllers !!>

The script needs some customization to your environment:

  • variable $Time, as mentioned before, needs to be changed to the interval you want the scheduled task to run
  • variable $ListOfMonitoredOUs needs to be changed to contain all OU’s which contain the groups you want to monitor
  • variables $FromAddress, $ToAddress and $SMTPServer need to be updated to reflect the appropriate email addresses and SMTP server

!! Note that the scheduled task needs to be run with an account which has domain admin privileges to be able to read from the security logs of all your domain controllers. I would advice you to create and use a dedicated service account for running this scheduled task, and to limit the Logon To of this account to just the server running the scheduled task !!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
If (-not (Get-Module -Name 'ActiveDirectory' -ErrorAction SilentlyContinue)) {
    Import-Module ActiveDirectory
}

# Fixed variables
$DomainDistinguishedName = (Get-ADDomain -Current LocalComputer).DistinguishedName
$ListOfDCs = @(Get-ADDomainController -Filter { Name -like "*" })

# https://www.morgantechspace.com/2013/08/active-directory-change-audit-events.html
# The following table document lists the event IDs of the Security Group Management category
$EventIDHashTable = [ordered]@{
    '4727' = 'A security-enabled global group was created'
    '4728' = 'A member was added to a security-enabled global group'
    '4729' = 'A member was removed from a security-enabled global group'
    '4730' = 'A security-enabled global group was deleted'
    '4731' = 'A security-enabled local group was created'
    '4732' = 'A member was added to a security-enabled local group'
    '4733' = 'A member was removed from a security-enabled local group'
    '4734' = 'A security-enabled local group was deleted'
    '4735' = 'A security-enabled local group was changed'
    '4737' = 'A security-enabled global group was changed'
    '4754' = 'A security-enabled universal group was created'
    '4755' = 'A security-enabled universal group was changed'
    '4756' = 'A member was added to a security-enabled universal group'
    '4757' = 'A member was removed from a security-enabled universal group'
    '4758' = 'A security-enabled universal group was deleted'
    '4764' = 'A groups type was changed'
}

#Dynamic variables
$Time = (Get-Date).AddHours(-1)
$ListOfMonitoredOUs = (
    "OU=OU1,$DomainDistinguishedName",
    "OU=OU2,$DomainDistinguishedName",
    "OU=OU3,$DomainDistinguishedName"
)

$FromAddress = '<FromEmailAddress>'
$ToAddress = '<ToEmailAddress>'
$SMTPServer = '<SMTPServer>'

$ListOfMonitoredGroups = $null
ForEach ($MonitoredOU in $ListOfMonitoredOUs) {
    $ListOfMonitoredGroups += @(Get-ADGroup -SearchBase $MonitoredOU -Filter *)
    $ListOfMonitoredGroups.Count
}

# Get Security Log Entries
$LogEntry = @()
$LogEntries = @()
ForEach ($DC in $ListofDCs) {
    Write-Host "Processing domain controller $DC"
    $LogEntries += Get-WinEvent -ComputerName $DC.Hostname -FilterHashTable @{Logname = 'Security'; StartTime = $Time } -ErrorAction Ignore | `
        Where-Object { $_.TaskDisplayName -eq "Security Group Management" -and $_.ID -ne "4737" }
    $LogEntries = $LogEntries | Sort-Object TimeCreated
}
#$LogEntries | FL

# Process Log Entries
If ($LogEntries -ne "") {
    ForEach ($LogEntry in $LogEntries) {
        $Subject = "[$env:USERDOMAIN] - Eventid " + $LogEntry.ID + " - " + $EventIDHashTable.Item($LogEntry.Id.ToString())
        $MailBody = ($LogEntry | Format-List | Out-String)
        Send-MailMessage `
            -From $FromAddress `
            -To $ToAddress `
            -Subject $Subject `
            -SmtpServer $SMTPServer `
            -Body $MailBody
    }
}


As always, please keep in mind this script is tailored to my environment, but can be used as a template for your environment. I do not pretend to be a PowerShell guru and as such my script may not be perfect. I am open to suggestions  🙂

Leave a Reply

Your email address will not be published. Required fields are marked *