Stale And Orphaned Accounts
How Stale And Orphaned Accounts works
Stale and orphaned accounts are enabled logins that outlived their purpose, from departed staff to service accounts whose system is gone. Others carry passwords older than policy, or rights piled up across role changes. They are a joiner-mover-leaver failure - the create and the move steps fire reliably because someone is waiting on them, while the leave and the tidy-up steps have no impatient requester, so they slip.
The attacker gains a login nobody watches. A departed employee’s enabled account can be phished, sprayed or reused with a known old password and its activity looks like a normal user, because on paper it is one. A service account left behind by a dead system often has a stale, never-rotated password and lingering rights, and its interactive use raises no flag because no owner remains to notice. It is easy to miss because absence is silent: there is no error for the disable that never happened, and permission accretion from role changes is additive by default - each move grants, none revokes.
Stale And Orphaned Accounts in practice
Report enabled accounts by last logon and password age
Establish the dormant and stale-password population before reconciling against people. Pull last-logon-timestamp and password-set date for every enabled account.
$stale = (Get-Date).AddDays(-90)
Get-ADUser -Filter 'Enabled -eq $true' -Properties LastLogonTimestamp, PasswordLastSet, Description |
Select-Object SamAccountName,
@{n='LastLogon';e={[datetime]::FromFileTime($_.LastLogonTimestamp)}},
PasswordLastSet, Description |
Where-Object { $_.LastLogon -lt $stale -or $_.PasswordLastSet -lt (Get-Date).AddDays(-365) } |
Sort-Object LastLogon |
Export-Csv .\stale-enabled.csv -NoTypeInformation
Reconcile the directory against HR leavers
An account is orphaned when the person is gone but the login is not. Join the enabled-account export to the authoritative HR leaver feed and keep the accounts HR no longer knows.
# hr-leavers.csv: employee_id,sam,termination_date
# enabled-accounts.csv: sam,enabled,last_logon
join -t, -1 2 -2 1 \
<(sort -t, -k2 hr-leavers.csv) \
<(sort -t, -k1 enabled-accounts.csv) \
| awk -F, '$5=="TRUE" { print $2" enabled after termination "$3" <- orphan" }'
Separate orphaned service accounts from their dead hosts
A service account whose system was decommissioned should have gone with it. Cross the service-account list against the live asset inventory and flag those whose owning host no longer exists.
Service account Documented owner host In asset inventory? Verdict
svc-backup-old bkp01.lab.internal no (decommissioned) orphan - retire
svc-sql-report sql02.lab.internal yes keep - in use
svc-scan scan01.lab.internal no orphan - retire
Rule: no live owning host + no recent logon = orphaned service account.
Confirm zero recent logons before disabling so a shared account still
in quiet use is not cut blind.
Surface permission accretion across role changes
A mover keeps old rights unless someone removes them. Compare group membership against the account’s current role profile to expose the residue.
$expected = Get-Content .\role-profile-finance.txt # groups a finance role should hold
Get-ADPrincipalGroupMembership 'jdoe' |
Select-Object -ExpandProperty name |
Where-Object { $_ -notin $expected } |
ForEach-Object { "$_ <- held but not in current role profile" }
How to fix and prevent Stale And Orphaned Accounts
- Drive disable from the HR leaver event
- Trigger account disable automatically from the termination record within a defined SLA, not from a quarterly sweep that runs weeks late.
- Disable first and delete after a hold period, so an erroneous disable is reversible and any owned resources can be reassigned.
- Give every service account a named owner and an expiry
- Tie each service account to a current owner and an owning system; when the system is decommissioned, retire the account in the same change.
- Report last logon and password age on a schedule
- Recurring dormancy and stale-password reports catch what the process misses; auto-disable past the dormancy threshold with an owner exception path.
- Recertify access at each move, revoking as well as granting
- Make role change remove the outgoing role’s rights, and run periodic access recertification so accretion is corrected rather than accumulated.
- Reconcile the directory against HR and asset records
- Treat HR as authoritative for people and the asset inventory as authoritative for service-owning hosts; investigate every account that matches neither.
Last updated