Modification of WDigest Security Provider
Identifies attempts to modify the WDigest security provider in the registry to force the user's password to be stored in clear text in memory. Windows 8.1+ and Server 2012 R2+ disable WDigest plaintext credential caching by default, but setting UseLogonCredential to 1 re-enables it, causing LSASS to retain cleartext passwords for subsequent interactive logons. Adversaries abuse this to prepare for credential dumping from LSASS memory.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2021/01/19"
3integration = ["endpoint", "windows", "m365_defender"]
4maturity = "production"
5updated_date = "2026/04/29"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies attempts to modify the WDigest security provider in the registry to force the user's password to be stored in
11clear text in memory. Windows 8.1+ and Server 2012 R2+ disable WDigest plaintext credential caching by default, but
12setting UseLogonCredential to 1 re-enables it, causing LSASS to retain cleartext passwords for subsequent interactive
13logons. Adversaries abuse this to prepare for credential dumping from LSASS memory.
14"""
15from = "now-9m"
16index = [
17 "winlogbeat-*",
18 "logs-endpoint.events.registry-*",
19 "logs-windows.sysmon_operational-*",
20 "endgame-*",
21 "logs-m365_defender.event-*",
22]
23language = "eql"
24license = "Elastic License v2"
25name = "Modification of WDigest Security Provider"
26references = [
27 "https://www.csoonline.com/article/567747/how-to-detect-and-halt-credential-theft-via-windows-wdigest.html",
28 "https://www.praetorian.com/blog/mitigating-mimikatz-wdigest-cleartext-credential-theft?edition=2019",
29 "https://frsecure.com/compromised-credentials-response-playbook/",
30 "https://www.elastic.co/security-labs/detect-credential-access",
31]
32risk_score = 73
33rule_id = "d703a5af-d5b0-43bd-8ddb-7a5d500b7da5"
34severity = "high"
35tags = [
36 "Domain: Endpoint",
37 "OS: Windows",
38 "Use Case: Threat Detection",
39 "Tactic: Credential Access",
40 "Resources: Investigation Guide",
41 "Data Source: Elastic Endgame",
42 "Data Source: Elastic Defend",
43 "Data Source: Sysmon",
44 "Data Source: Microsoft Defender XDR",
45]
46timestamp_override = "event.ingested"
47type = "eql"
48
49query = '''
50registry where host.os.type == "windows" and event.type in ("creation", "change") and
51 registry.value : "UseLogonCredential" and
52 registry.path : "*\\SYSTEM\\*ControlSet*\\Control\\SecurityProviders\\WDigest\\UseLogonCredential" and
53 registry.data.strings : ("1", "0x00000001") and
54 not (process.executable : "?:\\Windows\\System32\\svchost.exe" and user.id : "S-1-5-18")
55'''
56
57note = """## Triage and analysis
58
59### Investigating Modification of WDigest Security Provider
60#### Possible investigation steps
61
62- Is the write to the active ControlSet, and does host context explain enablement?
63 - Focus: `registry.path`, `registry.data.strings`, and `host.id`.
64 - Implication: escalate when the active ControlSet is enabled, leaving cleartext credentials in LSASS for later logons; lower suspicion only for a recognized lab or legacy compatibility host with the exact expected pattern.
65
66- Which process made the change, and does its identity fit?
67 - Focus: `process.executable`, `process.command_line`, `process.code_signature.subject_name`, and `process.parent.command_line`. $investigate_0
68 - Hint: pivot on `host.id` plus `process.entity_id`; if absent, bound to alert time and host.
69 - Implication: escalate when the writer is unsigned, user-writable, renamed, script-launched, or has an unrelated parent; lower suspicion only when identity, parent, and registry outcome match one recognized validation activity. Trusted signer alone is not clearance.
70
71- Does user and session context explain the change?
72 - Focus: `user.id`, `user.domain`, `process.Ext.session_info.logon_type`, and `process.Ext.token.integrity_level_name`.
73 - Implication: escalate when a normal user, unexpected admin, service account, remote session, or elevated token performs the write outside a recognized test path.
74
75- Did the same process leave WDigest enabled or change adjacent security registry state?
76 - Focus: registry events from the same `process.entity_id`: `registry.path`, `registry.value`, and `registry.data.strings`. $investigate_1
77 - Hint: check for WDigest reversal and LSA or SecurityProviders changes before widening to the host.
78 - Implication: escalate when WDigest stays enabled or the writer weakens LSA or security-provider settings; scope narrower when the write is isolated, promptly reversed, and no contradictory registry evidence remains.
79
80- Does process activity after the write show credential-dumping preparation or execution?
81 - Focus: child process events from `process.entity_id`: `process.executable` and `process.command_line`. $investigate_2
82 - Implication: escalate when children show Mimikatz/sekurlsa, ProcDump or comsvcs.dll LSASS dumping, CrackMapExec, PowerShell remote execution, archives, or cleanup; absent follow-on evidence narrows extraction proof but does not clear enablement.
83
84- Did any accounts authenticate while WDigest was enabled?
85 - Focus: logon events after `@timestamp`: `event.code` 4624, `winlog.event_data.TargetUserName`, `winlog.event_data.AuthenticationPackageName`, `winlog.logon.type`, and `source.ip`. $investigate_3
86 - Hint: expand until WDigest is disabled or the host is contained; for domain NTLM, search domain-controller 4776 records for the alert host as source workstation.
87 - Implication: escalate credential exposure when successful WDigest or privileged logons occur after enablement. Missing authentication telemetry is unresolved, not benign.
88
89- If local evidence is suspicious or unresolved, do related alerts change scope?
90 - Focus: alerts for `user.id`, especially credential access, privilege escalation, or lateral movement. $investigate_4
91 - Hint: compare host alerts for precursor access, LSASS-oriented follow-on, staging, or cleanup. $investigate_5
92 - Implication: broaden when the same user or host shows adjacent post-compromise behavior; keep local when related alerts are quiet and local evidence fits one recognized workflow.
93
94- Escalate when writer identity, session context, registry changes, unreverted WDigest exposure, follow-on activity, or related alerts indicate unauthorized credential-protection weakening; close only when those categories align with one confirmed activity and no contradictions remain; preserve and escalate when evidence is mixed or incomplete.
95
96### False positive analysis
97
98- Authorized security validation or legacy compatibility testing may enable WDigest. Confirm `process.executable`, `process.command_line`, `process.parent.command_line`, `user.id`, `host.id`, `registry.data.strings`, prompt reversion, and no contradictory registry or LSASS-oriented follow-on. If telemetry cannot prove the activity, leave unresolved.
99- Build exceptions from the minimum confirmed workflow: `process.executable` or signer, `process.parent.command_line`, `user.id`, `host.id`, `registry.path`, and expected `registry.data.strings`. Avoid exceptions on `registry.path`, `process.name`, signer, or `host.id` alone.
100
101### Response and remediation
102
103- If confirmed benign, reverse any temporary containment, document the aligned workflow evidence, and create an exception only when the confirmed evidence pattern is expected to repeat and can be scoped narrowly.
104- If suspicious but unconfirmed, preserve the alert, process tree, command lines, relevant registry events, related-alert results, and current WDigest state before containment. Apply reversible containment first, such as heightened monitoring or EDR network restrictions, and use host isolation only when follow-on dumping, unreverted exposure on a sensitive host, or broader compromise evidence justifies the operational impact.
105- If confirmed malicious, preserve the writer `process.entity_id`, process tree, command lines, registry evidence, and current WDigest state; then isolate the host when the evidence supports it, restore WDigest to the disabled state, and eradicate only the scripts, binaries, registry changes, and persistence found during the investigation.
106- After containment, review other registry changes by the same process and scope accounts that may have authenticated while WDigest was enabled through available authentication records; when those records are unavailable, treat credential exposure as unresolved and prioritize privileged, service, and lateral-movement-capable accounts for credential hygiene.
107- Post-incident hardening: restrict who can modify WDigest and related LSA policy, validate baseline configuration through endpoint or policy management, retain registry and process telemetry for this host class, and document the confirmed workflow or malicious pattern for future analysts.
108"""
109
110setup = """## Setup
111
112This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.
113
114Setup instructions: https://ela.st/install-elastic-defend
115
116### Additional data sources
117
118This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
119
120- [Microsoft Defender XDR](https://ela.st/m365-defender)
121- [Sysmon Registry Events](https://ela.st/sysmon-event-reg-setup)
122"""
123
124[rule.investigation_fields]
125field_names = [
126 "@timestamp",
127 "host.id",
128 "user.id",
129 "process.code_signature.subject_name",
130 "process.code_signature.trusted",
131 "process.executable",
132 "process.command_line",
133 "process.entity_id",
134 "process.parent.executable",
135 "process.parent.command_line",
136 "process.Ext.session_info.logon_type",
137 "process.Ext.token.integrity_level_name",
138 "registry.path",
139 "registry.value",
140 "registry.data.strings",
141]
142
143[transform]
144
145[[transform.investigate]]
146label = "Process events by WDigest writer"
147description = ""
148providers = [
149 [
150 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
151 { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
152 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" }
153 ]
154]
155relativeFrom = "now-1h"
156relativeTo = "now"
157
158[[transform.investigate]]
159label = "Registry events by WDigest writer"
160description = ""
161providers = [
162 [
163 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
164 { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
165 { excluded = false, field = "event.category", queryType = "phrase", value = "registry", valueType = "string" }
166 ]
167]
168relativeFrom = "now-1h"
169relativeTo = "now"
170
171[[transform.investigate]]
172label = "Child process events by WDigest writer"
173description = ""
174providers = [
175 [
176 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
177 { excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
178 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" }
179 ]
180]
181relativeFrom = "now-1h"
182relativeTo = "now"
183
184[[transform.investigate]]
185label = "Logon events on the WDigest host"
186description = ""
187providers = [
188 [
189 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
190 { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" }
191 ]
192]
193relativeFrom = "now-24h"
194relativeTo = "now"
195
196[[transform.investigate]]
197label = "Alerts associated with the user"
198description = ""
199providers = [
200 [
201 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
202 { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
203 ]
204]
205relativeFrom = "now-48h/h"
206relativeTo = "now"
207
208[[transform.investigate]]
209label = "Alerts associated with the host"
210description = ""
211providers = [
212 [
213 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
214 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
215 ]
216]
217relativeFrom = "now-48h/h"
218relativeTo = "now"
219
220[[rule.threat]]
221framework = "MITRE ATT&CK"
222
223[[rule.threat.technique]]
224id = "T1003"
225name = "OS Credential Dumping"
226reference = "https://attack.mitre.org/techniques/T1003/"
227
228[[rule.threat.technique.subtechnique]]
229id = "T1003.001"
230name = "LSASS Memory"
231reference = "https://attack.mitre.org/techniques/T1003/001/"
232
233[rule.threat.tactic]
234id = "TA0006"
235name = "Credential Access"
236reference = "https://attack.mitre.org/tactics/TA0006/"
237
238[[rule.threat]]
239framework = "MITRE ATT&CK"
240
241[[rule.threat.technique]]
242id = "T1112"
243name = "Modify Registry"
244reference = "https://attack.mitre.org/techniques/T1112/"
245
246[rule.threat.tactic]
247id = "TA0005"
248name = "Defense Evasion"
249reference = "https://attack.mitre.org/tactics/TA0005/"
Triage and analysis
Investigating Modification of WDigest Security Provider
Possible investigation steps
-
Is the write to the active ControlSet, and does host context explain enablement?
- Focus:
registry.path,registry.data.strings, andhost.id. - Implication: escalate when the active ControlSet is enabled, leaving cleartext credentials in LSASS for later logons; lower suspicion only for a recognized lab or legacy compatibility host with the exact expected pattern.
- Focus:
-
Which process made the change, and does its identity fit?
- Focus:
process.executable,process.command_line,process.code_signature.subject_name, andprocess.parent.command_line. $investigate_0 - Hint: pivot on
host.idplusprocess.entity_id; if absent, bound to alert time and host. - Implication: escalate when the writer is unsigned, user-writable, renamed, script-launched, or has an unrelated parent; lower suspicion only when identity, parent, and registry outcome match one recognized validation activity. Trusted signer alone is not clearance.
- Focus:
-
Does user and session context explain the change?
- Focus:
user.id,user.domain,process.Ext.session_info.logon_type, andprocess.Ext.token.integrity_level_name. - Implication: escalate when a normal user, unexpected admin, service account, remote session, or elevated token performs the write outside a recognized test path.
- Focus:
-
Did the same process leave WDigest enabled or change adjacent security registry state?
- Focus: registry events from the same
process.entity_id:registry.path,registry.value, andregistry.data.strings. $investigate_1 - Hint: check for WDigest reversal and LSA or SecurityProviders changes before widening to the host.
- Implication: escalate when WDigest stays enabled or the writer weakens LSA or security-provider settings; scope narrower when the write is isolated, promptly reversed, and no contradictory registry evidence remains.
- Focus: registry events from the same
-
Does process activity after the write show credential-dumping preparation or execution?
- Focus: child process events from
process.entity_id:process.executableandprocess.command_line. $investigate_2 - Implication: escalate when children show Mimikatz/sekurlsa, ProcDump or comsvcs.dll LSASS dumping, CrackMapExec, PowerShell remote execution, archives, or cleanup; absent follow-on evidence narrows extraction proof but does not clear enablement.
- Focus: child process events from
-
Did any accounts authenticate while WDigest was enabled?
- Focus: logon events after
@timestamp:event.code4624,winlog.event_data.TargetUserName,winlog.event_data.AuthenticationPackageName,winlog.logon.type, andsource.ip. $investigate_3 - Hint: expand until WDigest is disabled or the host is contained; for domain NTLM, search domain-controller 4776 records for the alert host as source workstation.
- Implication: escalate credential exposure when successful WDigest or privileged logons occur after enablement. Missing authentication telemetry is unresolved, not benign.
- Focus: logon events after
-
If local evidence is suspicious or unresolved, do related alerts change scope?
- Focus: alerts for
user.id, especially credential access, privilege escalation, or lateral movement. $investigate_4 - Hint: compare host alerts for precursor access, LSASS-oriented follow-on, staging, or cleanup. $investigate_5
- Implication: broaden when the same user or host shows adjacent post-compromise behavior; keep local when related alerts are quiet and local evidence fits one recognized workflow.
- Focus: alerts for
-
Escalate when writer identity, session context, registry changes, unreverted WDigest exposure, follow-on activity, or related alerts indicate unauthorized credential-protection weakening; close only when those categories align with one confirmed activity and no contradictions remain; preserve and escalate when evidence is mixed or incomplete.
False positive analysis
- Authorized security validation or legacy compatibility testing may enable WDigest. Confirm
process.executable,process.command_line,process.parent.command_line,user.id,host.id,registry.data.strings, prompt reversion, and no contradictory registry or LSASS-oriented follow-on. If telemetry cannot prove the activity, leave unresolved. - Build exceptions from the minimum confirmed workflow:
process.executableor signer,process.parent.command_line,user.id,host.id,registry.path, and expectedregistry.data.strings. Avoid exceptions onregistry.path,process.name, signer, orhost.idalone.
Response and remediation
- If confirmed benign, reverse any temporary containment, document the aligned workflow evidence, and create an exception only when the confirmed evidence pattern is expected to repeat and can be scoped narrowly.
- If suspicious but unconfirmed, preserve the alert, process tree, command lines, relevant registry events, related-alert results, and current WDigest state before containment. Apply reversible containment first, such as heightened monitoring or EDR network restrictions, and use host isolation only when follow-on dumping, unreverted exposure on a sensitive host, or broader compromise evidence justifies the operational impact.
- If confirmed malicious, preserve the writer
process.entity_id, process tree, command lines, registry evidence, and current WDigest state; then isolate the host when the evidence supports it, restore WDigest to the disabled state, and eradicate only the scripts, binaries, registry changes, and persistence found during the investigation. - After containment, review other registry changes by the same process and scope accounts that may have authenticated while WDigest was enabled through available authentication records; when those records are unavailable, treat credential exposure as unresolved and prioritize privileged, service, and lateral-movement-capable accounts for credential hygiene.
- Post-incident hardening: restrict who can modify WDigest and related LSA policy, validate baseline configuration through endpoint or policy management, retain registry and process telemetry for this host class, and document the confirmed workflow or malicious pattern for future analysts.
References
Related rules
- Potential Local NTLM Relay via HTTP
- Wireless Credential Dumping using Netsh Command
- Kirbi File Creation
- LSASS Memory Dump Creation
- Microsoft IIS Connection Strings Decryption