PowerShell Kerberos Ticket Request

Detects PowerShell script content that references KerberosRequestorSecurityToken, which can request Kerberos service tickets. Attackers request service tickets to perform Kerberoasting for offline password cracking of service accounts.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2022/01/24"
  3integration = ["windows"]
  4maturity = "production"
  5updated_date = "2026/04/27"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Detects PowerShell script content that references KerberosRequestorSecurityToken, which can request Kerberos service
 11tickets. Attackers request service tickets to perform Kerberoasting for offline password cracking of service accounts.
 12"""
 13from = "now-9m"
 14index = ["logs-windows.powershell*", "winlogbeat-*"]
 15language = "kuery"
 16license = "Elastic License v2"
 17name = "PowerShell Kerberos Ticket Request"
 18references = [
 19    "https://www.cobalt.io/blog/kerberoast-attack-techniques",
 20    "https://github.com/EmpireProject/Empire/blob/master/data/module_source/credentials/Invoke-Kerberoast.ps1",
 21]
 22risk_score = 73
 23rule_id = "eb610e70-f9e6-4949-82b9-f1c5bcd37c39"
 24severity = "high"
 25tags = [
 26    "Domain: Endpoint",
 27    "OS: Windows",
 28    "Use Case: Threat Detection",
 29    "Tactic: Credential Access",
 30    "Resources: Investigation Guide",
 31    "Data Source: PowerShell Logs",
 32]
 33timestamp_override = "event.ingested"
 34type = "query"
 35
 36query = '''
 37event.category:process and host.os.type:windows and
 38  powershell.file.script_block_text : "KerberosRequestorSecurityToken" and
 39  not powershell.file.script_block_text : (
 40    ("sentinelbreakpoints" and ("Set-PSBreakpoint" or "Set-HookFunctionTabs")) or
 41    ("function global" and "\\windows\\sentinel\\4")
 42  )
 43'''
 44
 45note = """## Triage and analysis
 46
 47### Investigating PowerShell Kerberos Ticket Request
 48
 49#### Possible investigation steps
 50
 51- What does the reconstructed script actually do with KerberosRequestorSecurityToken?
 52  - Focus: Reconstruct full 4104 content on `host.id` with `powershell.file.script_block_id`, `powershell.sequence`, and `powershell.total`; interpret `powershell.file.script_block_text`.
 53  - Hint: pull fragments with matching `host.id` and `powershell.file.script_block_id`, order by `powershell.sequence`, and note gaps before judging intent. $investigate_2
 54  - Implication: escalate when the script requests SPN TGS tickets, loops across "Get-DomainUser -SPN" results, or emits John/Hashcat, "TicketByteHexStream", "$krb5tgs$", or ".kirbi" material; lower suspicion only when reconstruction proves incidental text, comments, or a bounded fixed-SPN test with no output logic.
 55
 56- Do the user, host, and script source fit a bounded recognized Kerberos test?
 57  - Focus: `user.id`, `user.name`, `user.domain`, `host.id`, and `file.path`.
 58  - Hint: absent `file.path` means the script block may be interactive, pasted, or generated in memory, so require stronger corroboration before closure.
 59  - Implication: escalate when a standard user, shared workstation, production server, user-writable `file.path`, or absent `file.path` pairs with broad SPN targeting; lower suspicion only for a recognized identity test or Kerberos diagnostic on the expected host and user with a fixed SPN set.
 60
 61- If endpoint process telemetry is available for this host, how did the PowerShell session start?
 62  - Focus: `process.command_line`, `process.parent.executable`, `process.parent.command_line`, and `process.Ext.session_info.logon_type`.
 63  - Hint: recover the process via `host.id + process.pid` before interpreting `process.*` or `process.parent.*`; if absent after a wider lookup, keep launch context unresolved and scope later pivots with `host.id`, `user.id`, and alert time. $investigate_3
 64  - Implication: escalate when launch context shows encoded commands, pasted or remote delivery, Office or browser parents, unexpected service or network logon, or alternate-credential use; lower suspicion when command line and parent chain match the exact recognized test workflow.
 65
 66- Did the activity create ticket, hash, or target-list artifacts?
 67  - Focus: If endpoint file telemetry exists, scope writes to `host.id`, `user.id`, and the alert window; use the recovered process only after process recovery succeeds, and review `file.path` and `file.Ext.header_bytes`. $investigate_4
 68  - Implication: escalate when writes show SPN lists, ".kirbi" tickets, "$krb5tgs$" or John/Hashcat text, "TicketByteHexStream", base64 blobs, archives, or temp/share/user-writable staging; no file output does not clear direct hash output or memory-only ticket export, and missing file telemetry is unresolved, not benign.
 69
 70- Do domain-controller ticket events confirm active Kerberoasting behavior?
 71  - Focus: DC-side Windows Security `event.code` 4769 near alert time, starting with `winlog.event_data.TargetUserName` = alert `user.name` for domain requesters; review `winlog.event_data.TargetDomainName`, `source.ip`, `winlog.event_data.ServiceName`, `winlog.event_data.TicketEncryptionType`, and target SPN volume. $investigate_5
 72  - Hint: if the alert user is local, SYSTEM, or the transform is quiet, retry DC 4769 with UPN/domain variants from `user.name` + `user.domain`, then pivot by source host/address and candidate requester from reconstruction or launch context.
 73  - Implication: escalate when 4769 events show broad SPN enumeration, RC4 or weak encryption, service-account-heavy targeting, or client addresses inconsistent with the expected workflow. Missing authentication telemetry is unresolved, not benign.
 74
 75- Is this ticket-request activity isolated or part of broader suspicious behavior?
 76  - Focus: same-scope events or alerts for `user.id` in the last 48 hours for credential access, execution, discovery, or lateral movement. $investigate_0
 77  - Hint: use the host pivot separately when user scope is noisy or service-account-heavy. $investigate_1
 78  - Implication: broaden response when either pivot shows adjacent credential access, execution, discovery, or lateral movement; keep the case local only when related alerts stay quiet or match the same bounded recognized workflow.
 79
 80- Escalate active service-ticket collection without a recognized owner or with suspicious scope, output, launch, artifact, DC 4769, or same-scope evidence; close only when alert-local evidence and supported recovery bind one exact bounded workflow and outside confirmation resolves gaps; preserve evidence and escalate when findings are mixed or incomplete.
 81
 82### False positive analysis
 83
 84- Recognized Kerberos diagnostics, identity validation, or red-team tests can trigger this rule when reconstructed `powershell.file.script_block_text` stays limited to a fixed SPN set, creates no ticket or hash output, and the script source fits. If process telemetry was recovered via `host.id + process.pid`, require `process.command_line` and `process.parent.executable` to match. Require test-record alignment when present; otherwise close only when current telemetry proves the same fixed-SPN, no-output, user-host, source, and launch-chain pattern.
 85- Build exceptions from the minimum confirmed workflow: `user.id`, `host.id`, exact source pattern, recovered launch chain, and fixed SPN set. If prior alerts exist, verify they do not add expanded targets, crackable output, or a different launch path; for a first verified case, prefer a narrow candidate or time-bounded exception over broad suppression. Avoid exceptions on "KerberosRequestorSecurityToken" alone, `user.name` alone, or host alone.
 86
 87### Response and remediation
 88
 89- If confirmed benign, reverse any temporary containment and record the evidence that proved the recognized diagnostics, lab, or identity-test workflow: stable user-host pairing, fixed SPN scope, script source, recovered launch chain when available, and no contradictory artifact or same-scope evidence. Create only a narrow exception from that confirmed evidence; use prior alerts to tighten scope when they exist, not as the primary proof.
 90- If suspicious but unconfirmed, preserve the reconstructed `powershell.file.script_block_text`, `powershell.file.script_block_id`, `powershell.sequence`, `powershell.total`, `process.pid`, any recovered process details, named SPNs, output paths, and available identity records before containment. Apply reversible containment first, such as temporary host isolation or account restriction matched to host criticality, and avoid destructive cleanup until service-account exposure is scoped.
 91- If confirmed malicious, contain the host and affected account when script intent, recovered launch context, named SPNs, output artifacts, or same-scope events support unauthorized ticket collection. Record the recovered PowerShell command line, parent chain, named SPNs, output locations, and available identity evidence before terminating processes, deleting files, or purging sessions.
 92- If targeted or bulk service-ticket requests are confirmed, prioritize the named service accounts for password rotation, privilege review, and downstream logon analysis, then review affected services for anomalous authentication or access tied to the same period.
 93- Eradicate only the unauthorized scripts, SPN lists, ticket or hash output, scheduled tasks, and persistence mechanisms uncovered during the investigation, then remediate the delivery path or administrative-control gap that allowed the script to run.
 94- After containment, hunt for the same reconstructed script fragments, SPN patterns, and ticket-request evidence across other hosts, and retain PowerShell Script Block Logging plus supporting endpoint or identity telemetry where gaps limited the investigation.
 95"""
 96
 97setup = """## Setup
 98
 99PowerShell Script Block Logging must be enabled to generate the events used by this rule (e.g., 4104).
100Setup instructions: https://ela.st/powershell-logging-setup
101"""
102
103[rule.investigation_fields]
104field_names = [
105    "@timestamp",
106    "user.name",
107    "user.id",
108    "user.domain",
109    "powershell.file.script_block_text",
110    "powershell.file.script_block_id",
111    "powershell.sequence",
112    "powershell.total",
113    "file.path",
114    "file.directory",
115    "file.name",
116    "process.pid",
117    "host.name",
118    "host.id",
119    "powershell.file.script_block_length"
120]
121
122[transform]
123
124[[transform.investigate]]
125label = "Alerts associated with the user"
126description = ""
127providers = [
128  [
129    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
130    { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
131  ]
132]
133relativeFrom = "now-48h/h"
134relativeTo = "now"
135
136[[transform.investigate]]
137label = "Alerts associated with the host"
138description = ""
139providers = [
140  [
141    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
142    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
143  ]
144]
145relativeFrom = "now-48h/h"
146relativeTo = "now"
147
148[[transform.investigate]]
149label = "All PowerShell 4104 fragments for this script on this host"
150description = ""
151providers = [
152  [
153    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
154    { excluded = false, field = "powershell.file.script_block_id", queryType = "phrase", value = "{{powershell.file.script_block_id}}", valueType = "string" },
155    { excluded = false, field = "event.code", queryType = "phrase", value = "4104", valueType = "string" }
156  ]
157]
158relativeFrom = "now-1h"
159relativeTo = "now"
160
161[[transform.investigate]]
162label = "Process events for the PowerShell instance"
163description = ""
164providers = [
165  [
166    { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" },
167    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
168    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" }
169  ]
170]
171relativeFrom = "now-1h"
172relativeTo = "now"
173
174[[transform.investigate]]
175label = "File events for the PowerShell process"
176description = ""
177providers = [
178  [
179    { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" },
180    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
181    { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" }
182  ]
183]
184relativeFrom = "now-1h"
185relativeTo = "now"
186
187[[transform.investigate]]
188label = "Kerberos service ticket events for the alert user name"
189description = ""
190providers = [
191  [
192    { excluded = false, field = "winlog.event_data.TargetUserName", queryType = "phrase", value = "{{user.name}}", valueType = "string" },
193    { excluded = false, field = "event.code", queryType = "phrase", value = "4769", valueType = "string" }
194  ]
195]
196relativeFrom = "now-24h"
197relativeTo = "now"
198
199[[rule.threat]]
200framework = "MITRE ATT&CK"
201[[rule.threat.technique]]
202id = "T1558"
203name = "Steal or Forge Kerberos Tickets"
204reference = "https://attack.mitre.org/techniques/T1558/"
205[[rule.threat.technique.subtechnique]]
206id = "T1558.003"
207name = "Kerberoasting"
208reference = "https://attack.mitre.org/techniques/T1558/003/"
209
210[rule.threat.tactic]
211id = "TA0006"
212name = "Credential Access"
213reference = "https://attack.mitre.org/tactics/TA0006/"
214
215[[rule.threat]]
216framework = "MITRE ATT&CK"
217[[rule.threat.technique]]
218id = "T1059"
219name = "Command and Scripting Interpreter"
220reference = "https://attack.mitre.org/techniques/T1059/"
221[[rule.threat.technique.subtechnique]]
222id = "T1059.001"
223name = "PowerShell"
224reference = "https://attack.mitre.org/techniques/T1059/001/"
225
226[rule.threat.tactic]
227id = "TA0002"
228name = "Execution"
229reference = "https://attack.mitre.org/tactics/TA0002/"

Triage and analysis

Investigating PowerShell Kerberos Ticket Request

Possible investigation steps

  • What does the reconstructed script actually do with KerberosRequestorSecurityToken?

    • Focus: Reconstruct full 4104 content on host.id with powershell.file.script_block_id, powershell.sequence, and powershell.total; interpret powershell.file.script_block_text.
    • Hint: pull fragments with matching host.id and powershell.file.script_block_id, order by powershell.sequence, and note gaps before judging intent. $investigate_2
    • Implication: escalate when the script requests SPN TGS tickets, loops across "Get-DomainUser -SPN" results, or emits John/Hashcat, "TicketByteHexStream", "$krb5tgs$", or ".kirbi" material; lower suspicion only when reconstruction proves incidental text, comments, or a bounded fixed-SPN test with no output logic.
  • Do the user, host, and script source fit a bounded recognized Kerberos test?

    • Focus: user.id, user.name, user.domain, host.id, and file.path.
    • Hint: absent file.path means the script block may be interactive, pasted, or generated in memory, so require stronger corroboration before closure.
    • Implication: escalate when a standard user, shared workstation, production server, user-writable file.path, or absent file.path pairs with broad SPN targeting; lower suspicion only for a recognized identity test or Kerberos diagnostic on the expected host and user with a fixed SPN set.
  • If endpoint process telemetry is available for this host, how did the PowerShell session start?

    • Focus: process.command_line, process.parent.executable, process.parent.command_line, and process.Ext.session_info.logon_type.
    • Hint: recover the process via host.id + process.pid before interpreting process.* or process.parent.*; if absent after a wider lookup, keep launch context unresolved and scope later pivots with host.id, user.id, and alert time. $investigate_3
    • Implication: escalate when launch context shows encoded commands, pasted or remote delivery, Office or browser parents, unexpected service or network logon, or alternate-credential use; lower suspicion when command line and parent chain match the exact recognized test workflow.
  • Did the activity create ticket, hash, or target-list artifacts?

    • Focus: If endpoint file telemetry exists, scope writes to host.id, user.id, and the alert window; use the recovered process only after process recovery succeeds, and review file.path and file.Ext.header_bytes. $investigate_4
    • Implication: escalate when writes show SPN lists, ".kirbi" tickets, "$krb5tgs$" or John/Hashcat text, "TicketByteHexStream", base64 blobs, archives, or temp/share/user-writable staging; no file output does not clear direct hash output or memory-only ticket export, and missing file telemetry is unresolved, not benign.
  • Do domain-controller ticket events confirm active Kerberoasting behavior?

    • Focus: DC-side Windows Security event.code 4769 near alert time, starting with winlog.event_data.TargetUserName = alert user.name for domain requesters; review winlog.event_data.TargetDomainName, source.ip, winlog.event_data.ServiceName, winlog.event_data.TicketEncryptionType, and target SPN volume. $investigate_5
    • Hint: if the alert user is local, SYSTEM, or the transform is quiet, retry DC 4769 with UPN/domain variants from user.name + user.domain, then pivot by source host/address and candidate requester from reconstruction or launch context.
    • Implication: escalate when 4769 events show broad SPN enumeration, RC4 or weak encryption, service-account-heavy targeting, or client addresses inconsistent with the expected workflow. Missing authentication telemetry is unresolved, not benign.
  • Is this ticket-request activity isolated or part of broader suspicious behavior?

    • Focus: same-scope events or alerts for user.id in the last 48 hours for credential access, execution, discovery, or lateral movement. $investigate_0
    • Hint: use the host pivot separately when user scope is noisy or service-account-heavy. $investigate_1
    • Implication: broaden response when either pivot shows adjacent credential access, execution, discovery, or lateral movement; keep the case local only when related alerts stay quiet or match the same bounded recognized workflow.
  • Escalate active service-ticket collection without a recognized owner or with suspicious scope, output, launch, artifact, DC 4769, or same-scope evidence; close only when alert-local evidence and supported recovery bind one exact bounded workflow and outside confirmation resolves gaps; preserve evidence and escalate when findings are mixed or incomplete.

False positive analysis

  • Recognized Kerberos diagnostics, identity validation, or red-team tests can trigger this rule when reconstructed powershell.file.script_block_text stays limited to a fixed SPN set, creates no ticket or hash output, and the script source fits. If process telemetry was recovered via host.id + process.pid, require process.command_line and process.parent.executable to match. Require test-record alignment when present; otherwise close only when current telemetry proves the same fixed-SPN, no-output, user-host, source, and launch-chain pattern.
  • Build exceptions from the minimum confirmed workflow: user.id, host.id, exact source pattern, recovered launch chain, and fixed SPN set. If prior alerts exist, verify they do not add expanded targets, crackable output, or a different launch path; for a first verified case, prefer a narrow candidate or time-bounded exception over broad suppression. Avoid exceptions on "KerberosRequestorSecurityToken" alone, user.name alone, or host alone.

Response and remediation

  • If confirmed benign, reverse any temporary containment and record the evidence that proved the recognized diagnostics, lab, or identity-test workflow: stable user-host pairing, fixed SPN scope, script source, recovered launch chain when available, and no contradictory artifact or same-scope evidence. Create only a narrow exception from that confirmed evidence; use prior alerts to tighten scope when they exist, not as the primary proof.
  • If suspicious but unconfirmed, preserve the reconstructed powershell.file.script_block_text, powershell.file.script_block_id, powershell.sequence, powershell.total, process.pid, any recovered process details, named SPNs, output paths, and available identity records before containment. Apply reversible containment first, such as temporary host isolation or account restriction matched to host criticality, and avoid destructive cleanup until service-account exposure is scoped.
  • If confirmed malicious, contain the host and affected account when script intent, recovered launch context, named SPNs, output artifacts, or same-scope events support unauthorized ticket collection. Record the recovered PowerShell command line, parent chain, named SPNs, output locations, and available identity evidence before terminating processes, deleting files, or purging sessions.
  • If targeted or bulk service-ticket requests are confirmed, prioritize the named service accounts for password rotation, privilege review, and downstream logon analysis, then review affected services for anomalous authentication or access tied to the same period.
  • Eradicate only the unauthorized scripts, SPN lists, ticket or hash output, scheduled tasks, and persistence mechanisms uncovered during the investigation, then remediate the delivery path or administrative-control gap that allowed the script to run.
  • After containment, hunt for the same reconstructed script fragments, SPN patterns, and ticket-request evidence across other hosts, and retain PowerShell Script Block Logging plus supporting endpoint or identity telemetry where gaps limited the investigation.

References

Related rules

to-top