Home→Blog→Active Directory Health Check: PowerShell Commands...
Security Assessment

Active Directory Health Check: PowerShell Commands Every Australian IT Team Should Run

The essential PowerShell commands for an Active Directory health check, mapped to ACSC Essential Eight and ISM controls for Australian IT and security teams.

Alpesh Nakar
May 23, 2026
10 min read
🇦🇺 Australian Context
📜 ACSC Essential Eight, ISM, ASD

⚡TL;DR

  • •A structured PowerShell health check can surface the most critical Active Directory security gaps in under two hours.
  • •Stale privileged accounts, Kerberoastable service accounts, and accounts with non-expiring passwords are the highest-risk findings in Australian AD environments.
  • •Domain controller replication failures and DNS misconfigurations are operational risks that compound security risk.
  • •Run these checks quarterly as a minimum, and immediately after any significant change to your AD environment.
  • •Use the findings to prioritise remediation against ACSC Essential Eight and ISM controls before commissioning a formal penetration test.

⚠️Technical guidance — please read

The PowerShell scripts and configuration samples in this article are provided as sample guidance only and were correct as at the date of publication (May 23, 2026). Microsoft frequently updates its products, services, cmdlets and interfaces, so verify current behaviour against official Microsoft documentation before relying on anything here. Always test in a non-production environment before deploying to production. EDUC4TE provides this guidance "as is", without warranty of any kind, and accepts no liability for any loss, damage or disruption arising from its use.

Running a structured PowerShell health check on your Active Directory environment takes under two hours and will surface the security gaps that attackers consistently exploit in Australian organisations — stale privileged accounts, Kerberoastable service accounts, and domain controllers with replication failures.

This is not a theoretical audit. Every command in this guide reflects findings from real assessments of Australian AD environments. Use them before commissioning a penetration test, before claiming Essential Eight compliance, and as part of your quarterly security operations cadence.

If you want professional eyes on your results, an Active Directory assessment provides structured analysis and a remediation roadmap beyond what a self-service script can offer.

Prerequisites

You will need:

  • PowerShell 5.1 or later (Windows Server 2016 and later have this by default)
  • The ActiveDirectory module: Import-Module ActiveDirectory
  • An account with Domain Users rights at minimum (read-only; no elevated rights required for most checks)
  • On a workstation, the RSAT Active Directory tools. On Windows 10/11, install them from Settings > Optional features (or, in an elevated PowerShell session, Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0). On Windows Server, add the feature instead with Install-WindowsFeature RSAT-AD-PowerShell.

Run all commands from a domain-joined machine. Save output to a dedicated folder so you can compare results across quarters.

# Set up output directory
$OutputPath = 'C:\ADHealthCheck'
New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
$Date = Get-Date -Format 'yyyy-MM-dd'
Write-Host "AD Health Check started: $Date" -ForegroundColor Green

Section 1 — Privileged Account Audit

Privileged account hygiene is the foundation of ACSC Essential Eight ML2 compliance. These queries identify over-privileged accounts, dormant admin accounts, and service accounts with inappropriate group membership.

1.1 — Members of Highly Privileged Groups

# Export all members of sensitive privileged groups
$PrivGroups = @(
    'Domain Admins',
    'Enterprise Admins',
    'Schema Admins',
    'Administrators',
    'Group Policy Creator Owners',
    'Account Operators',
    'Backup Operators',
    'Server Operators',
    'Print Operators',
    'DnsAdmins'
)

$Results = foreach ($Group in $PrivGroups) {
    try {
        $Members = Get-ADGroupMember -Identity $Group -Recursive -ErrorAction Stop
        foreach ($Member in $Members) {
            if ($Member.objectClass -eq 'user') {
                # Enabled and PasswordNeverExpires are Get-ADUser properties, so query the
                # user directly and request them explicitly for the fields to populate.
                $Account = Get-ADUser -Identity $Member.DistinguishedName `
                    -Properties Enabled, PasswordNeverExpires, LastLogonDate
                [PSCustomObject]@{
                    Group           = $Group
                    Name            = $Member.Name
                    SamAccountName  = $Member.SamAccountName
                    ObjectClass     = $Member.objectClass
                    Enabled         = $Account.Enabled
                    LastLogonDate   = $Account.LastLogonDate
                    PasswordExpires = -not [bool]$Account.PasswordNeverExpires
                }
            } else {
                # Recursive expansion can surface computer or managed service accounts.
                [PSCustomObject]@{
                    Group           = $Group
                    Name            = $Member.Name
                    SamAccountName  = $Member.SamAccountName
                    ObjectClass     = $Member.objectClass
                    Enabled         = 'N/A'
                    LastLogonDate   = $null
                    PasswordExpires = 'N/A'
                }
            }
        }
    } catch {
        Write-Warning "Could not query group: $Group"
    }
}

$Results | Export-Csv "$OutputPath\$Date-PrivilegedGroupMembers.csv" -NoTypeInformation
Write-Host "Privileged group members exported: $($Results.Count) entries"

What to look for: Service accounts in Domain Admins (extremely common in Australian environments), user accounts with passwords that never expire, and accounts that have not logged on in over 90 days.

1.2 — Dormant Admin Accounts (No Logon in 90 Days)

$90DaysAgo = (Get-Date).AddDays(-90)

# Domain Admins is a group, not a container, so its members do not live under a DN.
# Expand the group membership, then query each user account.
$DomainAdminMembers = Get-ADGroupMember -Identity "Domain Admins" -Recursive |
    Where-Object { $_.objectClass -eq 'user' }

$DormantAdmins = foreach ($Member in $DomainAdminMembers) {
    Get-ADUser -Identity $Member.DistinguishedName `
        -Properties LastLogonDate, PasswordNeverExpires, MemberOf |
        Where-Object { $_.Enabled -eq $true -and $_.LastLogonDate -lt $90DaysAgo } |
        Select-Object Name, SamAccountName, LastLogonDate, PasswordNeverExpires
}

$DormantAdmins | Export-Csv "$OutputPath\$Date-DormantAdminAccounts.csv" -NoTypeInformation
Write-Host "Dormant admin accounts found: $($DormantAdmins.Count)"

Any result here is a critical finding. Disable these accounts immediately and investigate why they exist.

1.3 — Accounts with Passwords That Never Expire

$NeverExpire = Get-ADUser -Filter { PasswordNeverExpires -eq $true -and Enabled -eq $true } `
    -Properties PasswordNeverExpires, LastLogonDate, MemberOf |
    Select-Object Name, SamAccountName, LastLogonDate, @{
        Name='IsPrivileged'
        Expression={ ($_.MemberOf -match 'Domain Admins|Enterprise Admins') -ne $null }
    }

$NeverExpire | Export-Csv "$OutputPath\$Date-PasswordNeverExpires.csv" -NoTypeInformation
Write-Host "Non-expiring password accounts: $($NeverExpire.Count)"

Focus remediation on any account where IsPrivileged is True. Standard user accounts with non-expiring passwords are a lower-priority finding but should still be reviewed.

Section 2 — Kerberos and Authentication Weaknesses

Kerberoasting and AS-REP roasting are the two most commonly used attack techniques against Australian AD environments, appearing in the majority of penetration test reports Educ4te reviews. These queries identify vulnerable accounts.

2.1 — Kerberoastable Service Accounts (SPNs Set on User Accounts)

$Kerberoastable = Get-ADUser -Filter { ServicePrincipalName -like '*' -and Enabled -eq $true } `
    -Properties ServicePrincipalName, PasswordLastSet, PasswordNeverExpires, LastLogonDate |
    Select-Object Name, SamAccountName, ServicePrincipalName,
                  PasswordLastSet, PasswordNeverExpires, LastLogonDate

$Kerberoastable | Export-Csv "$OutputPath\$Date-KerberoastableAccounts.csv" -NoTypeInformation
Write-Host "Kerberoastable accounts: $($Kerberoastable.Count)"

For each result, verify whether the SPN is still in use. Orphaned SPNs (service no longer running) should be removed. Active SPNs should use managed service accounts (gMSA) where possible, which rotate passwords automatically and resist offline cracking.

2.2 — AS-REP Roastable Accounts (Pre-Authentication Disabled)

$ASREPRoastable = Get-ADUser -Filter {
    DoesNotRequirePreAuth -eq $true -and Enabled -eq $true
} -Properties DoesNotRequirePreAuth, LastLogonDate |
    Select-Object Name, SamAccountName, LastLogonDate

$ASREPRoastable | Export-Csv "$OutputPath\$Date-ASREPRoastableAccounts.csv" -NoTypeInformation
Write-Host "AS-REP Roastable accounts: $($ASREPRoastable.Count)"

This attribute should be set on zero accounts unless you have a specific legacy application requirement. Even then, accounts should be monitored closely and the setting documented with a risk acceptance.

2.3 — Accounts Allowing RC4 or Default (Unset) Kerberos Encryption

# Accounts that still allow RC4, or leave msDS-SupportedEncryptionTypes unset.
# RC4-HMAC is bit 0x4 (decimal 4); AES128 is 0x8, AES256 is 0x10.
# A null or 0 value is the real default-RC4 risk: the KDC may fall back to RC4.
$RC4Accounts = Get-ADUser -Filter { Enabled -eq $true } `
    -Properties msDS-SupportedEncryptionTypes, ServicePrincipalName |
    Where-Object {
        $encTypes = $_.'msDS-SupportedEncryptionTypes'
        ($null -eq $encTypes) -or ($encTypes -eq 0) -or ($encTypes -band 4)
    } |
    Select-Object Name, SamAccountName, 'msDS-SupportedEncryptionTypes'

Write-Host "Accounts allowing RC4 or using default encryption: $($RC4Accounts.Count)"

RC4-HMAC derives its key from the account's NT hash, which makes it far weaker than AES — but it is a Kerberos encryption type, not NTLM authentication. Accounts that leave msDS-SupportedEncryptionTypes unset (null or 0) are the quiet risk, because the KDC can still fall back to RC4 for them; an AES256-only account (value 16) is not flagged. ACSC guidance recommends disabling RC4 and enforcing AES-128 or AES-256 for Kerberos. This is a phased remediation because legacy applications may depend on RC4 — identify them before enforcing.

Section 3 — Stale and Orphaned Objects

Stale objects increase your attack surface without providing operational value. They represent accounts that attackers can use as cover while remaining below monitoring thresholds.

3.1 — Enabled User Accounts Inactive for Over 180 Days

$180DaysAgo = (Get-Date).AddDays(-180)

$StaleUsers = Get-ADUser -Filter {
    Enabled -eq $true -and LastLogonDate -lt $180DaysAgo
} -Properties LastLogonDate, PasswordLastSet, Department, Manager |
    Select-Object Name, SamAccountName, Department, Manager,
                  LastLogonDate, PasswordLastSet |
    Sort-Object LastLogonDate

$StaleUsers | Export-Csv "$OutputPath\$Date-StaleUserAccounts.csv" -NoTypeInformation
Write-Host "Stale user accounts (180+ days): $($StaleUsers.Count)"

3.2 — Stale Computer Accounts

$StaleComputers = Get-ADComputer -Filter {
    Enabled -eq $true -and LastLogonDate -lt $180DaysAgo
} -Properties LastLogonDate, OperatingSystem, OperatingSystemVersion |
    Select-Object Name, DNSHostName, OperatingSystem, OperatingSystemVersion, LastLogonDate |
    Sort-Object LastLogonDate

$StaleComputers | Export-Csv "$OutputPath\$Date-StaleComputerAccounts.csv" -NoTypeInformation
Write-Host "Stale computer accounts (180+ days): $($StaleComputers.Count)"

Pay particular attention to computer accounts running Windows 7, Windows Server 2008/2012, or any end-of-life operating system. These are both stale and a direct vulnerability.

Section 4 — Domain Controller Health

Domain controller replication failures cause authentication outages and can mask security events. These should be zero-finding categories.

4.1 — Replication Status

# Check replication summary
repadmin /replsummary

# Check for replication errors (requires domain admin or replication monitoring rights)
$ReplErrors = Get-ADReplicationFailure -Target (Get-ADDomain).DNSRoot -Scope Domain
if ($ReplErrors) {
    $ReplErrors | Select-Object Server, FirstFailureTime, FailureCount, LastError |
        Export-Csv "$OutputPath\$Date-ReplicationErrors.csv" -NoTypeInformation
    Write-Warning "Replication errors found: $($ReplErrors.Count)"
} else {
    Write-Host "No replication errors detected." -ForegroundColor Green
}

4.2 — Domain Controller Sysvol and Netlogon Availability

$DomainControllers = Get-ADDomainController -Filter * | Select-Object Name, IPv4Address, Site

foreach ($DC in $DomainControllers) {
    $SysvolPath = "\\$($DC.Name)\SYSVOL"
    $NetlogonPath = "\\$($DC.Name)\NETLOGON"
    [PSCustomObject]@{
        DCName        = $DC.Name
        Site          = $DC.Site
        SysvolAccess  = (Test-Path $SysvolPath)
        NetlogonAccess = (Test-Path $NetlogonPath)
    }
} | Format-Table -AutoSize

4.3 — DNS Health

# Check DNS server records for domain controllers
$DCList = (Get-ADDomainController -Filter *).HostName

foreach ($DC in $DCList) {
    $DNSResult = Resolve-DnsName -Name $DC -ErrorAction SilentlyContinue
    if (-not $DNSResult) {
        Write-Warning "DNS resolution failed for: $DC"
    } else {
        Write-Host "DNS OK: $DC -> $($DNSResult.IPAddress)" -ForegroundColor Green
    }
}

# Check for stale DNS records (computers that no longer exist but still have DNS entries)
dcdiag /test:DNS /v /c /DnsBasic /DnsForwarders /DnsDelegation /DnsDynamicUpdate

Section 5 — Group Policy and Security Configuration Checks

5.1 — GPOs with No Links (Orphaned Policies)

$AllGPOs = Get-GPO -All
$OrphanedGPOs = $AllGPOs | Where-Object { $_.GpoStatus -ne 'AllSettingsDisabled' } |
    Where-Object { (Get-GPOReport -Guid $_.Id -ReportType XML) -notmatch '<LinksTo>' }

$OrphanedGPOs | Select-Object DisplayName, CreationTime, ModificationTime |
    Export-Csv "$OutputPath\$Date-OrphanedGPOs.csv" -NoTypeInformation
Write-Host "Orphaned GPOs: $($OrphanedGPOs.Count)"

5.2 — Default Domain Policy Last Modified Date

$DefaultPolicy = Get-GPO -Name 'Default Domain Policy'
Write-Host "Default Domain Policy last modified: $($DefaultPolicy.ModificationTime)"
Write-Host "Default Domain Controllers Policy last modified:"
(Get-GPO -Name 'Default Domain Controllers Policy').ModificationTime

Organisations should avoid modifying the Default Domain Policy directly. Custom GPOs linked to the appropriate OUs provide better manageability and auditability.

Section 6 — Protected Users Group

The Protected Users security group is one of the most underutilised defences in Australian AD environments. Accounts in this group cannot use NTLM authentication, cannot use RC4 Kerberos encryption, and are not cached on devices. All Tier 0 and Tier 1 admin accounts should be members.

$ProtectedUsers = Get-ADGroupMember -Identity 'Protected Users' -Recursive
Write-Host "Accounts in Protected Users group: $($ProtectedUsers.Count)"

# Compare against privileged group membership
$DomainAdmins = Get-ADGroupMember -Identity 'Domain Admins' -Recursive
$NotProtected = $DomainAdmins | Where-Object {
    $_.SamAccountName -notin $ProtectedUsers.SamAccountName
}

Write-Host "Domain Admins NOT in Protected Users: $($NotProtected.Count)" -ForegroundColor Yellow
$NotProtected | Select-Object Name, SamAccountName

Any Domain Admin not in the Protected Users group is an immediate remediation priority. The Tier Model implementation guide covers how to integrate Protected Users group membership into your tiered administration design.

Interpreting and Prioritising Your Results

After running these checks, you will have a set of CSV exports and console output. Prioritise remediation in this order:

  1. Critical — Immediate action: Dormant privileged accounts (disable within 24 hours), Kerberoastable service accounts with administrative rights, AS-REP roastable accounts, replication failures
  2. High — Remediate within 30 days: Service accounts in Domain Admins, accounts with non-expiring passwords in privileged groups, Domain Admins not in Protected Users
  3. Medium — Remediate within 90 days: Stale user accounts over 180 days, stale computer accounts, orphaned GPOs, accounts using RC4 encryption
  4. Informational — Ongoing hygiene: Overall stale object volumes, DNS housekeeping

Taking It Further

These PowerShell commands cover the fundamentals, but a complete Active Directory security assessment goes deeper — analysing ACL inheritance, attack path mapping with BloodHound, and reviewing fine-grained password policies against your actual account population.

A structured Active Directory assessment provides this depth, including a finding report mapped directly to ACSC Essential Eight controls and an actionable remediation plan your team can implement immediately.

Run these checks quarterly at minimum. Save each run's output to a dated folder and compare results over time — the trend is often as informative as any single point-in-time result. An environment where stale account counts are falling and privileged group membership is shrinking is one moving in the right direction, regardless of where it starts.

Assess Your Maturity

Understand where your organisation stands on the Essential Eight maturity model and identify priority controls.

Train Your Team

Hands-on Essential Eight fundamentals course for security teams, architects, and IT leaders.

Resources to Deepen Your Knowledge

Explore training, pathways, assessments and tools aligned with this article's content.

Frequently Asked Questions

Questions security teams commonly ask about Essential Eight implementation.

Ready to Move from Level 1 to Level 2+?

Start your 12-month Essential Eight maturity journey with expert guidance and practical roadmaps.

Read Next

Continue exploring security insights and best practices

ACSC Essential Eight
May 20, 2026
9 min read

Learn how to implement the Active Directory Tier Model to meet ACSC Essential Eight ML2 requirements, with practical steps for Australian organisations.

Process
Apr 23, 2026
12 min read

A step-by-step recipe for Australian Active Directory administrators on verifying System State backups, building a recovery lab, and running an annual forest recovery rehearsal aligned to Essential Eight Maturity Level 2.

Technology
Apr 20, 2026
11 min read

A practitioner walk-through for Australian organisations on declaring Tier 0, separating administrative accounts, and standing up privileged access workstations in hybrid AD environments against ASD ISM and Essential Eight.