Example #1
0
        def do_local_auth(self, messageType, token, proxy):
            if messageType == 1:
                negotiateMessage = ntlm.NTLMAuthNegotiate()
                negotiateMessage.fromString(token)
                ansFlags = 0

                if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_56:
                    ansFlags |= ntlm.NTLMSSP_NEGOTIATE_56
                if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_128:
                    ansFlags |= ntlm.NTLMSSP_NEGOTIATE_128
                if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_KEY_EXCH:
                    ansFlags |= ntlm.NTLMSSP_NEGOTIATE_KEY_EXCH
                if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
                    ansFlags |= ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
                if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
                    ansFlags |= ntlm.NTLMSSP_NEGOTIATE_UNICODE
                if negotiateMessage['flags'] & ntlm.NTLM_NEGOTIATE_OEM:
                    ansFlags |= ntlm.NTLM_NEGOTIATE_OEM

                ansFlags |= ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_NEGOTIATE_TARGET_INFO | \
                            ntlm.NTLMSSP_TARGET_TYPE_SERVER | ntlm.NTLMSSP_NEGOTIATE_NTLM

                challengeMessage = ntlm.NTLMAuthChallenge()
                challengeMessage['flags'] = ansFlags
                challengeMessage['domain_name'] = ""
                challengeMessage['challenge'] = ''.join(random.choice(string.printable) for _ in range(64))
                challengeMessage['TargetInfoFields'] = ntlm.AV_PAIRS()
                challengeMessage['TargetInfoFields_len'] = 0
                challengeMessage['TargetInfoFields_max_len'] = 0
                challengeMessage['TargetInfoFields_offset'] = 40 + 16
                challengeMessage['Version'] = b'\xff' * 8
                challengeMessage['VersionLen'] = 8

                self.do_AUTHHEAD(message=b'NTLM ' + base64.b64encode(challengeMessage.getData()),proxy=proxy)
                return

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

                if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
                    self.authUser = ('%s/%s' % (authenticateMessage['domain_name'].decode('utf-16le'),
                                                authenticateMessage['user_name'].decode('utf-16le'))).upper()
                else:
                    self.authUser = ('%s/%s' % (authenticateMessage['domain_name'].decode('ascii'),
                                                authenticateMessage['user_name'].decode('ascii'))).upper()

                self.target = self.server.config.target.getTarget(identity = self.authUser)

                if self.target is None:
                    LOG.info("HTTPD(%s): Connection from %s@%s controlled, but there are no more targets left!" %
                        (self.server.server_address[1], self.authUser, self.client_address[0]))
                    self.send_not_found()
                    return

                LOG.info("HTTPD(%s): Connection from %s@%s controlled, attacking target %s://%s" % (self.authUser,
                    self.server.server_address[1], self.client_address[0], self.target.scheme, self.target.netloc))

                self.relayToHost = True
                self.do_REDIRECT()
Example #2
0
        def do_ntlm_negotiate(self, token):

            if self.target.scheme.upper() in self.server.config.protocolClients:
                self.client = self.server.config.protocolClients[self.target.scheme.upper()](self.server.config, self.target)
                # If connection failed, return
                if not self.client.initConnection():
                    return False
                self.challengeMessage = self.client.sendNegotiate(token)

                # Remove target NetBIOS field from the NTLMSSP_CHALLENGE
                if self.server.config.remove_target:
                    av_pairs = ntlm.AV_PAIRS(self.challengeMessage['TargetInfoFields'])
                    del av_pairs[ntlm.NTLMSSP_AV_HOSTNAME]
                    self.challengeMessage['TargetInfoFields'] = av_pairs.getData()
                    self.challengeMessage['TargetInfoFields_len'] = len(av_pairs.getData())
                    self.challengeMessage['TargetInfoFields_max_len'] = len(av_pairs.getData())

                # Check for errors
                if self.challengeMessage is False:
                    return False
            else:
                LOG.error('Protocol Client for %s not found!' % self.target.scheme.upper())
                return False

            return True
Example #3
0
    def send_ntlm_type1(self, http_obj, method, path, headers,
                        negotiateMessage):
        auth_headers = headers.copy()
        auth_headers['Content-Length'] = '0'
        auth_headers['Authorization'] = 'NTLM %s' % base64.b64encode(
            negotiateMessage).decode('ascii')
        http_obj.request(method, path, headers=auth_headers)
        res = http_obj.getresponse()
        res.read()

        if res.status != 401:
            raise Exception(
                'Status code returned: %d. '
                'Authentication does not seem required for url %s' %
                (res.status, path))

        if res.getheader('WWW-Authenticate') is None:
            raise Exception('No authentication requested by '
                            'the server for url %s' % path)

        if self.__auth_types == []:
            self.__auth_types = self.parse_www_authenticate(
                res.getheader('WWW-Authenticate'))

        if AUTH_NTLM not in self.__auth_types:
            # NTLM auth not supported for url
            return None, None

        try:
            serverChallengeBase64 = re.search(
                'NTLM ([a-zA-Z0-9+/]+={0,2})',
                res.getheader('WWW-Authenticate')).group(1)
            serverChallenge = base64.b64decode(serverChallengeBase64)
        except (IndexError, KeyError, AttributeError):
            raise Exception(
                'No NTLM challenge returned from server for url %s' % path)

        if not self.__ntlmssp_info:
            challenge = ntlm.NTLMAuthChallenge(serverChallenge)
            self.__ntlmssp_info = ntlm.AV_PAIRS(challenge['TargetInfoFields'])

        # Format: serverChallenge, reserved, ...
        return serverChallenge, None
Example #4
0
def smbComSessionSetupAndX(packet, packetNum, SMBCommand, questions, replies):

    # Test return code is always 0, otherwise leave before doing anything
    if packet['ErrorCode'] != 0:
        if packet['ErrorClass'] != 0x16:
            return False

    print "SMB_COM_SESSION_SETUP_ANDX ",
    try:
        if (packet['Flags1'] & smb.SMB.FLAGS1_REPLY) == 0:
            # Query
            if SMBCommand['WordCount'] == 12:
                # Extended Security
                sessionSetupParameters = smb.SMBSessionSetupAndX_Extended_Parameters(
                    SMBCommand['Parameters'])
                sessionSetupData = smb.SMBSessionSetupAndX_Extended_Data()
                sessionSetupData[
                    'SecurityBlobLength'] = sessionSetupParameters[
                        'SecurityBlobLength']
                sessionSetupData.fromString(SMBCommand['Data'])

                if struct.unpack('B', sessionSetupData['SecurityBlob']
                                 [0])[0] != smb.ASN1_AID:
                    # If there no GSSAPI ID, it must be an AUTH packet
                    blob = smb.SPNEGO_NegTokenResp(
                        sessionSetupData['SecurityBlob'])
                    token = blob['ResponseToken']
                else:
                    # NEGOTIATE packet
                    blob = smb.SPNEGO_NegTokenInit(
                        sessionSetupData['SecurityBlob'])
                    token = blob['MechToken']
                messageType = struct.unpack(
                    '<L', token[len('NTLMSSP\x00'):len('NTLMSSP\x00') + 4])[0]
                if messageType == 0x01:
                    # NEGOTIATE_MESSAGE
                    negotiateMessage = ntlm.NTLMAuthNegotiate()
                    negotiateMessage.fromString(token)
                elif messageType == 0x03:
                    # AUTHENTICATE_MESSAGE, here we deal with authentication
                    authenticateMessage = ntlm.NTLMAuthChallengeResponse()
                    authenticateMessage.fromString(token)

            else:
                # Standard Security
                sessionSetupParameters = smb.SMBSessionSetupAndX_Parameters(
                    SMBCommand['Parameters'])
                sessionSetupData = smb.SMBSessionSetupAndX_Data()
                sessionSetupData['AnsiPwdLength'] = sessionSetupParameters[
                    'AnsiPwdLength']
                sessionSetupData['UnicodePwdLength'] = sessionSetupParameters[
                    'UnicodePwdLength']
                sessionSetupData.fromString(SMBCommand['Data'])

        else:
            # Response
            if SMBCommand['WordCount'] == 4:
                # Extended Security
                sessionResponse = SMBCommand
                sessionParameters = smb.SMBSessionSetupAndX_Extended_Response_Parameters(
                    sessionResponse['Parameters'])
                sessionData = smb.SMBSessionSetupAndX_Extended_Response_Data(
                    flags=packet['Flags2'])
                sessionData['SecurityBlobLength'] = sessionParameters[
                    'SecurityBlobLength']
                sessionData.fromString(sessionResponse['Data'])
                respToken = smb.SPNEGO_NegTokenResp(
                    sessionData['SecurityBlob'])
                if respToken.fields.has_key('ResponseToken'):
                    # Let's parse some data and keep it to ourselves in case it is asked
                    ntlmChallenge = ntlm.NTLMAuthChallenge(
                        respToken['ResponseToken'])
                    if ntlmChallenge['TargetInfoFields_len'] > 0:
                        infoFields = ntlmChallenge['TargetInfoFields']
                        av_pairs = ntlm.AV_PAIRS(
                            ntlmChallenge['TargetInfoFields']
                            [:ntlmChallenge['TargetInfoFields_len']])
                        if av_pairs[ntlm.NTLMSSP_AV_HOSTNAME] is not None:
                            __server_name = av_pairs[
                                ntlm.NTLMSSP_AV_HOSTNAME][1].decode('utf-16le')
                        if av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME] is not None:
                            __server_domain = av_pairs[
                                ntlm.NTLMSSP_AV_DOMAINNAME][1].decode(
                                    'utf-16le')

            else:
                # Standard Security
                sessionResponse = SMBCommand

                sessionParameters = smb.SMBSessionSetupAndXResponse_Parameters(
                    sessionResponse['Parameters'])
                sessionData = smb.SMBSessionSetupAndXResponse_Data(
                    flags=packet['Flags2'], data=sessionResponse['Data'])
    except Exception, e:
        print "ERROR: %s" % e
        print "Command: 0x%x" % packet['Command']
        print "Packet: %d %r" % (packetNum, packet.getData())
        return True
Example #5
0
    def create_channel(self, method, headers):
        if self._rpcProxyUrl.scheme == 'http':
            self.__channels[method] = HTTPConnection(self._rpcProxyUrl.netloc)
        else:
            try:
                uv_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
                self.__channels[method] = HTTPSConnection(
                    self._rpcProxyUrl.netloc, context=uv_context)
            except AttributeError:
                self.__channels[method] = HTTPSConnection(
                    self._rpcProxyUrl.netloc)

        auth = ntlm.getNTLMSSPType1(domain=self.__domain)
        auth_headers = headers.copy()
        auth_headers['Content-Length'] = '0'
        auth_headers['Authorization'] = b'NTLM ' + base64.b64encode(
            auth.getData())

        self.__channels[method].request(method,
                                        self._rpcProxyUrl.path,
                                        headers=auth_headers)

        res = self.__channels[method].getresponse()
        res.read()

        if res.status != 401:
            raise RPCProxyClientException(
                'Status code returned: %d. Authentication does not seem required for url %s'
                % (res.status, self._rpcProxyUrl.path))

        if res.getheader('WWW-Authenticate') is None:
            raise RPCProxyClientException(
                'No authentication requested by the server for url %s' %
                self._rpcProxyUrl.path)

        if 'NTLM' not in res.getheader('WWW-Authenticate'):
            raise RPCProxyClientException(
                'NTLM Auth not offered by URL, offered protocols: %s' %
                res.getheader('WWW-Authenticate'))

        try:
            serverChallengeBase64 = re.search(
                'NTLM ([a-zA-Z0-9+/]+={0,2})',
                res.getheader('WWW-Authenticate')).group(1)
            serverChallenge = base64.b64decode(serverChallengeBase64)
        except (IndexError, KeyError, AttributeError):
            raise RPCProxyClientException(
                'No NTLM challenge returned from server for url %s' %
                self._rpcProxyUrl.path)

        # Default ACL in HKLM\SOFTWARE\Microsoft\Rpc\ValidPorts allows connections only by NetBIOS name of the server.
        # If remoteName is empty we assume the target is the rpcproxy server, and get its NetBIOS name from NTLMSSP.
        #
        # Interestingly, if Administrator renames the server, the ACL remains the original.
        if not self.__ntlmssp_info:
            challenge = ntlm.NTLMAuthChallenge(serverChallenge)
            self.__ntlmssp_info = ntlm.AV_PAIRS(challenge['TargetInfoFields'])

        if not self.__remoteName:
            self.__remoteName = self.__ntlmssp_info[
                ntlm.NTLMSSP_AV_HOSTNAME][1].decode('utf-16le')
            self._stringbinding.set_network_address(self.__remoteName)

        if not self._rpcProxyUrl.query:
            query = self.__remoteName + ':' + str(self.__dstport)
            self._rpcProxyUrl = self._rpcProxyUrl._replace(query=query)

        type3, exportedSessionKey = ntlm.getNTLMSSPType3(
            auth, serverChallenge, self.__username, self.__password,
            self.__domain, self.__lmhash, self.__nthash)

        headers['Authorization'] = b'NTLM ' + base64.b64encode(type3.getData())

        self.__channels[method].request(method,
                                        self._rpcProxyUrl.path + '?' +
                                        self._rpcProxyUrl.query,
                                        headers=headers)

        auth_resp = self.__channels[method].sock.recv(8192)

        if auth_resp != b'HTTP/1.1 100 Continue\r\n\r\n':
            try:
                auth_resp = auth_resp.split(b'\r\n')[0].decode(
                    "utf-8", errors='replace')
                raise RPCProxyClientException(
                    'RPC Proxy authentication failed in %s channel' % method,
                    proxy_error=auth_resp)
            except (IndexError, KeyError, AttributeError):
                raise RPCProxyClientException(
                    'RPC Proxy authentication failed in %s channel' % method)
Example #6
0
    def netlogonSessionKey(self, challenge, authenticateMessageBlob):
        # Here we will use netlogon to get the signing session key
        print "[*] Connecting to %s NETLOGON service" % self.domainIp

        respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
        authenticateMessage = ntlm.NTLMAuthChallengeResponse()
        authenticateMessage.fromString(respToken2['ResponseToken'])
        _, machineAccount = self.machineAccount.split('/')
        domainName = authenticateMessage['domain_name'].decode('utf-16le')

        try:
            av_pairs = authenticateMessage['ntlm'][44:]
            av_pairs = ntlm.AV_PAIRS(av_pairs)

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

        stringBinding = r'ncacn_np:%s[\PIPE\netlogon]' % self.domainIp

        rpctransport = transport.DCERPCTransportFactory(stringBinding)

        if len(self.machineHashes) > 0:
            lmhash, nthash = self.machineHashes.split(':')
        else:
            lmhash = ''
            nthash = ''

        if hasattr(rpctransport, 'set_credentials'):
            # This method exists only for selected protocol sequences.
            rpctransport.set_credentials(machineAccount, '', domainName,
                                         lmhash, nthash)

        dce = rpctransport.get_dce_rpc()
        dce.connect()
        dce.bind(nrpc.MSRPC_UUID_NRPC)
        resp = nrpc.hNetrServerReqChallenge(dce, NULL, serverName + '\x00',
                                            '12345678')

        serverChallenge = resp['ServerChallenge']

        if self.machineHashes == '':
            ntHash = None
        else:
            ntHash = self.machineHashes.split(':')[1].decode('hex')

        sessionKey = nrpc.ComputeSessionKeyStrongKey('', '12345678',
                                                     serverChallenge, ntHash)

        ppp = nrpc.ComputeNetlogonCredential('12345678', sessionKey)

        resp = nrpc.hNetrServerAuthenticate3(
            dce, NULL, machineAccount + '\x00',
            nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel,
            serverName + '\x00', ppp, 0x600FFFFF)

        clientStoredCredential = pack('<Q', unpack('<Q', ppp)[0] + 10)

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

        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'] = 0
        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'] = nrpc.ComputeNetlogonCredential(
            clientStoredCredential, sessionKey)
        authenticator['Timestamp'] = 10

        request['Authenticator'] = authenticator
        request['ReturnAuthenticator']['Credential'] = '\x00' * 8
        request['ReturnAuthenticator']['Timestamp'] = 0
        request['ExtraFlags'] = 0
        #request.dump()
        try:
            resp = dce.request(request)
            #resp.dump()
        except Exception, e:
            #import traceback
            #print traceback.print_exc()
            print "[!] %s " % e
            return e.get_error_code()
Example #7
0
                             f'{args.frontend}/rpc/rpcproxy.dll')
        r.headers['Authorization'] = f'NTLM {ntlmHash}'
        sess = requests.Session()
        if args.proxy:
            proxies = {'https': args.proxy}
        else:
            proxies = {}
        r = sess.send(r.prepare(), verify=False, proxies=proxies)
        if r.status_code != 401:
            raise Exception(f'RPC NTLM Session Auth received {r.status_code}')
        serverChallengeBase64 = re.search(
            'NTLM ([a-zA-Z0-9+/]+={0,2})',
            r.headers['WWW-Authenticate']).group(1)
        serverChallenge = base64.b64decode(serverChallengeBase64)
        challenge = ntlm.NTLMAuthChallenge(serverChallenge)
        hashData = ntlm.AV_PAIRS(challenge['TargetInfoFields'])
        args.backend = str(hashData.fields[3][1], 'utf-16')
        print(f'Backend: {args.backend}')

    p = Proxy(args.frontend, args.backend, proxy=args.proxy)

    if args.email is not None:
        url = '/autodiscover/autodiscover.xml'
        r = requests.Request('POST', url)
        r.headers['Content-Type'] = 'text/xml'
        r.data = f'<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"><Request><EMailAddress>{args.email}</EMailAddress><AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema></Request></Autodiscover> '
        r = p.send(r)
        if r.status_code != 200:
            raise Exception(f'Unexpected autodiscover status {r.status_code}')

        print(r.text)  # Jine added