Active Directory User Account Lockout Event Notification
Be notified by email when an Active Directory user account is locked out, this powershell script will grab the most recent lockout event and send you an email notification. Requires a Windows 2008+ domain controller and an email system accepting a relay from the DC.
$Event = Get-EventLog -LogName Security -InstanceId 4740 -Newest 1
$MailBody= $Event.Message + "r
`t" + $Event.TimeGenerated
$MailSubject= "User Account locked out"
$SmtpClient = New-Object system.net.mail.smtpClient
$SmtpClient.host = "ExchSvr.Domain.Local"
$MailMessage = New-Object system.net.mail.mailmessage
$MailMessage.from = "AcctLockNotify@domain.local"
$MailMessage.To.add("user@email.com")
$MailMessage.IsBodyHtml = 0
$MailMessage.Subject = $MailSubject
$MailMessage.Body = $MailBody
$SmtpClient.Send($MailMessage)
Create a new task in task scheduler to run on an event trigger with event ID 4740. Create a new action to ‘Start a program’ and add this path under program/script:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file C:\Scripts\acc_lockout.ps1 When you click ok, task scheduler is smart enough to break the argument up and add them to the correct field.
Before you set it and forget it, go to the General tab and select ‘Run whether user is logged on or not’ and use an account with the proper rights, like your common dedicated service account.
If you’re getting the error:
“File C:\Scripts\acc_lockout.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see “get-help about_signing” for more details.”, then you will need to turn off the execution policy with:
Set-ExecutionPolicy -0 You should see an email in the following format- A user account was locked out. Subject: Security ID: S-1-5-18 Account Name: DOMAINCONTROLLER$ Account Domain: DOMAINNAME Logon ID: 0x3e7 Account That Was Locked Out: Security ID: S-1-5-21-2388021981-560130107-590547658-1106 Account Name: adminuser1 Additional Information: Caller Computer Name: ServerHost1 11/08/2012 14:12:29
February 26, 2013 11:51 am @ 11:51
Awesome PS script, I love it and it works well but one thing… how come sometimes the Caller Computer Name is blank. Some of the times it has the domain computer’s name in there, other times nothing.
Could it be wireless devices that we have on our wifi? We do have people authenticating with their AD information for faculty and staff on our secure wifi so that is another way they can get locked out, but I just didn’t know for what reason would it not be able to pull the computer or device name? Is there a way to get around this to maybe pull a different variable to get the device info?
Thanks
February 26, 2013 12:41 pm @ 12:41
Thanks Matt, glad you like it. However, the blank caller computer name has nothing to do with the script. Indeed chances are increased that it is a wireless device with invalid credentials causing the lockout. There is no way that I’m aware of that allows you to record your own variables, since it’s builtin to the auditing mechanism. If you’re using NPS for EAP/RADIUS authentication, have you looked through those logs? Also might be worth it to try increasing auditing for failure on the DC and look for those events when the lockout occurs. In ADDS, enable advanced features from the view menu, open the users account that was locked out, attribute editor tab, look at the attribute ‘pwdLastSet’, does that coincide around the time the lockout? If so I would start suspecting devices that use manual passwords like iphones, ipads, droids etc.
I found this on Technet forums http://social.technet.microsoft.com/Forums/en-US/winserversecurity/thread/6cd9fbd4-a2f0-4f70-a60a-6bc458267f09
1. There is no secure method for the KDC to get the remote machine’s name at the current time. If the client provides the name (as in NTLM), then it’s not trustworthy and can be spoofed. There are Unix-based hacking tools which spoof workstation name in NTLM auth requests.
2. DNS and NetBIOS reverse lookup are not secure and are not reliable- if we tried this, we’d have a high incidence of incorrect or missing information, and hurt performance.
3. Even if we chose to do add the name anyway, when we could, there’s no field for us to use to carry it in Kerberos AS REQ & TGS REQ messages- we’d have to overload some other field, and run a high risk of loss of compatibility with MIT’s reference implementation.
February 27, 2013 5:58 am @ 05:58
Thanks for the info, we are going to implement this into our institution since we have account lockout issues all the time. One more question…. how hard do you think it would be since this is a Powershell script already, to pull in either the OU the use account is in, or the email address and have it piped out to the email so it will tell our IT staff whether or not it is a faculty, staff or student by that information. We handle those issues separately so it would be a huge asset to us. Thanks again.
February 27, 2013 3:53 pm @ 15:53
This will put the username in the subject, and output the users OU and email address at the bottom of the email notification:
$Event = Get-EventLog -LogName Security -InstanceId 4740 -Newest 1
$Usr = $Event.Message -split [char]13
# [#] is the line number in the output
$Usr = $Usr[10]
# (#) is the substring of that line
$Usr = $Usr.substring(17)
$OU = Get-ADUser $Usr -Properties distinguishedname,cn | select @{n='ParentContainer';e={$_.distinguishedname -replace "CN=$($_.cn),",''}}
$Email = Get-ADUser $Usr -Properties mail
$MailBody= $Event.Message + "`r`n`t" + $Event.TimeGenerated + "`r`n`t" + $OU + "`r`n`t" + $Email.mail
$MailSubject= "User Account locked out: " + $Usr
$SmtpClient = New-Object system.net.mail.smtpClient
$SmtpClient.host = "ExchSvr.Domain.Local"
$MailMessage = New-Object system.net.mail.mailmessage
$MailMessage.from = "AcctLockNotify@domain.local"
$MailMessage.To.add("user@email.com")
$MailMessage.IsBodyHtml = 0
$MailMessage.Subject = $MailSubject
$MailMessage.Body = $MailBody
$SmtpClient.Send($MailMessage)
February 27, 2013 6:05 am @ 06:05
And maybe even to be able to capture the username to make as part of the subject so when we have it go right into our helpdesk ticketing system, it could get handled effectively. Is any of this easily done? I am still learning Powershell and it seems that this script is just outputting the details of the event log entry and not really having to pull usernames etc even though they are in the details. Would it be a separate query to extract those details?
February 27, 2013 1:36 pm @ 13:36
This otta do it:
$Event = Get-EventLog -LogName Security -InstanceId 4740 -Newest 1
$Usr = $Event.Message -split [char]13
# [#] is the line number in the output
$Usr = $Usr[10]
# (#) is the substring of that line
$Usr = $Usr.substring(17)
#$Usr = $Usr | Out-String
$MailBody= $Event.Message + "`r`n`t" + $Event.TimeGenerated
$MailSubject= "User Account locked out: " + $Usr
$SmtpClient = New-Object system.net.mail.smtpClient
$SmtpClient.host = "ExchSvr.Domain.Local"
$MailMessage = New-Object system.net.mail.mailmessage
$MailMessage.from = "AcctLockNotify@domain.local"
$MailMessage.To.add("user@email.com")
$MailMessage.IsBodyHtml = 0
$MailMessage.Subject = $MailSubject
$MailMessage.Body = $MailBody
$SmtpClient.Send($MailMessage)
June 11, 2013 8:11 pm @ 20:11
Hi TR
I tried to setup the script and run the trigger, but i didn’t receive any email of user account lock. below i paste the script which i changed, is there any thing i need to add
$SmtpClient = New-Object system.net.mail.smtpClient
$SmtpClient.host = “smtp.gmail.com”
$MailMessage = New-Object system.net.mail.mailmessage
$MailMessage.from = “alerts@aism.edu.my”
$MailMessage.To.add(“kirup@aism.edu.my”)
June 17, 2013 6:28 pm @ 18:28
Gmail requires authentication and uses port 587, not 25. Use this instead:
$EmailFrom = “alerts@aism.edu.my”
$EmailTo = “kirup@aism.edu.my”
$Subject = “Notification from XYZ”
$Body = “this is a notification from XYZ Notifications..”
$SMTPServer = “smtp.gmail.com”
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential(“username”, “password”);
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
Source: http://stackoverflow.com/questions/1252335/send-mail-via-gmail-with-powershell-v2s-send-mailmessage
February 28, 2013 7:47 am @ 07:47
Fantastic, works like a charm… i think i am having powershell issues though. For some reason the executionpolicy and the import of the activedirectory module are not staying. It seems when I close powershell it seems to forget these settings and I have never experienced that before so I guess I have some more digging. Because this is running as a triggered event script, the powershell console isn’t manually opened, so it is failing :(
February 28, 2013 8:38 am @ 08:38
Yeah, I figured it out. It seems for some reason that the import-module activedirectory doesn’t stay set for some reason?!?!? I am not sure if it should or not but if I specify that in the powershell script at the beginning when the scheduled tasks kicks off, it works as I want it too. As I said I am still learning Powershell and I don’t know if this is by design or not.
February 28, 2013 9:23 am @ 09:23
Weird, that doesn’t happen to me on my Windows 2008 R2 DC. Go back into the task scheduler properties, edit the action, under Add arguments put this in: -executionpolicy unrestricted -command import-module ActiveDirectory -file C:\PathToYourScriptsFolder\acc_lockout.ps1
March 13, 2013 6:12 am @ 06:12
Hey Travis,
I have one more thing I am trying to pull out of this script if at all possible. In the Event Log it is already pulling the computer name (if it can detect it). I would like to be able to somehow call that string value up and resolve that name to an IP address. This would give us great visibility as to where the PC is physically located on our network. I know this will pull IP:
Get-ADComputer -Identity infosys -Properties IPv4Address | ft IPv4Address
But not sure how to incorporate that into the string value of the event log.
Any thoughts?
Thanks…
April 4, 2013 4:44 am @ 04:44
TR,
I’m trying this very same thing with the added step of using SCOM 2007R2 to call the script in either a console task or recovery task for an account lockout (4740) but issue seems to be passing the username to the vbs or ps script to unlock. Any thoughts.
April 4, 2013 8:17 am @ 08:17
I’m not familiar with SCOM so bare with me. If I understand correctly, you’re calling this script to get the username of the locked out user and pass it to another script? Please clarify.
If that’s the case take a look at this
http://stackoverflow.com/questions/1864128/load-variables-from-another-powershell-script
September 6, 2013 7:04 am @ 07:04
Hey Travis, I have been using your script for notifying us of account lockouts for some time now. We are noticing one thing that we would love to have to take some of the administrative tasks off of IT. Is there any way possible since the student’s email address and maybe a separate text informing them what happened in the body of the email. I know their email address is contained in the Event Log entry, to have the powershell script automatically email them as well so we don’t have to do it manually. See the students exist in our on-premise AD as well but their mailboxes do not which makes this ideal so they will still be able to logon to their email accounts to be notified about the lockout and what to do.
September 6, 2013 1:30 pm @ 13:30
Hey Matt, back again so soon? ^_^
I don’t believe the email address is in the actual account lockout event but it can be queried. Does the user account contain an email address attribute in your on-premise Active Directory? If not, is their email address syntax always [ADusername]@[domain.com]?
Ideally what I’m thinking if the user accounts have an email address attribute in your on-premise AD, is we use the $Usr username variable which I mentioned in a previous comment, to query the email address. This can be accomplished very easily with:
[code language=”powershell”]$UsrEmail = Get-ADUser $Usr -Properties mail[/code]
Then all you have to do is change the line
[code language=”powershell”]$MailMessage.To.add("user@email.com")[/code]
to
[code language=”powershell”]$MailMessage.To.add($UsrEmail.mail)[/code]
If you want to carbon copy your admin team then you can just add a line like $MailMessage.cc.add(“AdminTeam@email.com”) before the $SmtpClient.Send($MailMessage)
Is that what you’re looking for?
September 6, 2013 1:33 pm @ 13:33
Yes I should re post what the code is now, I believe you modified it to pull the ad name so it shows amended to the event log output. I would just like to have it automatically email then student so I don’t have to do it manually. I will get back up with you on Monday. Have a good weekend!
September 9, 2013 5:49 am @ 05:49
Here is what we have right now and it works very well. What I would like to do is send a copy to the student with different text because they won’t know what the output of the event log means. I’d rather send them something more simplified. How could I accomplish this?
Thanks so much!
import-module activedirectory
$Event = Get-EventLog -LogName Security -InstanceId 4740 -Newest 1
$Usr = $Event.Message -split [char]13
# [#] is the line number in the output
$Usr = $Usr[10]
# (#) is the substring of that line
$Usr = $Usr.substring(17)
$Usr2 = Get-ADUser $Usr | Select-Object -ExpandProperty name
$OU = Get-ADUser $Usr -Properties distinguishedname,cn | select @{n=’AD OU: ‘;e={$_.distinguishedname -replace ‘^.+?,(CN|OU.+)’,’$1′}}
$Email = Get-ADUser $Usr -Properties mail
$TelephoneNumber = Get-ADUser $Usr -Properties telephoneNumber | Select-Object -ExpandProperty telephoneNumber
$MailBody= $Event.Message + “`r`n`t” + $Event.TimeGenerated + “`r`n`t” + $OU + “`r`n`t” + $Email.mail + “`r`n`t” + “Direct: $TelephoneNumber” + “`r`n`t” + “`r`n`t” + “*ATTENTION* Do not automatically unlock the user’s account, please follow up with them first”
$MailSubject= “User Account Locked Out: ” + $Usr2
$SmtpClient = New-Object system.net.mail.smtpClient
$SmtpClient.host = “newport.wesley.int”
$MailMessage = New-Object system.net.mail.mailmessage
$MailMessage.from = “AcctLockNotify@wesley.edu”
$MailMessage.To.add(“helpdesk@wesley.edu”)
$MailMessage.IsBodyHtml = 0
$MailMessage.Subject = $MailSubject
$MailMessage.Body = $MailBody
$SmtpClient.Send($MailMessage)
September 6, 2013 8:13 pm @ 20:13
Thank you for this script, this worked very well.
September 7, 2013 6:35 am @ 06:35
Took it an extra step and trigger this task “on an event” selected log: Security event ID 4740. Whenever an account is locked and the entry is written into the event log, we’re noticed via email. Thanks again and thought I’d share this extra step.
September 11, 2013 6:55 am @ 06:55
So what do you think of my code I posted? How can we add a CC to the student and say something different to them?
September 12, 2013 12:56 pm @ 12:56
Basically what we are trying to do is within the same powershell script we want to send 2 different emails to 2 different people. We don’t want to send 2 people the same email. One person is technical, the other is not. So we were hoping to be able accomplish this but so far our testing hasn’t worked, the script seems to be stopping after the first send mail command.
September 12, 2013 9:14 pm @ 21:14
I’m sorry there has not been much time for me to pay attention to the site. Been busy with work and preparing for a motorcycle ride this Saturday. Basically I think what needs to be done is there needs to be a second set of $MailMessage variables which are passed to the smtpClient Send function. Will post the code when I can pay more attention to this.
September 13, 2013 4:53 am @ 04:53
OK thanks, no worries. We have a powershell guy here that has been playing around with this and trying to get something to work but it seems that after the first mail function the script just ends and doesn’t even proceed with the second one. Here is what he came up with which is a slight variation of yours but it should give you an idea of what we want to do. It used the built in powershell send message functions but you’ll get the jist. Thanks man.
$Event = Get-EventLog -LogName Security -InstanceId 4740 -Newest 1
$Usr = $Event.Message -split [char]13
$Usr = $Usr[10]
$Usr = $Usr.substring(17)
$Usr2 = Get-ADUser $Usr | Select-Object -ExpandProperty name
$OU = Get-ADUser $Usr -Properties distinguishedname,cn | select @{n=’AD OU: ‘;e={$_.distinguishedname -replace ‘^.+?,(CN|OU.+)’,’$1′}}
$UsersEmail = Get-ADUser $Usr -Properties mail | select -ExpandProperty mail
$OfficePhone = Get-ADUser $Usr -Properties officephone | Select-Object officephone
$MailBody = $Event.Message + “`r`n`t” + $Event.TimeGenerated + “`r`n`t” + $OU + “`r`n`t” + $Email.mail + “`r`n`t” + “Direct: $TelephoneNumber” + “`r`n`t” + “`r`n`t” + “*ATTENTION* Do not automatically unlock the user’s account, please follow up with them first”
$MailSubject = “User Account Locked Out: ” + $Usr2
$MailServer = “newport.wesley.int”
$MailSender = “AcctLockNotify@wesley.edu”
$MailHelpdesk = “helpdesk@wesley.edu”
Send-MailMessage -From $MailSender -Body $MailBody -Subject $MailSubject -To $MailHelpdesk -SmtpServer $MailServer
$test =”$usr”
$test | Out-File “c:\$usr.txt”
$UserSubject = “Wesley College Account Locked Out.”
$ToUserBody = “$Usr2 Your Wesley WiFi & PC logon account has been locked out. Please contact the IT Department at (302) 736-4199, or come to the IT Department to have your Wesley account unlocked.”
Send-MailMessage -From $MailSender -Body $ToUserBody -To $UsersEmail -Subject $MailSubject -SmtpServer $MailServer
September 13, 2013 2:33 pm @ 14:33
[code language=”powershell”]$Event = Get-EventLog -LogName Security -InstanceId 4740 -Newest 1
$Usr = $Event.Message -split [char]13
$Usr = $Usr[10]
$Usr = $Usr.substring(17)
$UsrProperties = Get-ADUser $Usr -Properties *
$EmailUsr = $UsrProperties.mail
$OU = $UserProperties.distinguishedname, $UserProperties.cn | select @{n=’AD OU: ‘;e={$_.distinguishedname -replace ‘^.+?,(CN|OU.+)’,’$1′}}
$EmailUsr = $UsrProperties.mail
$EmailHD = “helpdesk@wesley.edu”
$OfficePhone = $UsrProperties.telephonenumber
$Username = $UsrProperties.SamAccountName
$MailBodyHD = $Event.Message + “`r`n`t” + $Event.TimeGenerated + “`r`n`t” + $OU + “`r`n`t” + $UsrProperties.mail + “`r`n`t” + “Direct: $TelephoneNumber” + “`r`n`t” + “`r`n`t” + “*ATTENTION* Do not automatically unlock the user’s account, please follow up with them first” | Out-String
$MailBodyUsr = "Your Wesley WiFi & PC logon account (" + $Username + ") has been locked out. Please contact the IT Department at (302) 736-4199, or come to the IT Department to have your Wesley account unlocked." | Out-String
$MailSubjectHD = “User Account Locked Out: ” + $Username
$MailSubjectUser = “Wesley College Account Locked Out.”
$MailServer = “newport.wesley.int”
$MailSender = “AcctLockNotify@wesley.edu”
$MailHD = “helpdesk@wesley.edu”
# Send mail to the helpdesk
Send-MailMessage -From $MailSender `
-To $EmailHD `
-Subject $MailSubjectHD `
-Body $MailBodyHD `
-SmtpServer $MailServer
#Send mail to the user
Send-MailMessage -From $MailSender `
-To $EmailUsr `
-Subject $MailSubjectUser `
-Body $MailBodyUsr `
-SmtpServer $MailServer[/code]
September 16, 2013 4:59 am @ 04:59
Awesome, thanks again. I just put it in place this morning so we will see how it goes :) I love this script.
September 19, 2013 7:07 am @ 07:07
Well the script isn’t emailing the student. Any idea why?
September 19, 2013 7:10 am @ 07:10
We had the same issue with the version of the script we attempted to create, it seems to just “stop” after emailing the first person. Individually both commands work fine and email both parties if ran separately. That doesn’t help us though, we need it to occur in the same operation.
September 19, 2013 10:22 am @ 10:22
Nevermind, I think it is working after all.
November 4, 2013 7:09 am @ 07:09
Had UAC enabled, had to check the box that says “run with highest permissions” on the event viewer scheduled task to get this to work.
December 12, 2013 9:11 am @ 09:11
I tried a few of the examples here and used my own information and just copied and pasted everything else. I get the email notification, but none of the variables and the body aren’t displaying properly. The subject is: “User Account locked out: ” and the body is completely empty. Am I missing something? Thanks in advance!
-Jon
February 5, 2014 5:33 am @ 05:33
I love it! Thank you sooo much!
February 5, 2014 5:33 am @ 05:33
I love it! Thank you sooo much!
July 4, 2014 1:47 am @ 01:47
Thanks, this is set up very nicely. My only issue is that the script is working normally and I’m getting the e-mail when an account is locked out, but the body of that e-mail is blank. I thought it was just because I was testing the script, but I locked out an account manually and it sent, but was still blank. Any idea?
July 4, 2014 2:29 am @ 02:29
Hi Jeff,
Can you check the output of $MailBody and $Event.Message after “$MailBody= $Event.Message + “`r`n`t” + $Event.TimeGenerated”?
Try using Write-Host $Mailbody or Write-Host $Event.Message if you’re using PowerShell ISE.
July 4, 2014 1:47 am @ 01:47
Thanks, this is set up very nicely. My only issue is that the script is working normally and I’m getting the e-mail when an account is locked out, but the body of that e-mail is blank. I thought it was just because I was testing the script, but I locked out an account manually and it sent, but was still blank. Any idea?
July 4, 2014 2:29 am @ 02:29
Hi Jeff,
Can you check the output of $MailBody and $Event.Message after “$MailBody= $Event.Message + “`r`n`t” + $Event.TimeGenerated”?
Try using Write-Host $Mailbody or Write-Host $Event.Message if you’re using PowerShell ISE.
October 16, 2014 8:58 am @ 08:58
Hi Travis,
First of all this is a fantastic script and it is working very fine.
How can I configure this script to send alert only when a specific account get locked out. (ex: Tharundev) ?