Skip to content

Instantly share code, notes, and snippets.

@jschlackman
Last active July 12, 2023 15:48
Show Gist options
  • Save jschlackman/22ea726e7dc8caf6e37b71a7ea05fed2 to your computer and use it in GitHub Desktop.
Save jschlackman/22ea726e7dc8caf6e37b71a7ea05fed2 to your computer and use it in GitHub Desktop.
Sends an email alert if any privileged AD group has a member added.
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2019-04-08T12:00:00</Date>
<Author>james@schlackman.org</Author>
<Description>Sends an email alert if any privileged AD group has a member added.</Description>
</RegistrationInfo>
<Triggers>
<EventTrigger>
<Enabled>true</Enabled>
<Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="Security"&gt;&lt;Select Path="Security"&gt;*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and (EventID=4728 or EventID=4732 or EventID=4756)]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>
<ValueQueries>
<Value name="MemberName">Event/EventData/Data[@Name='MemberName']</Value>
<Value name="TargetUserName">Event/EventData/Data[@Name='TargetUserName']</Value>
<Value name="SubjectUserName">Event/EventData/Data[@Name='SubjectUserName']</Value>
</ValueQueries>
</EventTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>S-1-5-18</UserId>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>Queue</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
<UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>P3D</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>powershell</Command>
<Arguments>-ExecutionPolicy Bypass -File .\Email-AdminGroupAddition.ps1 -membername "$(MemberName)" -groupname "$(TargetUserName)" -editorname "$(SubjectUserName)"</Arguments>
<WorkingDirectory>\\contoso.com\SYSVOL\contoso.com\scripts</WorkingDirectory>
</Exec>
</Actions>
</Task>
# Name: Email-AdminGroupAddition.ps1
# Author: James Schlackman
# Last Modified: Oct 10 2021
#
# Sends an email alert if any privileged AD group has a member added.
#
# Should be configured to run on any non-RO Domain Controller, triggered by a scheduled task
# attached to event ID 4728, 4732, or 4756 in the Security event log.
param(
[string]$membername,
[string]$groupname,
[string]$editorname
)
$MailRelay = "smtp.contoso.com"
$Subject = "New member added to privileged AD group"
$FromAddress = "Contoso Support <support@contoso.com>"
$ToAddress = "accountalerts@contoso.com"
# Get names of all privileged groups defined in AD
$AdminGroups = Get-ADGroup -Filter 'AdminCount -eq 1' | Select -ExpandProperty sAMAccountName
# Define any additional groups you want to monitor here (that are not already marked in AD using the adminCount attribute)
$AdminGroups += 'Workstation Admins','Remote Assistance Agents'
If ($groupname -in $AdminGroups) {
# Find member that was added and who added them
$addedMember = Get-ADObject -Identity $membername -Properties Title,Description,SamAccountName
$editorUser = Get-ADUser -Identity $editorname -Properties Title,Description
# Create the body of the email
$Body = @"
<html>
<head>
<style>body, table {font-family: Calibri, sans-serif; font-size: 11pt} p.footer {margin-top: 3em; font-size: 9pt; font-style: italic; color: gray} th {font-weight: bold; padding-right: 1em; text-align: left; background-color: #f0f0f0}</style>
</head>
<body>
<p>The following AD user or group was just added to the <b>$groupname</b> group:</p>
<table>
<tr><th>Name:</th><td>$($addedMember.Name)</td></tr>
<tr><th>Username:</th><td>$($addedMember.SamAccountName)</td></tr>
<tr><th>Description:</th><td>$(If ($addedMember.Title) {$addedMember.Title} Else {$addedMember.Description})</td></tr>
<tr><th>Added By:</th><td>$($editorUser.Name)</td></tr>
<tr><th>Admin Username:</th><td>$($editorUser.SamAccountName)</td></tr>
<tr><th>Admin Description:</th><td>$(If ($editorUser.Title) {$editorUser.Title} Else {$editorUser.Description})</td></tr>
</table>
<p>If this addition was unexpected, investigate immediately as it may indicate an account compromise.</p>
<p>For more details, check the Security event log on Domain Controller <b>$env:COMPUTERNAME</b> for Event IDs 4728, 4732, and 4756.</p>
<p class="footer">This is a scripted message sent via the Task Scheduler on $env:COMPUTERNAME.</p>
</body></html>
"@
# Send email notification
Send-MailMessage -SmtpServer $MailRelay -Subject $Subject -From $FromAddress -BodyAsHtml $Body -To $ToAddress -Encoding UTF8
}
@sjteoh111
Copy link

Hi Sir, is dont work when i attached to Task Scheduler

@jschlackman
Copy link
Author

Hi Sir, is dont work when i attached to Task Scheduler

Without knowing the specifics of your implementation it's difficult to say what could be causing a failure. Common things to check are:

  1. Does the script work if you define dummy values for the inputs and run it manually?
  2. Did you modify the Working Directory for the power shell task to match the location of the script?
  3. What error code does Task Scheduler report?

@sjteoh111
Copy link

Hi Sir, is dont work when i attached to Task Scheduler

Without knowing the specifics of your implementation it's difficult to say what could be causing a failure. Common things to check are:

  1. Does the script work if you define dummy values for the inputs and run it manually?
  2. Did you modify the Working Directory for the power shell task to match the location of the script?
  3. What error code does Task Scheduler report?

i can receive the email but all the field is empty and having the error below.

image

image

@jschlackman
Copy link
Author

It looks like the parameters are not being passed from the event log entry. Did you create your task in the Task Scheduler manually or did you customize and import the sample XML from this gist?

The sample XML contains custom entries (the <ValueQueries> section on lines 12-16) that cannot be created in the Task Scheduler GUI - it will only work if you import a custom XML file.

@sjteoh111
Copy link

I create the task scheduler manually

image

@jschlackman
Copy link
Author

That's why it's not working. If you create the scheduled task manually it won't pass the parameters to the script from the event that triggers it. Download the sample XML from the gist, import it, then customize as needed before saving.

@sjteoh111
Copy link

Got it , after manual import it work now. Thanks @jschlackman . May i get some idea from you ? how do i add event ID 4729 for getting notification when user removed from domain group ?

@jschlackman
Copy link
Author

There are a couple of different approaches but the simplest one would be to make a copy of the script with all the instances of 'added' changed to 'removed' and then add it to the Task Scheduler with a modified XML to trigger on events 4729, 4733, and 4757 (you need all three to be able to monitor local, global, and universal groups).

@AET-Bove
Copy link

I noticed the imported scheduled task has optional "start in" field entry for contoso.com. I changed that to the C:\temp where the script is saved. Both script and xml are named the same as yours. I tested couple times, and I see the task running, but it runs for a while.

@jschlackman
Copy link
Author

I noticed the imported scheduled task has optional "start in" field entry for contoso.com. I changed that to the C:\temp where the script is saved.

You are correct that you will need to change that field to the folder that has the script - the task XML is just an example. In my environment I save the script in the SYSVOL scripts location so that every DC can access it without me having to copy it to (and update it on) each one individually.

I tested couple times, and I see the task running, but it runs for a while.

In my experience any significant delay can be attributed to the mail relay you are using. If it's not configured to accept unauthenticated SMTP submissions from the server you are running the script on, it might stall at the Send-MailMessage command. You can either make changes on the mail relay or add mail credentials to the script.

@AET-Bove
Copy link

AET-Bove commented Jul 12, 2023

I added the credentials for SMTP Auth.

``$MailRelay = "smtp.server.com"
$Subject = "AD Admin Group Updated"
$FromAddress = "support@domain.com"
$ToAddress = "engineering@domain.com"
$User = "support@domain.com"
$PWord = Get-Content "C:\temp\support.mp4" | ConvertTo-SecureString -Force
$mailCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord # Send email notification [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Send-MailMessage -SmtpServer $MailRelay -Subject $Subject -From $FromAddress -BodyAsHtml $Body -To $ToAddress -credential $mailCredentials -Encoding UTF8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment