Skip to content

Commit 6778455

Browse files
committed
Add target_name for KerberosSSP
1 parent f856d30 commit 6778455

File tree

10 files changed

+45
-19
lines changed

10 files changed

+45
-19
lines changed

doc/scapy/layers/smb.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ You might be wondering if you can pass the ``HashNT`` of the password of the use
7676

7777
.. code:: python
7878
79-
>>> smbclient("server1.domain.local", ssp=KerberosSSP(SPN="cifs/server1", UPN="Administrator@domain.local", PASSWORD="password"))
79+
>>> smbclient("server1.domain.local", ssp=KerberosSSP(UPN="Administrator@domain.local", PASSWORD="password"))
8080
8181
**smbclient using a** :class:`~scapy.layers.ntlm.KerberosSSP` **created by** `Ticketer++ <kerberos.html#ticketer>`_:
8282

@@ -155,7 +155,6 @@ Let's write a script that connects to a share and list the files in the root fol
155155
KerberosSSP(
156156
UPN="Administrator@domain.local",
157157
PASSWORD=password,
158-
SPN="cifs/server1",
159158
)
160159
])
161160
# Connect to the server

scapy/layers/gssapi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ def GSS_Init_sec_context(
455455
self,
456456
Context: CONTEXT,
457457
token=None,
458+
target_name: Optional[str] = None,
458459
req_flags: Optional[GSS_C_FLAGS] = None,
459460
chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,
460461
):

scapy/layers/http.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,7 @@ def request(
942942
self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(
943943
self.sspcontext,
944944
ssp_blob,
945+
target_name="http/" + host,
945946
req_flags=0,
946947
chan_bindings=self.chan_bindings,
947948
)

scapy/layers/kerberos.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4014,7 +4014,8 @@ class KerberosSSP(SSP):
40144014
40154015
:param ST: the service ticket to use for access.
40164016
If not provided, will be retrieved
4017-
:param SPN: the SPN of the service to use
4017+
:param SPN: the SPN of the service to use. If not provided, will use the
4018+
target_name provided in the GSS_Init_sec_context
40184019
:param UPN: The client UPN
40194020
:param DC_IP: (optional) is ST+KEY are not provided, will need to contact
40204021
the KDC at this IP. If not provided, will perform dc locator.
@@ -4512,6 +4513,7 @@ def GSS_Init_sec_context(
45124513
self,
45134514
Context: CONTEXT,
45144515
token=None,
4516+
target_name: Optional[str] = None,
45154517
req_flags: Optional[GSS_C_FLAGS] = None,
45164518
chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,
45174519
):
@@ -4542,8 +4544,8 @@ def GSS_Init_sec_context(
45424544
# Do we have a ST?
45434545
if self.ST is None:
45444546
# Client sends an AP-req
4545-
if not self.SPN:
4546-
raise ValueError("Missing SPN attribute")
4547+
if not self.SPN and not target_name:
4548+
raise ValueError("Missing SPN/target_name attribute")
45474549
additional_tickets = []
45484550
if self.U2U:
45494551
try:
@@ -4565,7 +4567,7 @@ def GSS_Init_sec_context(
45654567
# Use TGT
45664568
res = krb_tgs_req(
45674569
upn=self.UPN,
4568-
spn=self.SPN,
4570+
spn=self.SPN or target_name,
45694571
ip=self.DC_IP,
45704572
sessionkey=self.KEY,
45714573
ticket=self.TGT,
@@ -4577,7 +4579,7 @@ def GSS_Init_sec_context(
45774579
# Ask for TGT then ST
45784580
res = krb_as_and_tgs(
45794581
upn=self.UPN,
4580-
spn=self.SPN,
4582+
spn=self.SPN or target_name,
45814583
ip=self.DC_IP,
45824584
key=self.KEY,
45834585
password=self.PASSWORD,

scapy/layers/ldap.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,6 +1800,7 @@ def __init__(
18001800
verb=True,
18011801
):
18021802
self.sock = None
1803+
self.host = None
18031804
self.verb = verb
18041805
self.ssl = False
18051806
self.sslcontext = None
@@ -1815,7 +1816,7 @@ def __init__(
18151816

18161817
def connect(
18171818
self,
1818-
ip,
1819+
host,
18191820
port=None,
18201821
use_ssl=False,
18211822
sslcontext=None,
@@ -1826,7 +1827,7 @@ def connect(
18261827
"""
18271828
Initiate a connection
18281829
1829-
:param ip: the IP or hostname to connect to.
1830+
:param host: the IP or hostname to connect to.
18301831
:param port: the port to connect to. (Default: 389 or 636)
18311832
18321833
:param use_ssl: whether to use LDAPS or not. (Default: False)
@@ -1844,17 +1845,18 @@ def connect(
18441845
port = 389
18451846
sock = socket.socket()
18461847
self.timeout = timeout
1848+
self.host = host
18471849
sock.settimeout(timeout)
18481850
if self.verb:
18491851
print(
18501852
"\u2503 Connecting to %s on port %s%s..."
18511853
% (
1852-
ip,
1854+
host,
18531855
port,
18541856
" with SSL" if self.ssl else "",
18551857
)
18561858
)
1857-
sock.connect((ip, port))
1859+
sock.connect((host, port))
18581860
if self.verb:
18591861
print(
18601862
conf.color_theme.green(
@@ -1872,7 +1874,7 @@ def connect(
18721874
context = ssl.create_default_context()
18731875
else:
18741876
context = self.sslcontext
1875-
sock = context.wrap_socket(sock, server_hostname=sni or ip)
1877+
sock = context.wrap_socket(sock, server_hostname=sni or host)
18761878
# Wrap the socket in a Scapy socket
18771879
if self.ssl:
18781880
self.sock = SSLStreamSocket(sock, LDAP)
@@ -2042,6 +2044,7 @@ def bind(
20422044
# 2. First exchange: Negotiate
20432045
self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(
20442046
self.sspcontext,
2047+
target_name="ldap/" + self.host,
20452048
req_flags=(
20462049
GSS_C_FLAGS.GSS_C_REPLAY_FLAG
20472050
| GSS_C_FLAGS.GSS_C_SEQUENCE_FLAG
@@ -2068,6 +2071,7 @@ def bind(
20682071
self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(
20692072
self.sspcontext,
20702073
GSSAPI_BLOB(val),
2074+
target_name="ldap/" + self.host,
20712075
chan_bindings=self.chan_bindings,
20722076
)
20732077
resp = self.sr1(
@@ -2090,6 +2094,7 @@ def bind(
20902094
# GSSAPI or SPNEGO
20912095
self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(
20922096
self.sspcontext,
2097+
target_name="ldap/" + self.host,
20932098
req_flags=(
20942099
# Required flags for GSSAPI: RFC4752 sect 3.1
20952100
GSS_C_FLAGS.GSS_C_REPLAY_FLAG
@@ -2122,6 +2127,7 @@ def bind(
21222127
self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(
21232128
self.sspcontext,
21242129
GSSAPI_BLOB(val),
2130+
target_name="ldap/" + self.host,
21252131
chan_bindings=self.chan_bindings,
21262132
)
21272133
else:

scapy/layers/msrpce/msnrpc.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,12 @@ def GSS_VerifyMICEx(self, Context, msgs, signature):
475475
self._unsecure(Context, msgs, signature, False)
476476

477477
def GSS_Init_sec_context(
478-
self, Context, token=None, req_flags: Optional[GSS_C_FLAGS] = None
478+
self,
479+
Context: CONTEXT,
480+
token=None,
481+
target_name: Optional[str] = None,
482+
req_flags: Optional[GSS_C_FLAGS] = None,
483+
chan_bindings: bytes = GSS_C_NO_CHANNEL_BINDINGS,
479484
):
480485
if Context is None:
481486
Context = self.CONTEXT(True, req_flags=req_flags, AES=self.AES)

scapy/layers/msrpce/rpcclient.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def __init__(self, transport, ndr64=False, ndrendian="little", verb=True, **kwar
7676
self.ndr64 = ndr64
7777
self.ndrendian = ndrendian
7878
self.verb = verb
79+
self.host = None
7980
self.auth_level = kwargs.pop("auth_level", DCE_C_AUTHN_LEVEL.NONE)
8081
self.auth_context_id = kwargs.pop("auth_context_id", 0)
8182
self.ssp = kwargs.pop("ssp", None) # type: SSP
@@ -100,7 +101,7 @@ def from_smblink(cls, smbcli, smb_kwargs={}, **kwargs):
100101
)
101102
return client
102103

103-
def connect(self, ip, port=None, timeout=5, smb_kwargs={}):
104+
def connect(self, host, port=None, timeout=5, smb_kwargs={}):
104105
"""
105106
Initiate a connection
106107
"""
@@ -113,14 +114,15 @@ def connect(self, ip, port=None, timeout=5, smb_kwargs={}):
113114
raise ValueError(
114115
"Can't guess the port for transport: %s" % self.transport
115116
)
117+
self.host = host
116118
sock = socket.socket()
117119
sock.settimeout(timeout)
118120
if self.verb:
119121
print(
120122
"\u2503 Connecting to %s on port %s via %s..."
121-
% (ip, port, repr(self.transport))
123+
% (host, port, repr(self.transport))
122124
)
123-
sock.connect((ip, port))
125+
sock.connect((host, port))
124126
if self.verb:
125127
print(
126128
conf.color_theme.green(
@@ -313,6 +315,7 @@ def _bind(self, interface, reqcls, respcls):
313315
else 0
314316
)
315317
),
318+
target_name="host/" + self.host,
316319
)
317320
if status not in [GSS_S_CONTINUE_NEEDED, GSS_S_COMPLETE]:
318321
# Authentication failed.
@@ -349,6 +352,7 @@ def _bind(self, interface, reqcls, respcls):
349352
self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(
350353
self.sspcontext,
351354
token=resp.auth_verifier.auth_value,
355+
target_name="host/" + self.host,
352356
)
353357
if status in [GSS_S_CONTINUE_NEEDED, GSS_S_COMPLETE]:
354358
# Authentication should continue, in two ways:
@@ -390,6 +394,7 @@ def _bind(self, interface, reqcls, respcls):
390394
self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(
391395
self.sspcontext,
392396
token=resp.auth_verifier.auth_value,
397+
target_name="host/" + self.host,
393398
)
394399
# Check context acceptance
395400
if (

scapy/layers/ntlm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,7 @@ def GSS_Init_sec_context(
13881388
self,
13891389
Context: CONTEXT,
13901390
token=None,
1391+
target_name: Optional[str] = None,
13911392
req_flags: Optional[GSS_C_FLAGS] = None,
13921393
chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,
13931394
):

scapy/layers/smbclient.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def __init__(self, sock, ssp=None, *args, **kwargs):
136136
self.REQUIRE_ENCRYPTION = kwargs.pop("REQUIRE_ENCRYPTION", False)
137137
self.RETRY = kwargs.pop("RETRY", 0) # optionally: retry n times session setup
138138
self.SMB2 = kwargs.pop("SMB2", False) # optionally: start directly in SMB2
139-
self.SERVER_NAME = kwargs.pop("SERVER_NAME", "")
139+
self.HOST = kwargs.pop("HOST", "")
140140
# Store supported dialects
141141
if "DIALECTS" in kwargs:
142142
self.DIALECTS = kwargs.pop("DIALECTS")
@@ -351,7 +351,7 @@ def on_negotiate_smb2(self):
351351
# TODO support compression and RDMA
352352
SMB2_Negotiate_Context()
353353
/ SMB2_Netname_Negotiate_Context_ID(
354-
NetName=self.SERVER_NAME,
354+
NetName=self.HOST,
355355
),
356356
SMB2_Negotiate_Context()
357357
/ SMB2_Signing_Capabilities(
@@ -448,6 +448,7 @@ def NEGOTIATED(self, ssp_blob=None):
448448
ssp_tuple = self.session.ssp.GSS_Init_sec_context(
449449
self.session.sspcontext,
450450
token=ssp_blob,
451+
target_name="cifs/" + self.HOST if self.HOST else None,
451452
req_flags=(
452453
GSS_C_FLAGS.GSS_C_MUTUAL_FLAG
453454
| (GSS_C_FLAGS.GSS_C_INTEG_FLAG if self.session.SigningRequired else 0)
@@ -608,6 +609,7 @@ def AUTHENTICATED(self, ssp_blob=None):
608609
self.session.sspcontext, _, status = self.session.ssp.GSS_Init_sec_context(
609610
self.session.sspcontext,
610611
token=ssp_blob,
612+
target_name="cifs/" + self.HOST if self.HOST else None,
611613
)
612614
if status != GSS_S_COMPLETE:
613615
raise ValueError("Internal error: the SSP completed with an error.")
@@ -1175,7 +1177,7 @@ def __init__(
11751177
self.extra_create_options = []
11761178
# Wrap with the automaton
11771179
self.timeout = timeout
1178-
kwargs.setdefault("SERVER_NAME", target)
1180+
kwargs.setdefault("HOST", target)
11791181
self.sock = SMB_Client.from_tcpsock(
11801182
sock,
11811183
ssp=ssp,

scapy/layers/spnego.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,7 @@ def _common_spnego_handler(
838838
Context,
839839
IsClient,
840840
token=None,
841+
target_name: Optional[str] = None,
841842
req_flags=None,
842843
chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,
843844
):
@@ -906,6 +907,7 @@ def _common_spnego_handler(
906907
) = Context.ssp.GSS_Init_sec_context(
907908
Context.sub_context,
908909
token=token,
910+
target_name=target_name,
909911
req_flags=Context.req_flags,
910912
chan_bindings=chan_bindings,
911913
)
@@ -1066,13 +1068,15 @@ def GSS_Init_sec_context(
10661068
self,
10671069
Context: CONTEXT,
10681070
token=None,
1071+
target_name: Optional[str] = None,
10691072
req_flags: Optional[GSS_C_FLAGS] = None,
10701073
chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,
10711074
):
10721075
return self._common_spnego_handler(
10731076
Context,
10741077
True,
10751078
token=token,
1079+
target_name=target_name,
10761080
req_flags=req_flags,
10771081
chan_bindings=chan_bindings,
10781082
)

0 commit comments

Comments
 (0)