Stale admin accounts are silent security vulnerabilities, acting as unlocked backdoors for attackers in your Microsoft 365 tenant or hybrid environment. These forgotten privileged accounts often escape monitoring while posing serious compliance and breach risks.
In this guide, you’ll learn exactly how to find stale accounts in Active Directory, audit them efficiently, and implement automated cleanup using PowerShell, Microsoft Graph, and RMM tools to maintain a secure environment.
Procedures to find and clean up stale accounts in Active Directory
A stale admin account is any privileged identity with no recent activity, which can be Microsoft 365 global admins or privileged roles with 30+ days of no sign-ins, local Windows 11 administrator accounts on devices with no recent use, or service accounts lacking interactive logins or clear ownership documentation.
Former employee accounts that were not fully deprovisioned also pass as stale accounts. Proactively finding and cleaning up these accounts in Active Directory prevents security breaches and keeps your environment compliant.
📌 Use case: Perform this cleanup during quarterly security audits, after employee departures, or when preparing compliance reports like an Office 365 inactive accounts 30-day review. Monthly checks are ideal for catching risks early, especially when generating inactive user reports.
📌 Prerequisites: Before starting, ensure you have admin access to all Microsoft 365 tenants, PowerShell modules (like Microsoft Graph and AzureAD/MSOnline), enabled Microsoft Entra audit logs, and local admin tools for endpoint checks. For automation, leverage your RMM platform (for example, NinjaOne) to centralize scans and enforce policies.
We recommend checking ⚠️ Things to look out for before proceeding.
📌 Recommended deployment strategies:
Method 1: Use Microsoft Graph or AzureAD PowerShell to audit cloud admins
PowerShell gives you direct access to cloud activity data, making it the fastest way to find stale admin accounts.
📌 Use cases: Perform this audit quarterly for compliance checks, immediately after employee offboarding, or when preparing monthly security reports. It’s especially valuable when you need custom 30-day Office 365 inactive accounts reports that native tools can’t generate.
Step-by-step procedure:
- Open PowerShell (Admin).
- Press Win + X, then select Windows Terminal (Admin).
- Run this script to connect to Microsoft Graph.
Connect-MgGraph -Scopes "Directory.Read.All", "AuditLog.Read.All"
- Authenticate when prompted.
- List all admin accounts:
$admins = Get-MgRoleManagementDirectoryRoleAssignment |
Where-Object { (Get-MgDirectoryRole -DirectoryRoleId $_.RoleDefinitionId).DisplayName -match "Admin" } |
ForEach-Object { Get-MgUser -UserId $_.PrincipalId }
- Check the last sign-in date.
$results = @()
foreach ($admin in $admins) {
$lastSignIn = Get-MgUserSignIn -UserId $admin.Id -All |
Sort-Object CreatedDateTime -Descending |
Select-Object -First 1
$daysInactive = if ($lastSignIn) { (New-TimeSpan $lastSignIn.CreatedDateTime).Days } else { 999 }
$results += [PSCustomObject]@{
User = $admin.UserPrincipalName
LastSignIn = if ($lastSignIn) { $lastSignIn.CreatedDateTime } else { "Never" }
DaysInactive= $daysInactive
RiskStatus = if ($daysInactive -ge 30) { "STALE" } else { "Active" }
}
}
- It is a stale account if it’s 30 or more days since the last sign-in.
- Export flagged accounts:
$results | Where-Object { $_.RiskStatus -eq "STALE" } |
Export-Csv "C:\Audit\Stale_Admins_$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
After the Audit, you’ll have a CSV file listing all stale user accounts with admin privileges that have been inactive for 30+ days. Immediately deactivate high-risk accounts using PowerShell or Microsoft Admin Center, remove admin roles from flagged users, document your findings in your RMM platform, and schedule recurring audits.
Method 2: Identify local admin accounts on Windows devices via PowerShell
Unmonitored local admin accounts on Windows devices are prime targets for attackers. This method can configure direct queries to the Windows SAM database (no cloud dependencies).
📌 Use cases: Perform this audit monthly on all endpoints, especially after employee departures or during vulnerability scans. Critical for identifying stale accounts with persistent local access that bypass cloud monitoring.
Step-by-step procedure:
- In PowerShell (Admin), run this script to list local admins on a Windows 11 device:
Get-LocalGroupMember -Group "Administrators" |
Select-Object Name, PrincipalSource
- Output should show domain/cloud (AzureAD) vs. local accounts.
- Check last logon time:
Get-LocalUser |
Where-Object {$_.Enabled -eq $true} |
Select-Object Name, LastLogon
- Disable or remove stale accounts (30+ days inactive):
Disable-LocalUser -Name "LegacyAdmin" # First disable
Remove-LocalUser -Name "LegacyAdmin" # Then delete permanently
- Scale to all devices using the RMM script (such as NinjaOne):
$computers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name
Invoke-Command -ComputerName $computers -ScriptBlock {
Get-LocalUser | Where-Object {
($_.LastLogon -lt (Get-Date).AddDays(-30)) -and
($_.Name -ne "Administrator")
} | Disable-LocalUser
}
After the audit, you can identify local stale user accounts with admin rights. Immediately, disable high-risk accounts, rotate passwords using LAPS (Local Administrator Password Solution), document in your RMM platform with risk flags, and schedule recurring scans to prevent new stale accounts.
Method 3: Use CMD and Registry auditing for local admin persistence
When PowerShell isn’t available, these manual methods can uncover hidden stale accounts.
📌 Use cases: Use this for quick checks on individual Windows 11 devices during incident response or when PowerShell access is restricted. Ideal for identifying stale accounts that evade automated tools.
Step-by-step procedure:
- List local admins via Command Prompt (Admin).
- Search Command Prompt (Admin) via Search on the taskbar.
- Run this command:
net localgroup administrators
- Output should show all users with admin rights on the current device.
- Check the last login for a specific account using this Security Event Log:
wevtutil qe Security "/q:*[System[(EventID=4624)] and EventData[Data[@Name='TargetUserName']='oldadmin']" /f:text /c:1
- Replace oldadmin with the suspect username. This script will show the last successful login.
- Manual registry check (advanced fallback):
reg save HKLM\SAM sam.bak
reg save HKLM\SYSTEM system.bak
- Use offline SAM viewers (e.g., SAMInsight) to analyze \SAM\Domains\Account\Users\Names.
⚠️ Warning: Editing the Registry incorrectly can lead to serious system instability. Always back up your Registry or create a system restore point before proceeding. Review the ⚠️Things to look out for section to learn more.
Method 4: Use GPO to prevent local admin persistence
GPOs give you centralized control to prevent attackers from abusing stale local admin accounts.
📌 Use case: Deploy this during initial environment hardening, after identifying stale accounts, or when preparing for compliance audits (e.g., SOC 2). Critical for enforcing least privilege at scale.
Step-by-step procedure:
- Restrict local Administrators group membership.
- Open Group Policy Management Editor (gpedit.msc).
- Go to Computer Configuration > Policies > Windows Settings > Security Settings > Restricted Groups.
- Add the Administrators group, then define permitted members via:
DOMAIN\SecuredAdmins (Allowed admin group)
- This prevents unauthorized users from elevating privileges.
- Deny logon for stale/risky accounts.
- Go to the same GPO, then navigate to the following: Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies > User Rights Assignment.
- Modify Deny log on locally:
DOMAIN\OldAdmin
DOMAIN\Contractor_2020
- This blocks specified accounts from interactive login.
- Enforce LAPS for password rotation.
- Install LAPS on domain controllers:
Install-WindowsFeature -Name "RSAT-AD-PowerShell"
Install-Module LAPS -Force
- Configure LAPS policy:
Computer Configuration > Policies > Administrative Templates > LAPS
Enable "Password Settings" and "Local Account Password Management"
After implementation, within 90 minutes (next GPO refresh), stale user accounts will lose admin rights/logon access, local admin passwords auto-rotate every 30 days via LAPS, and surface attacks will shrink by blocking pass-the-hash risks.
Method 5: Automate and log audit trail and cleanup verification
Automation transforms stale account management from a reactive chore to proactive security.
📌 Use cases: Implement this for continuous compliance in multi-tenant environments, especially after initial audits or during monthly security cycles. Essential for MSPs managing 100+ endpoints.
Step-by-step procedure:
- Log all actions with PowerShell:
Start-Transcript -Path "C:\AuditLogs\$(Get-Date -Format 'yyyyMMdd').txt" -Append
- Run your audit script (e.g., Method 1 or 2)
Stop-Transcript
- This creates tamper-resistant records for compliance.
- Schedule in an RMM Platform (e.g., NinjaOne):
- Perform monthly admin audits.
- Use the PowerShell script from Method 1 to find stale accounts
- Auto-disable accounts that are inactive for 30 days or more:
- Perform monthly admin audits.
$staleUsers = Import-Csv "C:\Audit\Stale_Admins.csv"
$staleUsers | ForEach-Object {
if ($_.DaysInactive -ge 30) {
Set-MgUser -UserId $_.User -AccountEnabled:$false
}
}
- Export and archive reports:
Compress-Archive -Path "C:\AuditLogs\*.txt" -DestinationPath "\\NAS\Archives\StaleAdmins_$(Get-Date -Format 'yyyyMM').zip"
- Alert on policy violations:
- Trigger an email if a new admin is created outside the IT team.
$newAdmin = Get-MgDirectoryRoleMember -DirectoryRoleId "role-id" |
Where-Object { $_.CreatedDateTime -gt (Get-Date).AddHours(-1) }
if ($newAdmin) {
Send-MailMessage -To "[email protected]" -Subject "ALERT: Unauthorized Admin Created" -Body $newAdmin.UserPrincipalName
}
After it is automated, your system will auto-flag stale user accounts monthly, disable inactive accounts after 30 days, archive encrypted logs for compliance, alert in real-time for policy violations, and generate executive reports via RMM dashboards.
⚠️ Things to look out for
This section highlights potential challenges to keep in mind while following this guide.
Risks | Potential Consequences | Reversals |
1. Inconsistent Sign-in Data | False positives disabling active admins | 1. Verify that unified audit logs are enabled. 2. Run |
2. Local Admin Detection Failure | Missed stale accounts on endpoints | 1. Grant Administrator rights to the RMM agent. 2. Use |
3. Protected Account Removal | Critical service disruption | 1. Check the msDS-ProtectedFromAccidentalDeletion flag.2. Validate GPO enforcement with |
4. Graph API Authentication Errors | Script failures during automation | 1. Validate scopes with Get-MgContext .2. Use |
5. Registry Corruption | The operating system becomes unstable, and booting up fails. | Back up the registry* or create a System Restore Point. *Open Registry Editor (regedit), then select File > Export. Watch How to Back Up and Restore Windows Registry for more details. |
6. GPO Over-Enforcement | Locked out of all devices | 1. Preserve the break-glass account in GPO. 2. Revert via |
7. Over-Aggressive Automation | Accidental mass disablement of active users | 1. Implement a 72-hour grace period in scripts. 2. Restore from Entra ID recycle bin (up to 30 days). |
Key considerations when auditing stale accounts
Balance security and operational continuity with these critical safeguards.
Break-glass accounts
Always exclude at least one global admin account per tenant from automated cleanup (e.g., [email protected]). Store credentials in a sealed envelope or password vault, and verify quarterly via:
Get-MgUser -UserId "[email protected]" | Select AccountEnabled
This will prevent a complete lockout during misconfigurations or ransomware attacks.
Privileged Identity Management (PIM)
Enable Just-in-Time access in Microsoft Entra ID to eliminate standing admin roles. You can do this by navigating to Entra ID > Identity Governance > Privileged Access, converting admins to eligible roles requiring MFA-activated time limits.
Alerting integration
Connect Microsoft Sentinel/Defender for Cloud Apps to detect dormant accounts. Create these analytics rules:
SigninLogs
| where TimeGenerated > ago(90d)
| summarize LastLogin = max(TimeGenerated) by UserPrincipalName
| where LastLogin < ago(30d)
Email/SMS alerts for Office 365 inactive accounts, 30-day report violations.
Service accounts
Tag non-interactive accounts with [SERVICE] prefix and exempt them from standard inactivity policies:
Set-MgUser -UserId "svc_sqlbackup" -Department "ServiceAccount-Exempt"
The audit via:
Get-MgUser -Filter "startsWith(Department,'ServiceAccount')"
Audit log retention
Extend unified audit logs to 365 days, which requires an Entra ID P2 license. You can check this by going to Azure Portal > Microsoft Entra ID > Monitoring > Diagnostic settings. Then, enable AuditLogs and SignInLogs with 1-year retention.
Compliance: Meets FINRA/SOC 2 requirements for finding inactive users in O365.
Make Active Directory management easier with NinjaOne’s help
NinjaOne streamlines stale account auditing with integrated automation.
- Script Deployment: Automate PowerShell audits (Methods 1-2) across tenants and endpoints.
- Local Account Detection: Scan Windows 11 devices for unauthorized admins, flagging stale accounts in real-time.
- Scheduled Reports: Generate monthly Office 365 inactive accounts 30-day reports with one-click exports.
- Policy Enforcement: Apply GPO-equivalent restrictions (Method 4) to enforce least privilege.
- Alerting: Get notified of new local admins or 30+ day inactive global admins.
- Security Baselines: Enforce CIS/NIST controls to auto-disable high-risk accounts.
Secure Your Environment: Find stale accounts in Active Directory
Auditing and removing stale admin accounts is foundational to identity security, and this guide equips you with proven methods to eliminate these hidden risks.
By implementing these techniques, you’ll lock down forgotten backdoors that attackers can exploit, and meet compliance demands like SOC 2 or GDPR. Start your monthly audits today to maintain a secure, audit-ready environment.
Related topics