LSA Secrets in the SECURITY hive: the RegRipper lsasecrets plugin
8 min read
LSA secrets are the part of the SECURITY hive that most analysts know exists, never decrypt, and undervalue as a result. The encrypted blobs are the headline — autologon passwords, service-account credentials, the machine account password, cached domain logons — and the RegRipper lsasecrets plugin (and the related secrets plugin) is built to pull them out when you have both the SECURITY and SYSTEM hives. But on most engagements the decryption is beside the point. The names of the secrets, and the LastWrite timestamps on their keys, answer real investigative questions before you ever touch the ciphertext. This post is about reading the SECURITY hive as a forensic signal: what enumerating LSA secrets tells you about how a host was configured, what ran on it, and who it trusted.
Where LSA secrets live
LSA secrets are stored under SECURITY\Policy\Secrets. Each secret is a subkey named for the secret it holds, and under each name key the actual material lives in subvalues — typically CurrVal (current value), OldVal (previous value), and a set of timestamp/state keys (CupdTime, OupdTime, SecDesc). The data in CurrVal is encrypted.
The Registry Parser plugin that surfaces this is security_secrets. It is deliberately minimal: it walks the subkeys of Policy\Secrets and returns two columns — the secret name and the key LastWrite time:
columns: ["LSA secret", "Key last written (UTC)"]
It does not attempt decryption. The plugin note says it plainly: "LSA secret names (e.g. $MACHINE.ACC, DPAPI, service accounts). Values are encrypted." That is the right altitude for a browser-based triage tool, and as it happens it is also the most evidentially useful view. The same hive carries the account-domain SID (Policy\PolAcDmS) and the audit policy (Policy\PolAdtEv), which the polacdms and auditpol plugins decode — context worth pulling at the same time, because the SID prefix and the audit posture frame everything the secrets tell you.
Why the blobs need the SYSTEM bootkey
The reason offline tooling needs both hives is structural, not incidental. The LSA secrets in SECURITY are encrypted with the LSA key, and the LSA key is itself protected by the system bootkey — the syskey — which is assembled from four Class attributes scattered across SYSTEM\CurrentControlSet\Control\Lsa (the JD, Skew1, GBG, and Data subkeys). Neither hive is sufficient alone. SECURITY holds the ciphertext; SYSTEM holds the material needed to derive the key that decrypts it.
I am not going to walk through the derivation here, and you do not need it for the analysis that follows. The practical takeaway for an investigator is simply this: if a tool offers to decrypt LSA secrets from a single hive, it cannot, and you should be suspicious of the output. If you have only SECURITY, you still have the names and the timestamps, and those carry most of the IR value.
What the names tell you
This is the core of the post. Enumerate the secret names and read them as a configuration fingerprint. Common entries and what each one means to an analyst:
_SC_<ServiceName>— A service-account secret. Windows creates one of these for every service configured to run as a specific user account (rather thanLocalSystem,LocalService, orNetworkService). The presence of_SC_MSSQLSERVER,_SC_BITS, or_SC_<custom>tells you that service runs under a named account whose password the LSA is storing. Cross-reference the service names againstSYSTEM\CurrentControlSet\Servicesto see the binary and theObjectName(the account). A_SC_secret for a service you do not recognize is worth a hard look — attackers persist by installing services that run as a privileged account, and the_SC_entry is a durable side effect of that.DefaultPassword— Autologon was configured at some point. WhenAutoAdminLogonis enabled (underSOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon), the password is stashed here as an LSA secret. The mere existence ofDefaultPasswordis a finding: it means the host was set up to log a user in without interactive credential entry. That is common on kiosks, lab machines, and (unfortunately) on plenty of servers an admin "just wanted to get working." It is also a known attacker convenience. You do not need to decrypt it to report "autologon was configured on this host"; the secret name plus the corresponding Winlogon values establish it.$MACHINE.ACC— The computer account password for the domain. Its presence confirms the host is (or was) domain-joined and is the secret used to maintain the secure channel to a domain controller. The LastWrite on this key is interesting on its own — see below.NL$KM— The key used to protect cached domain credentials. Where you seeNL$KM, expect cached logons to exist on the host.DPAPI_SYSTEM— The machine-scope DPAPI master key material. Relevant if your investigation touches DPAPI-protected data, but as a name it mostly just confirms a normally-configured host.L$_.../_SC_.../RasDialParams.../L$RTMTIMEBOMB— A grab-bag of feature- and product-specific secrets (RAS dial credentials, licensing timers, third-party software stashing material via the LSA store API). Names prefixedL$are application-defined local secrets; a name you cannot account for can indicate software — legitimate or otherwise — that chose to use the LSA secret store.
The point is that the namespace is self-documenting. You can characterize a host's identity and service posture from the list of names alone: domain-joined or not, autologon or not, which services run as named accounts, whether cached creds are in play.
Cached domain credentials are nearby
While not part of Policy\Secrets, cached domain logons live one branch over, under SECURITY\Cache (commonly the NL$1, NL$2, … values, with NL$Control and NL$IterationCount governing them). These are the "logon cache" entries — the MSCACHEv2 verifiers that let a domain user log on when no DC is reachable. For an investigator, the count and freshness of these entries answer a useful question: which domain accounts have actually logged on interactively to this host? By default Windows caches the last ten. A workstation that holds a cached entry for a domain admin account is telling you a domain admin logged on there at least once — a lateral-movement and credential-exposure signal regardless of whether you ever crack the verifier. I would treat the existence and population of SECURITY\Cache as corroboration for logon-event analysis, not a replacement for it.
The forensic value of LastWrite
The security_secrets plugin emits the key LastWrite time for a reason. Each secret's name key carries a LastWrite that updates when the secret is created or rotated, and the per-secret CupdTime/OupdTime values record the current/old value update times more precisely. Read defensively:
$MACHINE.ACCLastWrite ≈ the last machine-account password rotation. Windows rotates this on a schedule (30 days by default) when the secure channel is healthy. A$MACHINE.ACCthat has not been rotated in a long time can indicate a host that was offline, deprovisioned, or had its secure channel broken — context for "was this machine actually live during the incident window?"DefaultPasswordLastWrite — roughly when autologon was last (re)configured. If that timestamp lands inside your incident window, someone enabled or changed autologon during the event. That is a pivot, not a footnote._SC_<service>LastWrite — when the service account's stored credential was last set, which tracks closely to when the service was installed or its account changed. A_SC_key with a LastWrite matching a suspicious service-install event in the System log ties the two artifacts together.
Timestamps in the registry are not gospel — LastWrite reflects the last write to the key, and tools or rollbacks can perturb it — so corroborate against event logs, the MFT, and (where available) VSS copies of the SECURITY hive to see how the secret set evolved over time. But as a first cut, the LastWrite column turns a flat list of names into a timeline.
How RegRipper handles it
RegRipper ships lsasecrets for the decrypted output (it consumes the bootkey from SYSTEM, derives the LSA key, and decrypts CurrVal) and lighter secrets-style enumeration for the names. If your engagement authorizes credential recovery and you have both hives, the plugin produces the cleartext. If it does not, run it for the enumeration and timestamps, which is what most triage actually needs. The plugin source is the reference for exactly which subvalues it reads and how it labels them; read it rather than trusting a summary.
Tools
- RegRipper's
lsasecretsplugin — the canonical SECURITY-hive LSA-secrets extractor. Decrypts when given the SYSTEM bootkey; enumerates names otherwise. Source on GitHub. See the RegRipper plugins reference for the surrounding SECURITY-hive plugins (polacdms,auditpol). - Eric Zimmerman's RECmd with a SECURITY batch file — for CSV enumeration of
Policy\SecretsandCache. - The parser on this site — you can analyze a SECURITY hive in your browser and the
security_secretsplugin lists every secret name with its key LastWrite, no decryption and no upload. Pair it with the SAM hive's accounts for a full local-identity picture.
What to report
The defensible findings from LSA-secret enumeration alone are: whether autologon was configured (and when), the inventory of services running as named accounts (and when those credentials were set), confirmation of domain membership via $MACHINE.ACC, and the presence and population of cached domain logons. Each of those is an evidentiary statement you can make without ever decrypting a byte, and each pivots cleanly to another artifact — the Winlogon keys, the Services subtree, the Security event log, the logon cache. The encrypted blobs are the part everyone fixates on; the name-and-timestamp view is the part that actually moves an investigation.