Delinea Training Platform  /  Module 03
0% Complete
Module 03 — Technical Discovery

Service Account
Discovery

Master the techniques for locating every service account in your Active Directory environment — including the ones nobody knows about.

Duration~90 min
LevelIntermediate
RoleAD Admin / PAM Engineer
Sections5 Modules

Why Discovery First?

Understand the scope of the service account problem, the risks of undiscovered accounts, and why a thorough inventory is the prerequisite for any successful PAM vaulting program.
More service accounts than human accounts in avg enterprise
40%Of discovered service accounts are orphaned or unused
68%Of breaches involve compromised privileged credentials
0Service accounts vaulted before discovery is complete
⚠️
Core Problem Service accounts are often created informally, documented inconsistently, and never reviewed. A password set in 2009 by a contractor who left the company may still be authenticating production workloads today — and nobody knows it exists.
👻

Ghost Accounts

Accounts tied to decommissioned applications. The app is gone; the account persists with full permissions and a password that hasn't changed in years.

🔑

Never-Rotated Passwords

Service accounts routinely excluded from password policies because developers feared breaking integrations. Common: 5–15 year old passwords.

🔍

Shadow IT Accounts

Accounts created by developers, DBAs, or middleware teams without IT's knowledge. Often named ad-hoc, stored in scripts or config files.

📋

MSAs & gMSAs

Managed Service Accounts and Group Managed Service Accounts. Often overlooked in discovery because they self-manage passwords — but still require inventory and governance.

The Discovery-First Methodology

🔎
AD
Discovery
⚙️
Service
Scan
📅
Task
Scan
📊
Risk
Scoring
🗂️
Inventory
Build
🔒
Vault &
Rotate
ℹ️
Key Principle Do not begin vaulting until discovery is at least 90% complete. Vaulting an account while its twin (same password, different name) remains unknown creates a false sense of security.
Which account type is most commonly missed during a first-pass service account audit?
✓ Correct. Accounts embedded in scheduled tasks, Windows services with "run as" configurations, and application config files are the most commonly overlooked. They're not in a service account OU — they may be anywhere, or created in the default Computers or Users containers.

AD Query Techniques

Use PowerShell, LDAP filters, and ADUC to systematically identify service accounts including edge cases: accounts with "Password Never Expires," inactive accounts, and stale last-logon dates.
💡
Prerequisites Run these queries from a domain-joined machine with RSAT installed and an account that has at minimum Domain Users + read access to AD. Queries marked [DC] require a Domain Controller session or elevated permissions.
Query by naming convention

Start with the known patterns — "svc_", "sa_", "_svc", "-service". This is fast and catches formally-created accounts.

PowerShell — RSAT
# Find accounts with common service account naming conventions
Get-ADUser -Filter {
    (SamAccountName -like "svc_*") -or
    (SamAccountName -like "sa_*") -or
    (SamAccountName -like "*_svc") -or
    (SamAccountName -like "*service*")
} -Properties SamAccountName, PasswordLastSet, LastLogonDate,
    PasswordNeverExpires, Enabled, Description, MemberOf |
Select-Object SamAccountName, Enabled, PasswordLastSet,
    LastLogonDate, PasswordNeverExpires, Description |
Sort-Object PasswordLastSet |
Export-Csv ".\svc_naming_$(Get-Date -f yyyyMMdd).csv" -NoTypeInformation
Find all "Password Never Expires" accounts

This is the single most important flag. Legitimate service accounts often have PNE set — this query surfaces every one of them regardless of name.

PowerShell — All PNE Accounts
# All enabled accounts with Password Never Expires set
Get-ADUser -Filter {
    PasswordNeverExpires -eq $true -and
    Enabled -eq $true
} -Properties PasswordLastSet, LastLogonDate, Description,
    PasswordNeverExpires, MemberOf, ServicePrincipalNames |
Select-Object @{n='Account';e={$_.SamAccountName}},
    @{n='PwdAge_Days';e={
        (New-TimeSpan -Start $_.PasswordLastSet).Days
    }},
    LastLogonDate, Description,
    @{n='HasSPN';e={$_.ServicePrincipalNames.Count -gt 0}} |
Sort-Object PwdAge_Days -Descending |
Format-Table -AutoSize
⚠️
Watch For Any PNE account with PasswordLastSet more than 365 days ago AND no recent LastLogonDate is a candidate for immediate investigation. It may be orphaned.
Query by Service Principal Name (SPN) — Kerberoastable accounts

Any account with an SPN registered can be Kerberoasted by any authenticated domain user. These are high-priority discovery targets.

PowerShell — SPN Discovery
# Find all accounts with Service Principal Names (SPNs)
Get-ADUser -Filter {ServicePrincipalNames -ne "$null"} -Properties * |
ForEach-Object {
    foreach ($spn in $_.ServicePrincipalNames) {
        [PSCustomObject]@{
            Account     = $_.SamAccountName
            SPN         = $spn
            PwdLastSet  = $_.PasswordLastSet
            PwdNeverExp = $_.PasswordNeverExpires
            Enabled     = $_.Enabled
            LastLogon   = $_.LastLogonDate
        }
    }
} | Export-Csv ".\spn_accounts.csv" -NoTypeInformation

# Alternatively use LDAP filter (faster on large domains)
Get-ADUser -LDAPFilter "(servicePrincipalName=*)" -Properties ServicePrincipalNames
Detect stale and orphaned accounts

Accounts that haven't authenticated in 90+ days are candidates for orphan status. Cross-reference against application inventory to confirm.

PowerShell — Stale Account Detection
# Accounts inactive for 90+ days (adjust threshold as needed)
$threshold = (Get-Date).AddDays(-90)

Search-ADAccount -AccountInactive -TimeSpan (New-TimeSpan -Days 90) -UsersOnly |
Get-ADUser -Properties PasswordNeverExpires, PasswordLastSet,
    LastLogonDate, Description, ServicePrincipalNames |
Where-Object { $_.PasswordNeverExpires -eq $true } |
Select-Object SamAccountName, Enabled, LastLogonDate,
    PasswordLastSet, Description |
Sort-Object LastLogonDate |
Format-Table -AutoSize

# Also check accounts that have NEVER logged on
Get-ADUser -Filter {LastLogonDate -notlike "*" -and Enabled -eq $true} -Properties LastLogonDate, PasswordNeverExpires |
Where-Object {$_.PasswordNeverExpires}
Find Managed Service Accounts (MSA / gMSA)

MSAs and gMSAs self-manage their passwords but still require governance — especially to understand which hosts use them and whether they're still needed.

PowerShell — MSA & gMSA Discovery
# List all Managed Service Accounts
Get-ADServiceAccount -Filter * -Properties * |
Select-Object Name, SamAccountName, Enabled,
    PrincipalsAllowedToRetrieveManagedPassword,
    ServicePrincipalNames, HostComputers |
Format-List

# Group Managed Service Accounts specifically
Get-ADObject -LDAPFilter "(objectClass=msDS-GroupManagedServiceAccount)" -Properties * |
Select-Object Name, DistinguishedName, Created, Modified,
    @{n='ManagedBy';e={$_.managedBy}}
Comprehensive domain-wide sweep (combine all sources)

Run this master query to pull all potential service accounts from AD in a single pass. This is your raw material for the inventory.

PowerShell — Master Discovery Query
# Master sweep: PNE + SPN + naming convention + disabled with SPN
$allSvcAccounts = Get-ADUser -Filter {
    PasswordNeverExpires -eq $true -or
    ServicePrincipalNames -ne "$null" -or
    SamAccountName -like "svc_*" -or
    SamAccountName -like "sa_*"
} -Properties SamAccountName, Enabled, PasswordLastSet,
    LastLogonDate, PasswordNeverExpires, Description,
    MemberOf, ServicePrincipalNames, DistinguishedName,
    Created, Modified, PasswordNotRequired

$allSvcAccounts | Select-Object -Property * |
    Export-Csv ".\master_svc_discovery_$(Get-Date -f yyyyMMdd_HHmm).csv" -NoTypeInformation

Write-Host "Found $($allSvcAccounts.Count) candidate service accounts" -ForegroundColor Cyan

Common LDAP Filters Reference

PurposeLDAP FilterRisk Level
Password never expires(userAccountControl:1.2.840.113556.1.4.803:=65536)High
Password not required(userAccountControl:1.2.840.113556.1.4.803:=32)Critical
Has SPN registered(servicePrincipalName=*)High
Account is disabled(userAccountControl:1.2.840.113556.1.4.803:=2)Medium
Pre-authentication not required (AS-REP roastable)(userAccountControl:1.2.840.113556.1.4.803:=4194304)Critical
Group Managed Service Account(objectClass=msDS-GroupManagedServiceAccount)Info
You run the PNE query and find 147 accounts with "Password Never Expires." 110 of them have no LastLogonDate recorded and PasswordLastSet is more than 3 years ago. What is your FIRST action?
✓ Correct. "LastLogonDate" in AD is not replicated in real time — it can lag by 9–14 days and is only updated on specific authentication types. Never disable accounts based solely on this attribute. Always cross-reference against your CMDB, application team contacts, and Windows service/task scans before acting.

Delinea Scanner Config

Configure and run Delinea Secret Server's built-in Discovery Scanner to automate service account detection across your domain. Covers scan zones, scan items, and result review workflows.
ℹ️
Where in Secret Server Navigate to Admin → Discovery → Edit Discovery Sources to configure your domain discovery. Discovery runs are found under Admin → Discovery → Discovery Network View.
Create or verify the Active Directory Discovery Source

One discovery source per AD domain or forest. The source defines the credentials used to scan and the scope of the search.

Configure Discovery Scanner Settings

The scanner configuration controls what Delinea looks for. Use the reference panel below to set optimal values for a full discovery sweep.

Set Scan Item Rules

Scan Items define what types of accounts Delinea will identify — local accounts, domain accounts, service accounts, scheduled tasks. Enable all scan item types for initial discovery.

Run Discovery and Review Results

After the scan, navigate to Discovery → Unmanaged Accounts. Filter by "Service Account" type. Review each result and either import to a secret or flag as non-applicable.

Source Type
Active Directory
Select for domain-joined environments. Use "Windows" for local account discovery on non-domain hosts.
Discovery Source Name
CORP-DOMAIN — Full Discovery
Name it clearly. Include domain name and scope. Avoid generic names like "Discovery 1".
Credentials (Secret)
svc_delinea_discovery (Domain Admin or delegated reader)
Minimum: Read access to all AD objects, right to enumerate services/tasks on remote hosts. Best practice: dedicated least-privilege discovery account.
Domain / Site Scope
corp.contoso.com — All Sites
For large environments, consider scoping to individual AD sites to reduce scan duration and network load. Run site-by-site in phased discovery.
Enable Organizational Unit Filtering
⚠️ OFF for initial sweep
Disabling OU filter ensures you catch accounts in unexpected OUs (Users, Computers, or custom structures). Re-enable after initial discovery to scope ongoing scans.
Scanner Type
Find Dependencies (Windows Service / Task)
Enable both the AD Account scanner AND the Dependency scanners to get full coverage. The AD scanner alone will not find accounts used only in services.
Port Scan Timeout
5000 ms
Default 3000ms can cause false-negatives on slow WAN links. Increase to 5000–8000ms for remote sites.
Maximum Concurrent Scans
25 (default: 10)
Increase for faster scans in large environments. Monitor Distributed Engine CPU. Never exceed 50 without load testing.
Scan Interval
Daily during initial discovery, then Weekly
During initial vaulting phase, daily scans catch newly created service accounts. After steady-state, weekly is sufficient for most environments.
Discovery Error Logging
Enabled — Verbose
Critical for troubleshooting hosts that fail to respond. Errors surface in Admin → Discovery → Discovery Log.
Scan Item TypeEnable?Rationale
AD Domain Users✓ EnableCore discovery — identifies all AD user objects
Windows Services — Domain Accounts✓ EnableFinds domain accounts running as Windows services
Windows Services — Local Accounts✓ EnableFinds local service accounts (often overlooked)
Scheduled Tasks — Domain✓ EnableCritical — high frequency of embedded credentials here
Scheduled Tasks — Local✓ EnableLocal task accounts are common in legacy environments
IIS Application Pools⚠ EnableWeb farms often run pools under domain service accounts
SQL Server Service Accounts✓ EnableSQL agent, SQL server engine often use privileged svc accounts
COM+ ApplicationsOptionalOlder middleware; enable for legacy Windows environments
Unmanaged Account View
Admin → Discovery → Unmanaged Accounts
All discovered accounts that are not yet vaulted appear here. Filter by "Type: Service Account" for your priority queue.
Import Action
Import to Secret (choose template)
Use a pre-built "Windows Service Account" or "Active Directory Account" template. Set secret policy, expiration, and folder on import.
Non-Applicable Accounts
Mark as "Ignored" — document reason
Don't simply skip non-applicable results. Explicitly mark and document them. This creates an auditable record that the account was reviewed.
Ownership Assignment
Assign Secret Owner on import
Every imported secret should have an owner (application team, DBA, etc.). Ownerless secrets become the next generation of orphaned accounts.
Discovery Notification
Email distribution group on new discoveries
Configure Admin → Configuration → Email → Discovery Notifications. Alerts the PAM team when net-new service accounts appear post-vaulting.
⚠️
Common Delinea Discovery Pitfalls (1) Running discovery only against one OU — misses shadow accounts. (2) Using a Domain Admin account for discovery instead of a least-privilege reader — violates PAM principles. (3) Not enabling the Dependency scanner — misses service and task accounts entirely. (4) Ignoring discovery errors instead of resolving host access issues.
In Delinea Secret Server, you enable Discovery but only the "AD Domain Users" scan item. After the scan completes, what category of service accounts will be MISSING from your results?
✓ Correct. The "AD Domain Users" scan item only queries Active Directory objects. It does not interrogate individual Windows hosts to check which accounts are configured as service identities or scheduled task runners. You must also enable the Windows Services and Scheduled Tasks scan items — called "Dependency Scanners" — to discover those associations.

Services & Scheduled Tasks

Manually enumerate Windows services and scheduled tasks to find embedded credentials — the accounts most likely to be undiscovered, unmanaged, and unchanged for years.
🚨
High-Risk Surface Area Services running as domain accounts or scheduled tasks with stored credentials represent the most common source of undiscovered privileged service accounts. These are also prime lateral movement targets because service account passwords rarely change.

Use this to interrogate a single server for services running under non-SYSTEM/LOCAL SERVICE accounts.

PowerShell — Single Host Service Accounts
# Query services on a single host — filter out built-in accounts
Get-WmiObject -Class Win32_Service |
Where-Object {
    $_.StartName -notmatch '^(LocalSystem|NT AUTHORITY|NT SERVICE)' -and
    $_.StartName -ne $null
} |
Select-Object Name, DisplayName, StartName, StartMode, State |
Format-Table -AutoSize

# More detail with service paths (for script injection risk assessment)
Get-WmiObject Win32_Service |
Where-Object { $_.StartName -match '\\' } |  # Domain accounts contain backslash
Select-Object Name, StartName, PathName, StartMode |
Sort-Object StartName

Run against all domain-joined Windows servers. Requires WinRM enabled or remote WMI access. Run from an elevated session.

PowerShell — Bulk Server Service Scan
# Get all domain-joined servers from AD
$servers = Get-ADComputer -Filter {OperatingSystem -like "*Server*"} |
    Select-Object -ExpandProperty Name

$results = foreach ($server in $servers) {
    try {
        Invoke-Command -ComputerName $server -ScriptBlock {
            Get-WmiObject Win32_Service |
            Where-Object {
                $_.StartName -match '\\' -and
                $_.StartName -notmatch 'NT SERVICE'
            } |
            Select-Object @{n='Host';e={$env:COMPUTERNAME}},
                Name, StartName, StartMode, State
        } -ErrorAction Stop
    } catch {
        [PSCustomObject]@{Host=$server; Error=$_.Exception.Message}
    }
}

$results | Export-Csv ".\domain_service_accounts_$(Get-Date -f yyyyMMdd).csv" -NoTypeInformation
Write-Host "Scanned $($servers.Count) servers — found $($results.Count) service account usages"

Scheduled tasks with "Run As" users set to domain accounts are among the most common sources of forgotten credentials. The password is stored in the Windows credential store on the host.

PowerShell — Scheduled Task Credential Discovery
# Local machine — find tasks with domain RunAs accounts
Get-ScheduledTask |
ForEach-Object {
    $task = $_
    $principal = $task.Principal
    if ($principal.UserId -match '\\') {  # domain\user format
        [PSCustomObject]@{
            TaskName  = $task.TaskName
            TaskPath  = $task.TaskPath
            RunAsUser = $principal.UserId
            LogonType = $principal.LogonType
            State     = $task.State
            LastRun   = (Get-ScheduledTaskInfo -TaskName $task.TaskName
                         -TaskPath $task.TaskPath -EA SilentlyContinue).LastRunTime
        }
    }
} | Format-Table -AutoSize

# Remote — scan all servers for scheduled tasks
$servers | ForEach-Object {
    Invoke-Command -ComputerName $_ -ScriptBlock {
        schtasks /query /fo CSV /v
    } -ErrorAction SilentlyContinue
} | ConvertFrom-Csv |
Where-Object { $_.'Run As User' -match '\\' } |
Select-Object 'HostName', 'TaskName', 'Run As User', 'Status'

IIS application pools running under domain accounts are common in web-heavy environments. Query the IIS configuration directly.

PowerShell — IIS App Pool Identities
# Requires WebAdministration module (available on IIS servers)
Import-Module WebAdministration

Get-WebConfiguration "system.applicationHost/applicationPools/add" |
Where-Object {$_.processModel.userName -ne ""} |
Select-Object Name,
    @{n='Identity';e={$_.processModel.identityType}},
    @{n='UserName';e={$_.processModel.userName}},
    State, ManagedRuntimeVersion |
Format-Table -AutoSize

# Equivalent appcmd approach (works without PowerShell module)
& "$env:windir\system32\inetsrv\appcmd.exe" list apppool /processModel.userName:*
🚨
Highest Risk — Handle Output Carefully This scan may return actual passwords in plaintext from config files. Run from a secured admin workstation, encrypt output immediately, and follow your organization's credential handling procedures.
PowerShell — Config File Credential Patterns
# Search common config files for credential-bearing patterns
# SENSITIVE — do not run in logged sessions without encryption
$patterns = @(
    'password\s*=',
    'pwd\s*=',
    'connectionstring.*password',
    'credentials.*user',
    'RunAs.*user'
)

$searchPaths = @(
    'C:\inetpub',
    'C:\Windows\System32\Tasks',
    'C:\Program Files'
)

foreach ($path in $searchPaths) {
    Get-ChildItem $path -Recurse -Include *.config,*.xml,*.json,*.ini,*.bat,*.ps1 -EA SilentlyContinue |
    Select-String -Pattern ($patterns -join '|') -CaseSensitive:$false |
    Select-Object Filename, LineNumber,
        @{n='Snippet';e={$_.Line.Trim().Substring(0,[Math]::Min(80,$_.Line.Trim().Length))}} |
    Export-Csv ".\cred_patterns.csv" -Append -NoTypeInformation
}

Account Risk Signals Reference

SignalRiskRecommended Action
Password age > 365 days + service accountHighVault immediately; plan rotation window
Password age > 3 yearsCriticalTreat as compromised; emergency rotation
No LastLogon + PNE + has SPNHighInvestigate orphan status; disable if confirmed
Domain admin group memberCriticalImmediate review; remove DA if not justified
Plaintext password in config fileCriticalVault, rotate, remove from file, use DPAPI or vault SDK
MSA/gMSA not in Delinea inventoryMediumAdd to inventory record; verify host associations
Service account with interactive logon rightsMediumRemove interactive logon right via GPO
AS-REP roastable (no pre-auth)CriticalEnable Kerberos pre-authentication immediately
You find a scheduled task on a production application server. The task runs daily as CORP\svc_legacy_backup — an account you cannot find in the current service account documentation. PasswordLastSet shows 2011. What is the CORRECT sequence of actions?
✓ Correct. Option A and D risk breaking production workloads. Option B is unsafe because the password would be rotated without being vaulted, creating a new undocumented password. The correct approach is: document → identify owner → vault → coordinate rotation. This is the PAM discovery-to-vaulting lifecycle.

Inventory Builder

Build your service account inventory in this interactive tool. Capture the metadata needed for vaulting decisions: ownership, application, risk level, and current status. Export as CSV when complete.
ℹ️
Practice Tool This inventory builder is a hands-on exercise. Use accounts from your AD queries or the example accounts provided to practice building a complete inventory record. A real production inventory would integrate with your CMDB.

Inventory Checklist — Required Fields

Every service account in your inventory must have these fields completed before vaulting. Check off each category as you've sourced the data for your accounts.

Account name (SamAccountName) confirmed in AD
Identity
Account type identified: Domain User / MSA / gMSA / Local
Identity
Business / application owner identified and confirmed
Ownership
Application or service the account supports is documented
Application
All hosts where account is used (services, tasks) enumerated
Scope
Current password age and last rotation date confirmed
Security
Group memberships and privileges reviewed and documented
Security
Password rotation impact assessed (will rotating break anything?)
Risk
Risk level assigned (Critical / High / Medium / Low)
Risk
Vaulting target date agreed with account owner
PAM
Secret Server folder and policy determined for import
PAM
Required Fields Coverage 0 / 11 complete
Service Account Inventory Register
Inventory: 0 accounts recorded
No accounts added yet. Use the form above or load sample data to begin.

Vaulting Readiness Criteria

Your inventory is the foundation. Before you begin vaulting, verify these organizational prerequisites are also in place.

At least one complete discovery pass (AD + Services + Tasks) completed for all in-scope domains
Discovery
All Critical and High risk accounts have identified owners
Ownership
Secret Server folder structure and secret policies defined
PAM Config
Secret Server Distributed Engine deployed to all scan zones
PAM Config
Rotation schedule and change window agreed with app owners
Operations
Rollback plan documented for failed rotation scenarios
Risk
Ongoing discovery scan scheduled (weekly minimum) post-vaulting
Continuous
Alerts configured for new undiscovered accounts appearing in Delinea
Continuous
Vaulting Readiness 0 / 8 complete
🎯
Module Complete You now have the core techniques for a complete service account discovery program: AD queries by PNE, SPN, naming convention, and staleness; Delinea Scanner configuration with all dependency scan items enabled; manual enumeration of Windows services, scheduled tasks, IIS pools, and config files; and an inventory framework that captures the metadata needed for informed vaulting decisions.