Potential PowerShell Pass-the-Hash/Relay Script

edit
IMPORTANT: This documentation is no longer updated. Refer to Elastic's version policy and the latest documentation.

Potential PowerShell Pass-the-Hash/Relay Script

edit

Detects PowerShell scripts associated with NTLM relay or pass-the-hash tooling and SMB/NTLM negotiation artifacts. Attackers use relay and PtH techniques to authenticate without passwords and pivot to other systems.

Rule type: query

Rule indices:

  • logs-windows.powershell*
  • winlogbeat-*

Severity: high

Risk score: 73

Runs every: 5m

Searches indices from: now-9m (Date Math format, see also Additional look-back time)

Maximum alerts per execution: 100

References:

Tags:

  • Domain: Endpoint
  • OS: Windows
  • Use Case: Threat Detection
  • Tactic: Credential Access
  • Resources: Investigation Guide
  • Data Source: PowerShell Logs

Version: 110

Rule authors:

  • Elastic

Rule license: Elastic License v2

Investigation guide

edit

Triage and analysis

Investigating Potential PowerShell Pass-the-Hash/Relay Script

Possible investigation steps

  • Does the visible script content implement relay-listener behavior, pass-the-hash execution, target validation, or more than one?
  • Focus: powershell.file.script_block_text and any file-backed file.path.
  • Implication: escalate when the fragment builds NTLMSSP/SMB messages, starts HTTP/SMB/proxy listeners, forwards authentication, references WMI/SMB/WinRM helpers, or pairs byte arrays with target selection; lower suspicion only for parser or lab text with no targeting, listener, credential, or execution logic.
  • Does full script reconstruction reveal target lists, credential material, service names, or listener settings the matching fragment did not show?
  • Why: script block logging often splits relay mode, target configuration, and execution helpers into separate fragments.
  • Focus: powershell.file.script_block_id, powershell.sequence, powershell.total, and reconstructed powershell.file.script_block_text on host.id; reassemble by powershell.sequence and treat missing fragments as unresolved. !{investigate{"description":"","label":"All PowerShell 4104 fragments for this script on this host","providers":[[{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"powershell.file.script_block_id","queryType":"phrase","value":"{{powershell.file.script_block_id}}","valueType":"string"},{"excluded":false,"field":"event.code","queryType":"phrase","value":"4104","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • Implication: escalate on remote targets, password hashes, "TargetList", "SMBRelayTarget", "wpad.dat", "WPAD", listener ports, service names, execution helpers, or fan-out logic; lower suspicion only for research or validation code with no credential material, targets, listener, or execution path.
  • Which recovered PowerShell process explains launch context and downstream pivots?
  • Focus: If endpoint process telemetry exists, recover the matching process via host.id + process.pid before interpreting process.* or process.parent.*; if absent, keep launch context unresolved. Record process.command_line, process.parent.executable, process.Ext.session_info.logon_type, process.Ext.authentication_id, and process.entity_id. !{investigate{"description":"","label":"Process events for the PowerShell instance","providers":[[{"excluded":false,"field":"process.pid","queryType":"phrase","value":"{{process.pid}}","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"event.category","queryType":"phrase","value":"process","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • Implication: escalate when the recovered launch shows encoded commands, remote-administration launchers, Office or browser parents, elevated context, or service/network logon sessions that do not fit the user; do not infer legitimacy from process.pid alone.
  • Do authentication events show local operator context or relay/PtH follow-on?
  • Focus: same-host.id/user.id Windows Security events for event.code 4624, 4625, or 4648; review source.ip, winlog.event_data.AuthenticationPackageName, and winlog.logon.type. !{investigate{"description":"","label":"Windows Security authentication events for the user","providers":[[{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"user.id","queryType":"phrase","value":"{{user.id}}","valueType":"string"},{"excluded":false,"field":"event.code","queryType":"phrase","value":"4624","valueType":"string"}],[{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"user.id","queryType":"phrase","value":"{{user.id}}","valueType":"string"},{"excluded":false,"field":"event.code","queryType":"phrase","value":"4625","valueType":"string"}],[{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"user.id","queryType":"phrase","value":"{{user.id}}","valueType":"string"},{"excluded":false,"field":"event.code","queryType":"phrase","value":"4648","valueType":"string"}]],"relativeFrom":"now-24h","relativeTo":"now"}}
  • Hint: bridge recovered process.Ext.authentication_id to winlog.event_data.TargetLogonId only for the local session; prove relay/PtH with same-host inbound NTLM without user.id, target-host 4624/4625, or DC-side 4776 for reconstructed targets or sources.
  • Implication: escalate when local, target-host, or DC authentication shows unexpected type 3 NTLM, repeated failures, privileged sessions, or explicit-credential use tied to reconstructed targets; missing authentication telemetry is unresolved, not benign.
  • Do network events show outbound relay or hash-validation activity to targets named in the script?
  • Why: relay code often resolves targets, then reaches SMB, RPC, WinRM, or HTTP destinations; listener-only capture may not.
  • Focus: If endpoint network telemetry exists, scope same-host events to host.id, process.pid, and the alert window, or use reconstructed targets when process identity is unavailable; separate DNS (dns.question.name, dns.resolved_ip) from connections (destination.ip, destination.port). !{investigate{"description":"","label":"Network events for the PowerShell process","providers":[[{"excluded":false,"field":"process.pid","queryType":"phrase","value":"{{process.pid}}","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"event.category","queryType":"phrase","value":"network","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • Implication: escalate when the host fans out to named targets or reaches SMB, RPC, WinRM, or relay ports (80, 443, 445) outside the declared test scope; listener scripts stay suspicious with little outbound traffic when reconstruction shows "SMBRelayTarget", "wpad.dat", or similar relay-ready settings. Missing network telemetry is unresolved, not benign.
  • If local evidence remains suspicious or incomplete, do related alerts widen the user or host scope?
  • Focus: related alerts for user.id; if quiet, compare host.id for adjacent relay, pass-the-hash, remote-service, persistence, or post-compromise alerts.
  • !{investigate{"description":"","label":"Alerts associated with the user","providers":[[{"excluded":false,"field":"event.kind","queryType":"phrase","value":"signal","valueType":"string"},{"excluded":false,"field":"user.id","queryType":"phrase","value":"{{user.id}}","valueType":"string"}]],"relativeFrom":"now-48h/h","relativeTo":"now"}}
  • !{investigate{"description":"","label":"Alerts associated with the host","providers":[[{"excluded":false,"field":"event.kind","queryType":"phrase","value":"signal","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"}]],"relativeFrom":"now-48h/h","relativeTo":"now"}}
  • Implication: broaden when local evidence stays suspicious or unresolved and related alerts show connected relay, listener-only capture, hash-validation fan-out, or lateral-movement behavior; keep local when surrounding alerts are absent or confined to the same declared test scope.
  • Weigh script intent, reconstruction, launch context, authentication follow-on, network contact, and related-alert scope: escalate when they align on unauthorized relay or pass-the-hash activity; close only when reconstructed content, launch, source, and available auth or network evidence support one controlled workflow with no contradictions; preserve and escalate if evidence is mixed or incomplete.

False positive analysis

  • Controlled testing, incident-response, or protocol-research workflows can trigger this rule when reconstructed powershell.file.script_block_text names only recognized targets or stays limited to parser/validation routines, recovered launch context matches the operator workflow, and authentication or network telemetry shows no live relay, listener, or execution outside scope. If engagement or change records exist, require alignment; otherwise, confirm recurring user.id, host.id, source pattern, recovered launch pattern, and target or port pattern across prior alerts from this rule. Do not close if hashes, listener ports, or follow-on authentication diverge.
  • Before creating an exception, validate recurring user.id, host.id, recovered launch pattern, source pattern, and target set across prior alerts. Build the exception from that minimum workflow. Avoid exceptions on byte sequences alone, user.name alone, or host alone.

Response and remediation

  • If confirmed benign, reverse any temporary containment and document the script content, recovered launch chain, source path pattern, target set, and session origin or logon-type pattern that proved the lab, response, or troubleshooting workflow. Create an exception only if the same workflow recurs across prior alerts from this rule.
  • If suspicious but unconfirmed, preserve the reconstructed powershell.file.script_block_text, powershell.file.script_block_id, fragment ordering metadata, recovered process and parent details, named targets, listener ports, service names, UNC paths, and related authentication or network evidence before destructive actions.
  • Apply reversible containment first, such as host isolation if tolerable or temporary controls on exposed accounts and named targets. Avoid terminating processes or deleting artifacts until possible credential misuse and lateral movement scope is clearer.
  • If confirmed malicious, isolate the endpoint when possible; otherwise escalate with the recorded host.id, recovered process identifiers, source IP values, named targets, and authentication evidence. Rotate or invalidate impacted credentials, review named systems for successful SMB/WMI/WinRM/service activity, restrict exposed NTLM pathways where supported, then remove only the scripts, services, scheduled tasks, persistence, or staging artifacts found during the investigation.
  • Retain PowerShell Script Block Logging plus supporting endpoint, authentication, and network telemetry. Document adjacent variants such as listener-only capture, hash-validation fan-out, or non-PowerShell relay/pass-the-hash alerts for detection follow-up.

Setup

edit

Setup

PowerShell Script Block Logging must be enabled to generate the events used by this rule (e.g., 4104). Setup instructions: https://ela.st/powershell-logging-setup

Rule query

edit
event.category:process and host.os.type:windows and
  powershell.file.script_block_text : (
    ("NTLMSSPNegotiate" and ("NegotiateSMB" or "NegotiateSMB2")) or
    "4E544C4D53535000" or
    "0x4e,0x54,0x4c,0x4d,0x53,0x53,0x50" or
    "0x4e,0x54,0x20,0x4c,0x4d" or
    "0x53,0x4d,0x42,0x20,0x32" or
    "0x81,0xbb,0x7a,0x36,0x44,0x98,0xf1,0x35,0xad,0x32,0x98,0xf0,0x38"
  ) and
  not file.directory : "C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Downloads"

Framework: MITRE ATT&CKTM