Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
10 changes: 7 additions & 3 deletions nxc/protocols/smb.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="",
kerb_pass = ""
self.username = self.args.delegate
serverName = Principal(self.args.delegate_spn if self.args.delegate_spn else f"cifs/{self.remoteName}", type=constants.PrincipalNameType.NT_SRV_INST.value)
tgs, sk = kerberos_login_with_S4U(domain, self.hostname, username, password, nthash, lmhash, aesKey, kdcHost, self.args.delegate, serverName, useCache, no_s4u2proxy=self.args.no_s4u2proxy)
tgs, sk = kerberos_login_with_S4U(domain, self.hostname, username, password, nthash, lmhash, aesKey, kdcHost, self.args.delegate, serverName, useCache, no_s4u2proxy=self.args.no_s4u2proxy, u2u=self.args.u2u)
self.logger.debug(f"TGS obtained for {self.args.delegate} for {serverName}")

spn = f"cifs/{self.remoteName}"
Expand All @@ -385,10 +385,14 @@ def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="",

used_ccache = " from ccache" if useCache else f":{process_secret(kerb_pass)}"
if self.args.delegate:
used_ccache = f" through S4U with {username}"
u2u_str = "+U2U" if self.args.u2u else ""
auth_user = username if username else "ccache"
used_ccache = f" through S4U{u2u_str} with {auth_user}"

if self.args.delegate_spn:
used_ccache = f" through S4U with {username} (w/ SPN {self.args.delegate_spn})"
u2u_str = "+U2U" if self.args.u2u else ""
auth_user = username if username else "ccache"
used_ccache = f" through S4U{u2u_str} with {auth_user} (w/ SPN {self.args.delegate_spn})"

out = f"{self.domain}\\{self.username}{used_ccache} {self.mark_pwned()}"
self.logger.success(out)
Expand Down
27 changes: 18 additions & 9 deletions nxc/protocols/smb/kerberos.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@
from nxc.logger import nxc_logger


def kerberos_login_with_S4U(domain, hostname, username, password, nthash, lmhash, aesKey, kdcHost, impersonate, spn, use_cache, no_s4u2proxy=False):
def kerberos_login_with_S4U(domain, hostname, username, password, nthash, lmhash, aesKey, kdcHost, impersonate, spn, use_cache, no_s4u2proxy=False, u2u=False):
my_tgt = None
if use_cache:
domain, _, tgt, _ = CCache.parseFile(domain, username, f"cifs/{hostname}")
if my_tgt is None:
raise
my_tgt = tgt["KDC_REP"]
cipher = tgt["cipher"]
session_key = tgt["sessionKey"]
domain, ccache_user, tgt, _ = CCache.parseFile(domain)
if tgt is not None:
my_tgt = decoder.decode(tgt["KDC_REP"], asn1Spec=AS_REP())[0]
cipher = tgt["cipher"]
session_key = tgt["sessionKey"]
if not username and ccache_user:
username = ccache_user
if my_tgt is None:
principal = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
nxc_logger.debug("Getting TGT for user")
Expand Down Expand Up @@ -117,9 +118,14 @@ def kerberos_login_with_S4U(domain, hostname, username, password, nthash, lmhash
opts.append(constants.KDCOptions.renewable.value)
opts.append(constants.KDCOptions.canonicalize.value)

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

req_body["kdc-options"] = constants.encodeFlags(opts)

server_name = Principal(username, type=constants.PrincipalNameType.NT_UNKNOWN.value)
# For U2U, include the domain in the serverName
server_name = Principal(username, domain.upper(), type=constants.PrincipalNameType.NT_UNKNOWN.value) if u2u else Principal(username, type=constants.PrincipalNameType.NT_UNKNOWN.value)

seq_set(req_body, "sname", server_name.components_to_asn1)
req_body["realm"] = str(decoded_tgt["crealm"])
Expand All @@ -130,7 +136,10 @@ def kerberos_login_with_S4U(domain, hostname, username, password, nthash, lmhash
req_body["nonce"] = random.getrandbits(31)
seq_set_iter(req_body, "etype", (int(cipher.enctype), int(constants.EncryptionTypes.rc4_hmac.value)))

nxc_logger.info("Requesting S4U2self")
if u2u:
seq_set_iter(req_body, "additional-tickets", (ticket.to_asn1(TicketAsn1()),))

nxc_logger.info(f"Requesting S4U2self{'+U2U' if u2u else ''}")
message = encoder.encode(tgs_req)

r = sendReceive(message, domain, kdcHost)
Expand Down
2 changes: 2 additions & 0 deletions nxc/protocols/smb/proto_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def proto_args(parser, parents):
delegate_spn_arg = smb_parser.add_argument("--delegate-spn", action=get_conditional_action(_StoreAction), make_required=[], help="SPN to use for S4U2Proxy, if not specified the SPN used will be cifs/<target>", type=str)
generate_st = smb_parser.add_argument("--generate-st", type=str, dest="generate_st", action=get_conditional_action(_StoreAction), make_required=[], help="Store the S4U Service Ticket in the specified file")
self_delegate_arg = smb_parser.add_argument("--self", dest="no_s4u2proxy", action=get_conditional_action(_StoreTrueAction), make_required=[], help="Only do S4U2Self, no S4U2Proxy (use with delegate)")
u2u_arg = smb_parser.add_argument("--u2u", action=get_conditional_action(_StoreTrueAction), make_required=[], help="Use User-to-User (U2U) authentication with S4U2Self")

dgroup = smb_parser.add_mutually_exclusive_group()
dgroup.add_argument("-d", "--domain", metavar="DOMAIN", dest="domain", type=str, help="domain to authenticate to")
Expand All @@ -29,6 +30,7 @@ def proto_args(parser, parents):
self_delegate_arg.make_required = [delegate_arg]
generate_st.make_required = [delegate_arg]
delegate_spn_arg.make_required = [delegate_arg]
u2u_arg.make_required = [delegate_arg]

cred_gathering_group = smb_parser.add_argument_group("Credential Gathering")
cred_gathering_group.add_argument("--sam", choices={"regdump", "secdump"}, nargs="?", const="regdump", help="dump SAM hashes from target systems")
Expand Down