Credential Access
T1003 — OS Credential Dumping
Adversaries may dump credentials from operating system memory or storage (LSASS, SAM, NTDS.dit, /etc/shadow, keychains) to obtain account credentials for further access and lateral movement.
Treat any tool or process accessing LSASS memory, the SAM hive, or NTDS.dit outside of known-good backup/administrative tooling as a near-certain credential dumping attempt requiring immediate containment and full credential rotation for anything that may have been exposed.
Platforms
Windows, Linux, macOS
Priority / status
high / complete
Evidence to collect
- Host affected (and whether it is a domain controller)
- Process that accessed the credential store
- Technique used (LSASS dump, SAM/NTDS extraction, shadow copy)
- Accounts/hashes potentially exposed
- Any follow-on authentication using exposed credentials
D3-PSA · detect
Process Spawn Analysis
Detect processes opening a handle to lsass.exe outside of known security/monitoring tooling.
Tooling: Defender for Endpoint, Sysmon
D3-FA · detect
File Analysis
Detect access to SAM/SYSTEM hives, NTDS.dit, or shadow copies used to extract them.
Tooling: Defender for Endpoint
D3-KBPI · isolate
Kernel-based Process Isolation
Enable Credential Guard / virtualization-based LSASS protection so credential material cannot be read even by a process with local admin.
Tooling: Defender for Endpoint, Group Policy
D3-CR · evict
Credential Revocation
Rotate all credentials that may have been present in memory or the dumped store, including the krbtgt account if domain controllers are involved.
Tooling: Entra ID, Active Directory
| ATT&CK Technique | D3FEND Technique | Practical SOC Action | Tooling |
|---|---|---|---|
| T1003 OS Credential Dumping | Process Spawn Analysis | Detect processes opening a handle to lsass.exe outside of known security/monitoring tooling. | Defender for Endpoint, Sysmon |
| T1003 OS Credential Dumping | File Analysis | Detect access to SAM/SYSTEM hives, NTDS.dit, or shadow copies used to extract them. | Defender for Endpoint |
| T1003 OS Credential Dumping | Kernel-based Process Isolation | Enable Credential Guard / virtualization-based LSASS protection so credential material cannot be read even by a process with local admin. | Defender for Endpoint, Group Policy |
| T1003 OS Credential Dumping | Credential Revocation | Rotate all credentials that may have been present in memory or the dumped store, including the krbtgt account if domain controllers are involved. | Entra ID, Active Directory |
T1003 OS Credential Dumping → D3FEND → SOC action
Investigation steps — Microsoft
- MDE portal → Device inventory → <DEVICE_NAME> → Isolate device
- Record: initiating process name, command line, folder path, and SHA256 hash
- Submit the SHA256 hash to VirusTotal immediately — is it a known tool?
- Is the process running from %TEMP%, %APPDATA%, C:\ProgramData, or C:\Users? → Almost certainly malicious
- Is the process digitally signed? By whom? (An unsigned process accessing LSASS is extremely high confidence)
- Notify SOC Manager and open P1 incident ticket
- Immediately reset the password — do not wait for investigation completion
- For domain admin accounts: treat as Critical escalation — KRBTGT reset may be required
Investigation steps — generic
- Identify the process and technique used to access credential material.
- Determine the scope of accounts/hashes potentially exposed.
- Check for follow-on lateral movement using any exposed credential.
- Real detection reference: "LSASS Memory Access by Non-Standard Process" -- Flags processes reading lsass.exe memory outside the small set of expected security/monitoring tools, indicative of credential dumping (Mimikatz, procdump, comsvcs MiniDump).
Response actions
| Action | Risk | Automation safe | Approval required |
|---|---|---|---|
| Isolate device | Medium | No | Yes |
| Reset ALL passwords | High | No | Yes |
| Disable the initiating account | Medium | No | Yes |
| Purge Kerberos tickets | Medium | No | Yes |
| Notify customer CISO | Low | Yes | No |
| Open P1 incident ticket | Low | Yes | No |
| Force MFA re-enrolment for all affected accounts | Low | No | Yes |
| Revoke all active sessions for affected accounts across M365 | Medium | No | Yes |
KQL
GEN-CA-001 — LSASS Memory Access by Non-Standard Process
let AllowedInitiators = dynamic([
"MsMpEng.exe",
"MsSense.exe",
"SenseIR.exe",
"wermgr.exe",
"csrss.exe",
"svchost.exe",
"werfault.exe"
]);
DeviceProcessEvents
| where TimeGenerated >= ago(5m)
| where ProcessCommandLine has_any ("lsass", "MiniDump", "procdump", "sekurlsa")
| where FileName !in~ (AllowedInitiators)
| where InitiatingProcessFileName !in~ (AllowedInitiators)
| project
TimeGenerated,
DeviceName,
DeviceId,
AccountName,
FileName,
ProcessCommandLine,
InitiatingProcessFileName,
InitiatingProcessCommandLine,
InitiatingProcessSHA256,
InitiatingProcessIntegrityLevel
| extend timestamp = TimeGenerated,
HostCustomEntity = DeviceName,
AccountCustomEntity = AccountName
| order by TimeGenerated desc 29a29e5d-354e-4f5e-8321-8b39d25047bf — Dev-0228 File Path Hashes November 2021 (ASIM Version)
let files1 = dynamic(["C:\\Windows\\TAPI\\lsa.exe", "C:\\Windows\\TAPI\\pa.exe", "C:\\Windows\\TAPI\\pc.exe", "C:\\Windows\\TAPI\\Rar.exe"]);
let files2 = dynamic(["svchost.exe","wdmsvc.exe"]);
let FileHash1 = dynamic(["43109fbe8b752f7a9076eaafa417d9ae5c6e827cd5374b866672263fdebd5ec3", "ab50d8d707b97712178a92bbac74ccc2a5699eb41c17aa77f713ff3e568dcedb", "010e32be0f86545e116a8bc3381a8428933eb8789f32c261c81fd5e7857d4a77", "56cd102b9fc7f3523dad01d632525ff673259dbc9a091be0feff333c931574f7"]);
let FileHash2 = dynamic(["2a1044e9e6e87a032f80c6d9ea6ae61bbbb053c0a21b186ecb3b812b49eb03b7", "9ab7e99ed84f94a7b6409b87e56dc6e1143b05034a5e4455e8c555dbbcd0d2dd", "18a072ccfab239e140d8f682e2874e8ff19d94311fc8bb9564043d3e0deda54b"]);
imProcessCreate
| where ((Process has_any (files1)) and (ActingProcessSHA256 has_any (FileHash1))) or ((Process has_any (files2)) and (ActingProcessSHA256 has_any (FileHash2)))
// Increase risk score if recent alerts for the host
| join kind=leftouter (
SecurityAlert
| where ProviderName =~ "MDATP"
| extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)
| mv-expand todynamic(Entities)
| extend DvcId = tostring(parse_json(Entities).MdatpDeviceId)
| where isnotempty(DvcId)
// Higher risk score are for Defender alerts related to threat actor
| extend AlertRiskScore = iif(ThreatName has_any ("Backdoor:MSIL/ShellClient.A", "Backdoor:MSIL/ShellClient.A!dll", "Trojan:MSIL/Mimikatz.BA!MTB"), 1.0, 0.5)
| project DvcId, AlertRiskScore)
on DvcId
| extend AlertRiskScore = iif(isempty(AlertRiskScore), 0.0, AlertRiskScore)
| extend AccountName = tostring(split(ActorUsername, @'\')[1]), AccountNTDomain = tostring(split(ActorUsername, @'\')[0])
| extend HostName = tostring(split(Dvc, ".")[0]), DomainIndex = toint(indexof(Dvc, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Dvc, DomainIndex + 1), Dvc)
| project-away DomainIndex 3b443f22-9be9-4c35-ac70-a94757748439 — Dev-0228 File Path Hashes November 2021
let files1 = dynamic(["C:\\Windows\\TAPI\\lsa.exe", "C:\\Windows\\TAPI\\pa.exe", "C:\\Windows\\TAPI\\pc.exe", "C:\\Windows\\TAPI\\Rar.exe"]);
let files2 = dynamic(["svchost.exe","wdmsvc.exe"]);
let FileHash1 = dynamic(["43109fbe8b752f7a9076eaafa417d9ae5c6e827cd5374b866672263fdebd5ec3", "ab50d8d707b97712178a92bbac74ccc2a5699eb41c17aa77f713ff3e568dcedb", "010e32be0f86545e116a8bc3381a8428933eb8789f32c261c81fd5e7857d4a77", "56cd102b9fc7f3523dad01d632525ff673259dbc9a091be0feff333c931574f7"]);
let FileHash2 = dynamic(["2a1044e9e6e87a032f80c6d9ea6ae61bbbb053c0a21b186ecb3b812b49eb03b7", "9ab7e99ed84f94a7b6409b87e56dc6e1143b05034a5e4455e8c555dbbcd0d2dd", "18a072ccfab239e140d8f682e2874e8ff19d94311fc8bb9564043d3e0deda54b"]);
DeviceProcessEvents
| where ( FolderPath has_any (files1) and SHA256 has_any (FileHash1)) or (FolderPath has_any (files2) and SHA256 has_any (FileHash2))
| extend DvcId = DeviceId
| join kind=leftouter (SecurityAlert
| where ProviderName =~ "MDATP"
| extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)
| mv-expand todynamic(Entities)
| extend DvcId = tostring(parse_json(Entities).MdatpDeviceId)
| where isnotempty(DvcId)
// Higher risk score are for Defender alerts related to threat actor
| extend AlertRiskScore = iif(ThreatName has_any ("Backdoor:MSIL/ShellClient.A", "Backdoor:MSIL/ShellClient.A!dll", "Trojan:MSIL/Mimikatz.BA!MTB"), 1.0, 0.5)
| project DvcId, AlertRiskScore) on DvcId
| extend AlertRiskScore = iif(isempty(AlertRiskScore), 0.0, AlertRiskScore)
| extend InitiatingProcessAccount = strcat(InitiatingProcessAccountDomain, "\\", InitiatingProcessAccountName)
| extend HostName = tostring(split(DeviceName, ".")[0]), DomainIndex = toint(indexof(DeviceName, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(DeviceName, DomainIndex + 1), DeviceName)
| extend timestamp = TimeGenerated Escalation criteria
- Domain controller involved.
- Known dumping tool signature matched.
- Follow-on authentication observed using a potentially exposed credential.
- Privileged or service account credentials potentially exposed.
False positive considerations
- Windows Defender Antivirus (MsMpEng.exe) — Pre-excluded in the approved list — verify hash matches Microsoft's known-good
- MDE Sense process (SenseCE.exe / MsSense.exe) — Pre-excluded — verify the hash matches the installed MDE version
- Authorised penetration test — Pentest scope document, written approval, date/time window
- Azure AD Connect agent — AzureADConnectAuthenticationAgentService.exe — pre-excluded
# T1003 - OS Credential Dumping
## SOC Recommendation
Treat any tool or process accessing LSASS memory, the SAM hive, or NTDS.dit outside of known-good backup/administrative tooling as a near-certain credential dumping attempt requiring immediate containment and full credential rotation for anything that may have been exposed.
## D3FEND Mappings
| D3FEND Technique | Relationship | Practical SOC Action |
|---|---|---|
| Process Spawn Analysis | Detect | Detect processes opening a handle to lsass.exe outside of known security/monitoring tooling. |
| File Analysis | Detect | Detect access to SAM/SYSTEM hives, NTDS.dit, or shadow copies used to extract them. |
| Kernel-based Process Isolation | Isolate | Enable Credential Guard / virtualization-based LSASS protection so credential material cannot be read even by a process with local admin. |
| Credential Revocation | Evict | Rotate all credentials that may have been present in memory or the dumped store, including the krbtgt account if domain controllers are involved. |
## Investigation Steps
1. MDE portal → Device inventory → <DEVICE_NAME> → Isolate device
2. Record: initiating process name, command line, folder path, and SHA256 hash
3. Submit the SHA256 hash to VirusTotal immediately — is it a known tool?
4. Is the process running from %TEMP%, %APPDATA%, C:\ProgramData, or C:\Users? → Almost certainly malicious
5. Is the process digitally signed? By whom? (An unsigned process accessing LSASS is extremely high confidence)
6. Notify SOC Manager and open P1 incident ticket
7. Immediately reset the password — do not wait for investigation completion
8. For domain admin accounts: treat as Critical escalation — KRBTGT reset may be required
## Evidence to Collect
- Host affected (and whether it is a domain controller)
- Process that accessed the credential store
- Technique used (LSASS dump, SAM/NTDS extraction, shadow copy)
- Accounts/hashes potentially exposed
- Any follow-on authentication using exposed credentials
## Response Actions
| Action | Risk | Automation Safe | Approval Required |
|---|---|---|---|
| Isolate device | Medium | No | Yes |
| Reset ALL passwords | High | No | Yes |
| Disable the initiating account | Medium | No | Yes |
| Purge Kerberos tickets | Medium | No | Yes |
| Notify customer CISO | Low | Yes | No |
| Open P1 incident ticket | Low | Yes | No |
| Force MFA re-enrolment for all affected accounts | Low | No | Yes |
| Revoke all active sessions for affected accounts across M365 | Medium | No | Yes |
## KQL
```kql
let AllowedInitiators = dynamic([
"MsMpEng.exe",
"MsSense.exe",
"SenseIR.exe",
"wermgr.exe",
"csrss.exe",
"svchost.exe",
"werfault.exe"
]);
DeviceProcessEvents
| where TimeGenerated >= ago(5m)
| where ProcessCommandLine has_any ("lsass", "MiniDump", "procdump", "sekurlsa")
| where FileName !in~ (AllowedInitiators)
| where InitiatingProcessFileName !in~ (AllowedInitiators)
| project
TimeGenerated,
DeviceName,
DeviceId,
AccountName,
FileName,
ProcessCommandLine,
InitiatingProcessFileName,
InitiatingProcessCommandLine,
InitiatingProcessSHA256,
InitiatingProcessIntegrityLevel
| extend timestamp = TimeGenerated,
HostCustomEntity = DeviceName,
AccountCustomEntity = AccountName
| order by TimeGenerated desc
```
```kql
let files1 = dynamic(["C:\\Windows\\TAPI\\lsa.exe", "C:\\Windows\\TAPI\\pa.exe", "C:\\Windows\\TAPI\\pc.exe", "C:\\Windows\\TAPI\\Rar.exe"]);
let files2 = dynamic(["svchost.exe","wdmsvc.exe"]);
let FileHash1 = dynamic(["43109fbe8b752f7a9076eaafa417d9ae5c6e827cd5374b866672263fdebd5ec3", "ab50d8d707b97712178a92bbac74ccc2a5699eb41c17aa77f713ff3e568dcedb", "010e32be0f86545e116a8bc3381a8428933eb8789f32c261c81fd5e7857d4a77", "56cd102b9fc7f3523dad01d632525ff673259dbc9a091be0feff333c931574f7"]);
let FileHash2 = dynamic(["2a1044e9e6e87a032f80c6d9ea6ae61bbbb053c0a21b186ecb3b812b49eb03b7", "9ab7e99ed84f94a7b6409b87e56dc6e1143b05034a5e4455e8c555dbbcd0d2dd", "18a072ccfab239e140d8f682e2874e8ff19d94311fc8bb9564043d3e0deda54b"]);
imProcessCreate
| where ((Process has_any (files1)) and (ActingProcessSHA256 has_any (FileHash1))) or ((Process has_any (files2)) and (ActingProcessSHA256 has_any (FileHash2)))
// Increase risk score if recent alerts for the host
| join kind=leftouter (
SecurityAlert
| where ProviderName =~ "MDATP"
| extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)
| mv-expand todynamic(Entities)
| extend DvcId = tostring(parse_json(Entities).MdatpDeviceId)
| where isnotempty(DvcId)
// Higher risk score are for Defender alerts related to threat actor
| extend AlertRiskScore = iif(ThreatName has_any ("Backdoor:MSIL/ShellClient.A", "Backdoor:MSIL/ShellClient.A!dll", "Trojan:MSIL/Mimikatz.BA!MTB"), 1.0, 0.5)
| project DvcId, AlertRiskScore)
on DvcId
| extend AlertRiskScore = iif(isempty(AlertRiskScore), 0.0, AlertRiskScore)
| extend AccountName = tostring(split(ActorUsername, @'\')[1]), AccountNTDomain = tostring(split(ActorUsername, @'\')[0])
| extend HostName = tostring(split(Dvc, ".")[0]), DomainIndex = toint(indexof(Dvc, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Dvc, DomainIndex + 1), Dvc)
| project-away DomainIndex
```
```kql
let files1 = dynamic(["C:\\Windows\\TAPI\\lsa.exe", "C:\\Windows\\TAPI\\pa.exe", "C:\\Windows\\TAPI\\pc.exe", "C:\\Windows\\TAPI\\Rar.exe"]);
let files2 = dynamic(["svchost.exe","wdmsvc.exe"]);
let FileHash1 = dynamic(["43109fbe8b752f7a9076eaafa417d9ae5c6e827cd5374b866672263fdebd5ec3", "ab50d8d707b97712178a92bbac74ccc2a5699eb41c17aa77f713ff3e568dcedb", "010e32be0f86545e116a8bc3381a8428933eb8789f32c261c81fd5e7857d4a77", "56cd102b9fc7f3523dad01d632525ff673259dbc9a091be0feff333c931574f7"]);
let FileHash2 = dynamic(["2a1044e9e6e87a032f80c6d9ea6ae61bbbb053c0a21b186ecb3b812b49eb03b7", "9ab7e99ed84f94a7b6409b87e56dc6e1143b05034a5e4455e8c555dbbcd0d2dd", "18a072ccfab239e140d8f682e2874e8ff19d94311fc8bb9564043d3e0deda54b"]);
DeviceProcessEvents
| where ( FolderPath has_any (files1) and SHA256 has_any (FileHash1)) or (FolderPath has_any (files2) and SHA256 has_any (FileHash2))
| extend DvcId = DeviceId
| join kind=leftouter (SecurityAlert
| where ProviderName =~ "MDATP"
| extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)
| mv-expand todynamic(Entities)
| extend DvcId = tostring(parse_json(Entities).MdatpDeviceId)
| where isnotempty(DvcId)
// Higher risk score are for Defender alerts related to threat actor
| extend AlertRiskScore = iif(ThreatName has_any ("Backdoor:MSIL/ShellClient.A", "Backdoor:MSIL/ShellClient.A!dll", "Trojan:MSIL/Mimikatz.BA!MTB"), 1.0, 0.5)
| project DvcId, AlertRiskScore) on DvcId
| extend AlertRiskScore = iif(isempty(AlertRiskScore), 0.0, AlertRiskScore)
| extend InitiatingProcessAccount = strcat(InitiatingProcessAccountDomain, "\\", InitiatingProcessAccountName)
| extend HostName = tostring(split(DeviceName, ".")[0]), DomainIndex = toint(indexof(DeviceName, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(DeviceName, DomainIndex + 1), DeviceName)
| extend timestamp = TimeGenerated
```
## Escalation Criteria
- Domain controller involved.
- Known dumping tool signature matched.
- Follow-on authentication observed using a potentially exposed credential.
- Privileged or service account credentials potentially exposed.
## False Positive Considerations
- Windows Defender Antivirus (MsMpEng.exe) — Pre-excluded in the approved list — verify hash matches Microsoft's known-good
- MDE Sense process (SenseCE.exe / MsSense.exe) — Pre-excluded — verify the hash matches the installed MDE version
- Authorised penetration test — Pentest scope document, written approval, date/time window
- Azure AD Connect agent — AzureADConnectAuthenticationAgentService.exe — pre-excluded
Generated by SOC Response Atlas by Basyrix.
Want to push this directly to Confluence? Upgrade to Basyrix Pro.
- /api/techniques/T1003.json
- /api/recommendations/T1003.json
- /api/d3fend/T1003.json
- /api/mappings/T1003.json
- /api/confluence/T1003.md
Example curl:
curl https://atlas.basyrix.com/api/recommendations/T1003.json Response:
{
"technique_id": "T1003",
"name": "OS Credential Dumping",
"priority": "high",
"status": "complete",
"version": "0.1.0",
"last_reviewed": "2026-07-23",
"generated_by": "SOC Response Atlas by Basyrix",
"tactics": [
"Credential Access"
],
"platforms": [
"Windows",
"Linux",
"macOS"
],
"summary": "Adversaries may dump credentials from operating system memory or storage (LSASS, SAM, NTDS.dit, /etc/shadow, keychains) to obtain account credentials for further access and lateral movement.\n",
"soc_recommendation": "Treat any tool or process accessing LSASS memory, the SAM hive, or NTDS.dit outside of known-good backup/administrative tooling as a near-certain credential dumping attempt requiring immediate containment and full credential rotation for anything that may have been exposed.\n",
"d3fend_mappings": [
{
"id": "D3-PSA",
"name": "Process Spawn Analysis",
"relationship": "detect",
"practical_action": "Detect processes opening a handle to lsass.exe outside of known security/monitoring tooling.\n",
"tooling": [
"Defender for Endpoint",
"Sysmon"
]
},
{
"id": "D3-FA",
"name": "File Analysis",
"relationship": "detect",
"practical_action": "Detect access to SAM/SYSTEM hives, NTDS.dit, or shadow copies used to extract them.",
"tooling": [
"Defender for Endpoint"
]
},
{
"id": "D3-KBPI",
"name": "Kernel-based Process Isolation",
"relationship": "isolate",
"practical_action": "Enable Credential Guard / virtualization-based LSASS protection so credential material cannot be read even by a process with local admin.\n",
"tooling": [
"Defender for Endpoint",
"Group Policy"
]
},
{
"id": "D3-CR",
"name": "Credential Revocation",
"relationship": "evict",
"practical_action": "Rotate all credentials that may have been present in memory or the dumped store, including the krbtgt account if domain controllers are involved.",
"tooling": [
"Entra ID",
"Active Directory"
]
}
],
"investigation_steps": {
"microsoft": [
"MDE portal → Device inventory → <DEVICE_NAME> → Isolate device",
"Record: initiating process name, command line, folder path, and SHA256 hash",
"Submit the SHA256 hash to VirusTotal immediately — is it a known tool?",
"Is the process running from %TEMP%, %APPDATA%, C:\\ProgramData, or C:\\Users? → Almost certainly malicious",
"Is the process digitally signed? By whom? (An unsigned process accessing LSASS is extremely high confidence)",
"Notify SOC Manager and open P1 incident ticket",
"Immediately reset the password — do not wait for investigation completion",
"For domain admin accounts: treat as Critical escalation — KRBTGT reset may be required"
],
"generic": [
"Identify the process and technique used to access credential material.",
"Determine the scope of accounts/hashes potentially exposed.",
"Check for follow-on lateral movement using any exposed credential.",
"Real detection reference: \"LSASS Memory Access by Non-Standard Process\" -- Flags processes reading lsass.exe memory outside the small set of expected security/monitoring tools, indicative of credential dumping (Mimikatz, procdump, comsvcs MiniDump)."
]
},
"evidence_to_collect": [
"Host affected (and whether it is a domain controller)",
"Process that accessed the credential store",
"Technique used (LSASS dump, SAM/NTDS extraction, shadow copy)",
"Accounts/hashes potentially exposed",
"Any follow-on authentication using exposed credentials"
],
"response_actions": [
{
"name": "Isolate device",
"category": "Containment",
"risk": "Medium",
"automation_safe": false,
"approval_required": true,
"tool": "Defender for Endpoint",
"notes": "MDE portal"
},
{
"name": "Reset ALL passwords",
"category": "Containment",
"risk": "High",
"automation_safe": false,
"approval_required": true,
"tool": "See investigation guide",
"notes": "for every account with an active session on the host"
},
{
"name": "Disable the initiating account",
"category": "Containment",
"risk": "Medium",
"automation_safe": false,
"approval_required": true,
"tool": "Entra ID",
"notes": "the account running the dump tool — in Entra ID"
},
{
"name": "Purge Kerberos tickets",
"category": "Containment",
"risk": "Medium",
"automation_safe": false,
"approval_required": true,
"tool": "Defender for Endpoint",
"notes": "on all affected hosts: run klist purge via Live Response"
},
{
"name": "Notify customer CISO",
"category": "Containment",
"risk": "Low",
"automation_safe": true,
"approval_required": false,
"tool": "See investigation guide",
"notes": "this is a credential breach affecting potentially multiple accounts"
},
{
"name": "Open P1 incident ticket",
"category": "Containment",
"risk": "Low",
"automation_safe": true,
"approval_required": false,
"tool": "See investigation guide",
"notes": "tag CRED-DUMP-LSASS, P1"
},
{
"name": "Force MFA re-enrolment for all affected accounts",
"category": "Eradication",
"risk": "Low",
"automation_safe": false,
"approval_required": true,
"tool": "See investigation guide"
},
{
"name": "Revoke all active sessions for affected accounts across M365",
"category": "Eradication",
"risk": "Medium",
"automation_safe": false,
"approval_required": true,
"tool": "Entra ID",
"notes": "Revoke all active sessions for affected accounts across M365 and Entra ID"
}
],
"queries": {
"kql": [
{
"name": "GEN-CA-001 — LSASS Memory Access by Non-Standard Process",
"description": "Flags processes reading lsass.exe memory outside the small set of expected security/monitoring tools, indicative of credential dumping (Mimikatz, procdump, comsvcs MiniDump). (Source: Bell Integration baseline detection library, mapped via sub-technique T1003.001.)",
"query": "let AllowedInitiators = dynamic([\n \"MsMpEng.exe\",\n \"MsSense.exe\",\n \"SenseIR.exe\",\n \"wermgr.exe\",\n \"csrss.exe\",\n \"svchost.exe\",\n \"werfault.exe\"\n]);\nDeviceProcessEvents\n| where TimeGenerated >= ago(5m)\n| where ProcessCommandLine has_any (\"lsass\", \"MiniDump\", \"procdump\", \"sekurlsa\")\n| where FileName !in~ (AllowedInitiators)\n| where InitiatingProcessFileName !in~ (AllowedInitiators)\n| project\n TimeGenerated,\n DeviceName,\n DeviceId,\n AccountName,\n FileName,\n ProcessCommandLine,\n InitiatingProcessFileName,\n InitiatingProcessCommandLine,\n InitiatingProcessSHA256,\n InitiatingProcessIntegrityLevel\n| extend timestamp = TimeGenerated,\n HostCustomEntity = DeviceName,\n AccountCustomEntity = AccountName\n| order by TimeGenerated desc"
},
{
"name": "29a29e5d-354e-4f5e-8321-8b39d25047bf — Dev-0228 File Path Hashes November 2021 (ASIM Version)",
"description": "This hunting query looks for file paths/hashes related to observed activity by Dev-0228. The actor is known to use custom version of popular tool like PsExec, Procdump etc. to carry its activity. The risk score associated with each result is based on a number of factors, hosts with higher risk events should be investigated first. This query uses the Microsoft Sentinel Information Model - https://docs.microsoft.com/azure/sentinel/normalization' (Source: Microsoft's official Azure-Sentinel Detections (MIT licensed).)",
"query": "let files1 = dynamic([\"C:\\\\Windows\\\\TAPI\\\\lsa.exe\", \"C:\\\\Windows\\\\TAPI\\\\pa.exe\", \"C:\\\\Windows\\\\TAPI\\\\pc.exe\", \"C:\\\\Windows\\\\TAPI\\\\Rar.exe\"]);\nlet files2 = dynamic([\"svchost.exe\",\"wdmsvc.exe\"]);\nlet FileHash1 = dynamic([\"43109fbe8b752f7a9076eaafa417d9ae5c6e827cd5374b866672263fdebd5ec3\", \"ab50d8d707b97712178a92bbac74ccc2a5699eb41c17aa77f713ff3e568dcedb\", \"010e32be0f86545e116a8bc3381a8428933eb8789f32c261c81fd5e7857d4a77\", \"56cd102b9fc7f3523dad01d632525ff673259dbc9a091be0feff333c931574f7\"]);\nlet FileHash2 = dynamic([\"2a1044e9e6e87a032f80c6d9ea6ae61bbbb053c0a21b186ecb3b812b49eb03b7\", \"9ab7e99ed84f94a7b6409b87e56dc6e1143b05034a5e4455e8c555dbbcd0d2dd\", \"18a072ccfab239e140d8f682e2874e8ff19d94311fc8bb9564043d3e0deda54b\"]);\nimProcessCreate\n| where ((Process has_any (files1)) and (ActingProcessSHA256 has_any (FileHash1))) or ((Process has_any (files2)) and (ActingProcessSHA256 has_any (FileHash2)))\n// Increase risk score if recent alerts for the host\n| join kind=leftouter (\n SecurityAlert\n | where ProviderName =~ \"MDATP\"\n | extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)\n | mv-expand todynamic(Entities)\n | extend DvcId = tostring(parse_json(Entities).MdatpDeviceId)\n | where isnotempty(DvcId)\n // Higher risk score are for Defender alerts related to threat actor\n | extend AlertRiskScore = iif(ThreatName has_any (\"Backdoor:MSIL/ShellClient.A\", \"Backdoor:MSIL/ShellClient.A!dll\", \"Trojan:MSIL/Mimikatz.BA!MTB\"), 1.0, 0.5)\n | project DvcId, AlertRiskScore) \n on DvcId\n| extend AlertRiskScore = iif(isempty(AlertRiskScore), 0.0, AlertRiskScore)\n| extend AccountName = tostring(split(ActorUsername, @'\\')[1]), AccountNTDomain = tostring(split(ActorUsername, @'\\')[0])\n| extend HostName = tostring(split(Dvc, \".\")[0]), DomainIndex = toint(indexof(Dvc, '.'))\n| extend HostNameDomain = iff(DomainIndex != -1, substring(Dvc, DomainIndex + 1), Dvc)\n| project-away DomainIndex"
},
{
"name": "3b443f22-9be9-4c35-ac70-a94757748439 — Dev-0228 File Path Hashes November 2021",
"description": "This hunting query looks for file paths/hashes related to observed activity by Dev-0228. The actor is known to use custom version of popular tool like PsExec, Procdump etc. to carry its activity. The risk score associated with each result is based on a number of factors, hosts with higher risk events should be investigated first.' (Source: Microsoft's official Azure-Sentinel Detections (MIT licensed).)",
"query": "let files1 = dynamic([\"C:\\\\Windows\\\\TAPI\\\\lsa.exe\", \"C:\\\\Windows\\\\TAPI\\\\pa.exe\", \"C:\\\\Windows\\\\TAPI\\\\pc.exe\", \"C:\\\\Windows\\\\TAPI\\\\Rar.exe\"]);\nlet files2 = dynamic([\"svchost.exe\",\"wdmsvc.exe\"]);\nlet FileHash1 = dynamic([\"43109fbe8b752f7a9076eaafa417d9ae5c6e827cd5374b866672263fdebd5ec3\", \"ab50d8d707b97712178a92bbac74ccc2a5699eb41c17aa77f713ff3e568dcedb\", \"010e32be0f86545e116a8bc3381a8428933eb8789f32c261c81fd5e7857d4a77\", \"56cd102b9fc7f3523dad01d632525ff673259dbc9a091be0feff333c931574f7\"]);\nlet FileHash2 = dynamic([\"2a1044e9e6e87a032f80c6d9ea6ae61bbbb053c0a21b186ecb3b812b49eb03b7\", \"9ab7e99ed84f94a7b6409b87e56dc6e1143b05034a5e4455e8c555dbbcd0d2dd\", \"18a072ccfab239e140d8f682e2874e8ff19d94311fc8bb9564043d3e0deda54b\"]);\nDeviceProcessEvents\n| where ( FolderPath has_any (files1) and SHA256 has_any (FileHash1)) or (FolderPath has_any (files2) and SHA256 has_any (FileHash2))\n| extend DvcId = DeviceId\n| join kind=leftouter (SecurityAlert\n| where ProviderName =~ \"MDATP\"\n| extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)\n| mv-expand todynamic(Entities)\n| extend DvcId = tostring(parse_json(Entities).MdatpDeviceId)\n| where isnotempty(DvcId)\n// Higher risk score are for Defender alerts related to threat actor\n| extend AlertRiskScore = iif(ThreatName has_any (\"Backdoor:MSIL/ShellClient.A\", \"Backdoor:MSIL/ShellClient.A!dll\", \"Trojan:MSIL/Mimikatz.BA!MTB\"), 1.0, 0.5)\n| project DvcId, AlertRiskScore) on DvcId\n| extend AlertRiskScore = iif(isempty(AlertRiskScore), 0.0, AlertRiskScore)\n| extend InitiatingProcessAccount = strcat(InitiatingProcessAccountDomain, \"\\\\\", InitiatingProcessAccountName)\n| extend HostName = tostring(split(DeviceName, \".\")[0]), DomainIndex = toint(indexof(DeviceName, '.'))\n| extend HostNameDomain = iff(DomainIndex != -1, substring(DeviceName, DomainIndex + 1), DeviceName)\n| extend timestamp = TimeGenerated"
}
],
"spl": [
{
"name": "Credential dumping tool indicators",
"description": "Search for known dumping tool activity in Splunk.",
"query": "index=endpoint earliest=-24h\n| search process_command_line=\"*lsass*\" OR process_command_line=\"*mimikatz*\"\n"
}
],
"esql": [
{
"name": "ff4599cb-409f-4910-a239-52e4e6f532ff — LSASS Process Access via Windows API",
"description": "(ESQL) Identifies access attempts to the LSASS handle, which may indicate an attempt to dump credentials from LSASS memory. (Source: Elastic's official detection-rules repository (Elastic License v2).)",
"query": "from logs-endpoint.events.api-*, logs-m365_defender.event-* metadata _id, _version, _index\n\n| where event.category == \"api\" and host.os.family == \"windows\" and\n process.Ext.api.name in (\"OpenProcess\", \"OpenThread\", \"ReadProcessMemory\") and\n Target.process.name == \"lsass.exe\" and process.executable is not null and\n\n // Noisy patterns\n not to_lower(process.executable) like \"\"\"c:\\\\program files\\\\*.exe\"\"\" and\n not to_lower(process.executable) like \"\"\"c:\\\\program files (x86)\\\\*.exe\"\"\" and\n not to_lower(process.executable) like \"\"\"c:\\\\programdata\\\\microsoft\\\\windows defender\\\\platform\\\\msmpeng.exe\"\"\" and\n not to_lower(process.executable) like \"\"\"c:\\\\programdata\\\\microsoft\\\\windows defender\\\\platform\\\\*\\\\msmpeng.exe\"\"\"\n\n /* normalize process paths to reduce known random patterns in process.executable */\n| eval Esql.process_path = replace(process.executable, \"\"\"([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\\.tmp|DX[A-Z0-9]{3,4}\\.tmp|7z[A-Z0-9]{3,5}\\.tmp|[0-9\\.\\-\\_]{3,})\"\"\", \"\")\n\n// Group by process path\n| stats Esql.access_count = count(*),\n Esql.count_distinct_hosts = count_distinct(host.id),\n Esql.host_id_values = VALUES(host.id),\n Esql.host_name_values = VALUES(host.name),\n Esql.user_name_values = VALUES(user.name),\n Esql.process_pid_values = VALUES(process.entity_id),\n Esql.process_executable_values = VALUES(process.executable),\n Esql.data_stream_namespace.values = VALUES(data_stream.namespace),\n Esql.user_name_values = VALUES(user.name) by Esql.process_path\n\n// Limit to rare instances limited to 1 unique host\n| where Esql.count_distinct_hosts == 1 and Esql.access_count <= 3\n\n// Extract the single host ID and process into their corresponding ECS fields for alerts exclusion\n| eval host.id = mv_min(Esql.host_id_values),\n host.name = mv_min(Esql.host_name_values),\n process.executable = mv_min(Esql.process_executable_values), \n user.name = mv_min(Esql.user_name_values)\n\n// Add the new field to the keep statement\n| keep Esql.*, host.id, host.name, user.name, process.executable"
},
{
"name": "f3ac6734-7e52-4a0d-90b7-6847bf4308f2 — Web Server Potential Command Injection Request",
"description": "(ESQL) This rule detects potential command injection attempts via web server requests by identifying URLs that contain suspicious patterns commonly associated with command execution payloads. Attackers may exploit vulnerabilities in web applications to inject and execute arbitrary commands on the server, often using interpreters like Python, Perl, Ruby, PHP, or shell commands... (Source: Elastic's official detection-rules repository (Elastic License v2).)",
"query": "from logs-nginx.access-*, logs-apache.access-*, logs-apache_tomcat.access-*, logs-iis.access-*, logs-traefik.access-*\n| where\n // Limit to 200 response code to reduce noise\n http.response.status_code == 200\n\n| eval Esql.url_original_to_lower = to_lower(url.original)\n\n| eval Esql.contains_interpreter = case(Esql.url_original_to_lower like \"*python* -c*\" or Esql.url_original_to_lower like \"*perl* -e*\" or Esql.url_original_to_lower like \"*ruby* -e*\" or Esql.url_original_to_lower like \"*ruby* -rsocket*\" or Esql.url_original_to_lower like \"*lua* -e*\" or Esql.url_original_to_lower like \"*php* -r*\" or Esql.url_original_to_lower like \"*node* -e*\", 1, 0)\n| eval Esql.contains_shell = case(Esql.url_original_to_lower like \"*/bin/bash*\" or Esql.url_original_to_lower like \"*bash*-c*\" or Esql.url_original_to_lower like \"*/bin/sh*\" or Esql.url_original_to_lower rlike \"*sh.{1,2}-c*\", 1, 0)\n| eval Esql.contains_nc = case(Esql.url_original_to_lower like \"*netcat*\" or Esql.url_original_to_lower like \"*ncat*\" or Esql.url_original_to_lower rlike \"\"\".*nc.{1,2}[0-9]{1,3}(\\.[0-9]{1,3}){3}.{1,2}[0-9]{1,5}.*\"\"\" or Esql.url_original_to_lower like \"*nc.openbsd*\" or Esql.url_original_to_lower like \"*nc.traditional*\" or Esql.url_original_to_lower like \"*socat*\", 1, 0)\n| eval Esql.contains_devtcp = case(Esql.url_original_to_lower like \"*/dev/tcp/*\" or Esql.url_original_to_lower like \"*/dev/udp/*\", 1, 0)\n| eval Esql.contains_helpers = case((Esql.url_original_to_lower like \"*/bin/*\" or Esql.url_original_to_lower like \"*/usr/bin/*\") and (Esql.url_original_to_lower like \"*mkfifo*\" or Esql.url_original_to_lower like \"*nohup*\" or Esql.url_original_to_lower like \"*setsid*\" or Esql.url_original_to_lower like \"*busybox*\"), 1, 0)\n| eval Esql.contains_sus_cli = case(Esql.url_original_to_lower like \"*import*pty*spawn*\" or Esql.url_original_to_lower like \"*import*subprocess*call*\" or Esql.url_original_to_lower like \"*tcpsocket.new*\" or Esql.url_original_to_lower like \"*tcpsocket.open*\" or Esql.url_original_to_lower like \"*io.popen*\" or Esql.url_original_to_lower like \"*os.execute*\" or Esql.url_original_to_lower like \"*fsockopen*\", 1, 0)\n| eval Esql.contains_privileges = case(Esql.url_original_to_lower like \"*chmod*+x\", 1, 0)\n| eval Esql.contains_downloader = case(Esql.url_original_to_lower like \"*curl *\" or Esql.url_original_to_lower like \"*wget *\" , 1, 0)\n| eval Esql.contains_file_read_keywords = case(Esql.url_original_to_lower like \"*/etc/shadow*\" or Esql.url_original_to_lower like \"*/etc/passwd*\" or Esql.url_original_to_lower like \"*/root/.ssh/*\" or Esql.url_original_to_lower like \"*/home/*/.ssh/*\" or Esql.url_original_to_lower like \"*~/.ssh/*\" or Esql.url_original_to_lower like \"*/proc/self/environ*\", 1, 0)\n| eval Esql.contains_base64_cmd = case(Esql.url_original_to_lower like \"*base64*-d*\" or Esql.url_original_to_lower like \"*echo*|*base64*\", 1, 0)\n| eval Esql.contains_suspicious_path = case(Esql.url_original_to_lower like \"*/tmp/*\" or Esql.url_original_to_lower like \"*/var/tmp/*\" or Esql.url_original_to_lower like \"*/dev/shm/*\" or Esql.url_original_to_lower like \"*/root/*\" or Esql.url_original_to_lower like \"*/home/*/*\" or Esql.url_original_to_lower like \"*/var/www/*\" or Esql.url_original_to_lower like \"*/etc/cron.*/*\", 1, 0)\n\n| eval Esql.any_payload_keyword = case(\n Esql.contains_interpreter == 1 or Esql.contains_shell == 1 or Esql.contains_nc == 1 or Esql.contains_devtcp == 1 or\n Esql.contains_helpers == 1 or Esql.contains_sus_cli == 1 or Esql.contains_privileges == 1 or Esql.contains_downloader == 1 or\n Esql.contains_file_read_keywords == 1 or Esql.contains_base64_cmd == 1 or Esql.contains_suspicious_path == 1, 1, 0)\n\n| keep\n @timestamp,\n Esql.url_original_to_lower,\n Esql.any_payload_keyword,\n Esql.contains_interpreter,\n Esql.contains_shell,\n Esql.contains_nc,\n Esql.contains_devtcp,\n Esql.contains_helpers,\n Esql.contains_sus_cli,\n Esql.contains_privileges,\n Esql.contains_downloader,\n Esql.contains_file_read_keywords,\n Esql.contains_base64_cmd,\n Esql.contains_suspicious_path,\n source.ip,\n destination.ip,\n agent.id,\n http.request.method,\n http.response.status_code,\n user_agent.original,\n agent.name,\n data_stream.dataset,\n data_stream.namespace\n\n| stats\n Esql.event_count = count(),\n Esql.url_path_count_distinct = count_distinct(Esql.url_original_to_lower),\n\n // General fields\n\n Esql.agent_name_values = values(agent.name),\n Esql.agent_id_values = values(agent.id),\n Esql.url_path_values = values(Esql.url_original_to_lower),\n Esql.http.response.status_code_values = values(http.response.status_code),\n Esql.user_agent_original_values = values(user_agent.original),\n Esql.data_stream_dataset_values = values(data_stream.dataset),\n Esql.data_stream_namespace_values = values(data_stream.namespace),\n\n // Rule Specific fields\n Esql.any_payload_keyword_max = max(Esql.any_payload_keyword),\n Esql.contains_interpreter_values = values(Esql.contains_interpreter),\n Esql.contains_shell_values = values(Esql.contains_shell),\n Esql.contains_nc_values = values(Esql.contains_nc),\n Esql.contains_devtcp_values = values(Esql.contains_devtcp),\n Esql.contains_helpers_values = values(Esql.contains_helpers),\n Esql.contains_sus_cli_values = values(Esql.contains_sus_cli),\n Esql.contains_privileges_values = values(Esql.contains_privileges),\n Esql.contains_downloader_values = values(Esql.contains_downloader),\n Esql.contains_file_read_keywords_values = values(Esql.contains_file_read_keywords),\n Esql.contains_base64_cmd_values = values(Esql.contains_base64_cmd),\n Esql.contains_suspicious_path_values = values(Esql.contains_suspicious_path)\n\n by source.ip, agent.id\n\n| where\n // Filter for potential command injection attempts with low event counts to reduce false positives\n Esql.any_payload_keyword_max == 1 and Esql.event_count < 5"
}
]
},
"automation": {
"safe": [
"Add recommendation as Sentinel incident comment.",
"Kill a confirmed-malicious dumping process.",
"Create ServiceNow SecOps task."
],
"approval_required": [
"Isolate the host.",
"Rotate potentially exposed credentials (including krbtgt)."
]
},
"escalation_criteria": [
"Domain controller involved.",
"Known dumping tool signature matched.",
"Follow-on authentication observed using a potentially exposed credential.",
"Privileged or service account credentials potentially exposed."
],
"false_positive_considerations": [
"Windows Defender Antivirus (MsMpEng.exe) — Pre-excluded in the approved list — verify hash matches Microsoft's known-good",
"MDE Sense process (SenseCE.exe / MsSense.exe) — Pre-excluded — verify the hash matches the installed MDE version",
"Authorised penetration test — Pentest scope document, written approval, date/time window",
"Azure AD Connect agent — AzureADConnectAuthenticationAgentService.exe — pre-excluded"
],
"confluence": {
"title": "T1003 - OS Credential Dumping Response Guidance",
"labels": [
"mitre",
"attack",
"d3fend",
"secops",
"basyrix"
],
"sections": [
"summary",
"d3fend_mappings",
"investigation_steps",
"response_actions",
"queries",
"automation",
"escalation_criteria",
"false_positive_considerations"
]
}
}