Get Report of Active Directory Locked Accounts and Machine they logged in from

Story:

I got some clients  that have reported some of their users being locked out and not able to discover how is this happening or which device its getting locked on.

Symptoms:

The user lock happens after you setup your GPO policy to get user locked after failing to login for X times with the correct password.

When user gets locked, they either can’t login or get prompted to re-enter their password in Outlook for example not knowing they have been locked. 

Hard to Find Out:

There’s no easy way to figure out what’s really happening and why the user got locked out specially if the account is being used on multiple devices e.g. (Phone, iPad, Desktop ..etc). Unless you have an auditing or an AD monitoring software that will log all auditing attempts to an external party and tell you where exactly the user is coming from, it’s a not an easy task to find out where is this taking place.  

Solution: 

1- Enabling Relevant Logs

In order for this to work, you’ll need to enable some Auditing logs on the Default Domain Controller Group Policy

Go to  >> Computer Configuration >> Windows Settings >> Security Settings >> Advanced Audit Policy Configuration >> Audit Policies >> Account Management >> Double Click on Audit User Account and enable both Success and Failure.

Once you applied this policy, you’ll need to force update your DCs , Sign out and back in and you’ll start noticing that in Event Viewer / Security the event 4740 and 4625 will start appearing .

The event 4740 will show you the locked user and the machine it tried to login from. 

The event 4625 will show you the path to the process/application that tried to login with your account. 

So to make this more benefitial I ended up writing a script that will get triggered by Task Scheduler in the case of Event 4740 being reported.

The script will search AD for any locked account. will scan the Logs for the user’s event and find the machine the user tried to login from and generate a report with all these details then send it to a target email in Excel forma after converting it using ImportExcel module.

Note that you must have a local SMTP Server for the email to be sent. If not you can just get the CSV and send it manually. 

 

2- Finding the relevant event

3- Finally The script

The script is simple so feel free to modify it, improve it or share it with others. 

Almost done
Script below 80%

#Report NTLM Authentication Failure for users
$ReportTime = ([datetime]::Today).ToString(“MM-dd-yyyy”)

#Generate report
$Report = [System.Collections.Generic.List[Object]]::new()

$LockedAccount = (Search-ADAccount -LockedOut -UsersOnly)
$i = 0
foreach ($User in $LockedAccount){

$i ++
Write-Progress -Activity “Gathering Logon info” -Status “Checking Login info for: $($User.Name)” -PercentComplete (($i / ($LockedAccount | Measure-Object).Count) * 100)
if($User.LockedOut){

$Event = Get-WinEvent -FilterHashtable @{ logname = ‘Security’; id = 4740 } -MaxEvents 500 | Select-Object TimeCreated,
@{ Name=’TargetUserName’; Expression={$_.Properties[0].value}},
@{ Name=’LogonMachine’; Expression={$_.Properties[1].value}} | Where {$_.TargetUserName -eq $User.SamAccountName}
}

$ReportLine = [PSCustomObject][Ordered]@{
Count = $i
ReportedUser = $User.Name
UPN = $User.UserPrincipalName
UserIsLocked = $User.LockedOut
LastLogonDate = $user.Lastlogondate
MachineName = $Event.LogonMachine -join ‘,’
‘Access Failure Time’ = $Event.TimeCreated -join ‘,’
‘Report Date’ = $ReportTime
}
$Report.Add($ReportLine)
}

$MailBody = “
<html><body>
<font color=’006400′> Dear Team, `
Please find attached a report of all locked out users including machine used for the login … `
If any issue you can report it via the ticketing system.</font>
<body><html>

#Eexport in CSV
$Report | Export-csv “C:\Reports\LockOutReport_$ReportTime.cscv” -NoTypeInformation

#Eexport in Excel Format
$Report | Export-Excel “C:\Reports\LockOutReport_$ReportTime.xlsx” -WorksheetName LogonFailure -TableName LogonFailure -AutoSize

$Exported = “C:\Reports\LockOutReport_$ReportTime.xlsx”

$CC = @(‘User2@domain.com’)
#
Get-ChildItem $Exported | send-mailmessage -from “system@domain.com” -to “user1@domain.com” -cc $cc -subject “Users LockOut Report $ReportTime” -body “$MailBody” -Priority High -smtpServer relay.domain.com -BodyAsHtml

Link to Github:

 

https://github.com/moh30ly/powershell/blob/main/ActiveDirectoryLockOutNotification

4- Attach Task to an Event

5- Get The Report

Checking and Providing Full and SendAs delegate access on O365 Exchange Online

Delegate Permissions

This is a code that I have wrote recently to check if an account have Full and SendAs access on target mailboxes in CSV and give the option to choose whether to provide this access or not.

Checking First:

You’ll need to provide two things to get this code working, First the Source account that will need access to the mailboxes. in this case referred to as “ServiceAccount”.

CSV List of Mailbxoes:

You’ll need to provide list of Mailboxes of the users you’d like to provide access to, the List must be user’s Identity either UPN or SMTP would be fine.

The Service account’s Identity must be the UPN attribute.

If you would like to improve this code please do comment or get in touch directly

Thanks

#Connect to Exchange
#Connect & Login to ExchangeOnline (MFA)

try
{
    Get-Clutter -Identity user@domain.com -ErrorAction Stop > $null
}
catch 
{
Connect-ExchangeOnline
}

    $Users = import-csv 'C:\CSV\MailboxListIsHere.csv'
    $ServiceAccount = 'Your Account that will access other Mailboxes' #// Please change the SVC account before running the code
    

        foreach ($User in $users)
        {
            $Mailbox = $User.Identity
            
            #Checking Full Access
            $Full = Get-MailboxPermission -Identity $Mailbox -User $ServiceAccount
            If ($Full.AccessRights -eq "FullAccess")
            {
                Write-Host -f Green $($ServiceAccount) "Already has Full access to $Mailbox."}
            
                    Else
                    {
                        $Answer1 = Read-Host "Do you want to assign $($ServiceAccount) Full access to $Mailbox (Yes or No)"
                        If ($Answer1 -eq "Yes")
                            {
                                Try{
                                    Add-MailboxPermission -Identity $Mailbox -User $ServiceAccount -AccessRights FullAccess
                                    Write-Host -f DarkGreen $($ServiceAccount) "Send-as access has been added to $Mailbox"
                                    }
                           
                            Catch{ ($Full.AccessRights -eq "FullAccess")}
                            
                        }
                        
                    }
                
                $SendAs = Get-RecipientPermission -Identity $Mailbox -Trustee $ServiceAccount -AccessRights SendAs
                if($SendAs.AccessRights -eq "SendAs") {
                    Write-Host -f Green $($ServiceAccount) "Already has SendAs access to $Mailbox."
                    }
                    Else
                    {
                        $Answer2 = Read-Host "Do you want to assign $($ServiceAccount) Send-as access to $Mailbox (Yes or No)"
                        If ($Answer2 -eq "Yes")
                            {
                                Try{
                                    Add-RecipientPermission -Identity $Mailbox -AccessRights SendAs -Trustee $ServiceAccount
                                    Write-Host -f Green $($ServiceAccount) "has Send-as access on $Mailbox"
                                }
                            Catch{($SendAs.AccessRights -eq "Sendas")}}
                            else{Exit}
                        }
                    }
        }