Example #1
0
    def getData(self):
        credentials = pack('B', 0xa1)
        credentials += asn1encode(
            pack('B', ASN1_OCTET_STRING) + asn1encode(self['credentials']))

        ans = pack('B', ASN1_SEQUENCE)
        ans += asn1encode(
            pack('B', 0xa0) + asn1encode(
                pack('B', 0x02) + asn1encode(pack('B', self['credType']))) +
            credentials)
        return ans
Example #2
0
   def getData(self):
     # Let's pack the credentials field
     credentials =  pack('B',0xa1) 
     credentials += asn1encode(pack('B',ASN1_OCTET_STRING) +
                    asn1encode(self['credentials']))

     ans = pack('B',ASN1_SEQUENCE) 
     ans += asn1encode( pack('B', 0xa0) +
            asn1encode( pack('B', 0x02) + 
            asn1encode( pack('B', self['credType']))) +
            credentials)
     return ans
Example #3
0
    def getData(self):
        # Let's pack the credentials field
        credentials = pack('B',0xa1)
        credentials += asn1encode(pack('B',ASN1_OCTET_STRING) +
                                    asn1encode(self['credentials']))

        asn = pack('B',ASN1_SEQUENCE)
        asn += asn1encode(
            pack('B', 0xa0) +
            asn1encode(
                pack('B', 0x02) +
                asn1encode(
                    pack('B', self['credType']))) + credentials)

        return asn
Example #4
0
def getPubKey():

    cert = open("./server.crt",'r')
    crt = crypto.load_certificate(crypto.FILETYPE_PEM,cert.read())
    pubkeyObj = crt.get_pubkey()
    pubkeyStr = crypto.dump_privatekey(crypto.FILETYPE_ASN1,pubkeyObj)
    pubkeyStr = pubkeyStr[7:]
    pubkeyStr = b'\x30' + asn1encode(pubkeyStr)

    return pubkeyStr
Example #5
0
 def getData(self):
     ans = pack('B', ASN1_SEQUENCE)
     ans += asn1encode( pack('B', 0xa0) +
            asn1encode( pack('B', ASN1_OCTET_STRING) + 
            asn1encode( self['domainName'].encode('utf-16le'))) +
            pack('B', 0xa1) + 
            asn1encode( pack('B', ASN1_OCTET_STRING) + 
            asn1encode( self['userName'].encode('utf-16le'))) +
            pack('B', 0xa2) + 
            asn1encode( pack('B', ASN1_OCTET_STRING) + 
            asn1encode( self['password'].encode('utf-16le'))) )
     return ans 
Example #6
0
 def getData(self):
     ans = pack('B', ASN1_SEQUENCE)
     ans += asn1encode( pack('B', 0xa0) +
            asn1encode( pack('B', ASN1_OCTET_STRING) + 
            asn1encode( self['domainName'].encode('utf-16le'))) +
            pack('B', 0xa1) + 
            asn1encode( pack('B', ASN1_OCTET_STRING) + 
            asn1encode( self['userName'].encode('utf-16le'))) +
            pack('B', 0xa2) + 
            asn1encode( pack('B', ASN1_OCTET_STRING) + 
            asn1encode( self['password'].encode('utf-16le'))) )
     return ans 
Example #7
0
    def check_rdp(host, username, password, domain, hashes=None):

        if hashes is not None:
            lmhash, nthash = hashes.split(':')
            lmhash = a2b_hex(lmhash)
            nthash = a2b_hex(nthash)

        else:
            lmhash = ''
            nthash = ''

        tpkt = TPKT()
        tpdu = TPDU()
        rdp_neg = RDP_NEG_REQ()
        rdp_neg['Type'] = TYPE_RDP_NEG_REQ
        rdp_neg['requestedProtocols'] = PROTOCOL_HYBRID | PROTOCOL_SSL
        tpdu['VariablePart'] = rdp_neg.getData()
        tpdu['Code'] = TDPU_CONNECTION_REQUEST
        tpkt['TPDU'] = tpdu.getData()

        s = socket.socket()
        s.connect((host, 3389))  #port default
        s.sendall(tpkt.getData())
        pkt = s.recv(8192)
        tpkt.fromString(pkt)
        tpdu.fromString(tpkt['TPDU'])
        cr_tpdu = CR_TPDU(tpdu['VariablePart'])
        if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE:
            rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart'])
            rdp_failure.dump()
            logging.error(
                "Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials"
            )
            return
        else:
            rdp_neg.fromString(tpdu['VariablePart'])

        # Since we were accepted to talk PROTOCOL_HYBRID, below is its implementation

        # 1. The CredSSP client and CredSSP server first complete the TLS handshake,
        # as specified in [RFC2246]. After the handshake is complete, all subsequent
        # CredSSP Protocol messages are encrypted by the TLS channel.
        # The CredSSP Protocol does not extend the TLS wire protocol. As part of the TLS
        # handshake, the CredSSP server does not request the client's X.509 certificate
        # (thus far, the client is anonymous). Also, the CredSSP Protocol does not require
        # the client to have a commonly trusted certification authority root with the
        # CredSSP server. Thus, the CredSSP server MAY use, for example,
        # a self-signed X.509 certificate.

        # Switching to TLS now
        ctx = SSL.Context(SSL.TLSv1_2_METHOD)
        ctx.set_cipher_list(b'RC4,AES')
        tls = SSL.Connection(ctx, s)
        tls.set_connect_state()
        tls.do_handshake()

        # If you want to use Python internal ssl, uncomment this and comment
        # the previous lines
        #tls = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers='RC4')

        # 2. Over the encrypted TLS channel, the SPNEGO handshake between the client
        # and server completes mutual authentication and establishes an encryption key
        # that is used by the SPNEGO confidentiality services, as specified in [RFC4178].
        # All SPNEGO tokens as well as the underlying encryption algorithms are opaque to
        # the calling application (the CredSSP client and CredSSP server).
        # The wire protocol for SPNEGO is specified in [MS-SPNG].
        # The SPNEGO tokens exchanged between the client and the server are encapsulated
        # in the negoTokens field of the TSRequest structure. Both the client and the
        # server use this structure as many times as necessary to complete the SPNEGO
        # exchange.<9>
        #
        # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted
        # from the TSRequest structure by the client and server; the OPTIONAL pubKeyAuth
        # field is omitted by the client unless the client is sending the last SPNEGO token.
        # If the client is sending the last SPNEGO token, the TSRequest structure MUST have
        # both the negoToken and the pubKeyAuth fields filled in.

        # NTLMSSP stuff
        auth = ntlm.getNTLMSSPType1('', '', True, use_ntlmv2=True)

        ts_request = TSRequest()
        ts_request['NegoData'] = auth.getData()

        tls.send(ts_request.getData())
        buff = tls.recv(4096)
        ts_request.fromString(buff)

        # 3. The client encrypts the public key it received from the server (contained
        # in the X.509 certificate) in the TLS handshake from step 1, by using the
        # confidentiality support of SPNEGO. The public key that is encrypted is the
        # ASN.1-encoded SubjectPublicKey sub-field of SubjectPublicKeyInfo from the X.509
        # certificate, as specified in [RFC3280] section 4.1. The encrypted key is
        # encapsulated in the pubKeyAuth field of the TSRequest structure and is sent over
        # the TLS channel to the server.
        #
        # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted
        # from the TSRequest structure; the client MUST send its last SPNEGO token to the
        # server in the negoTokens field (see step 2) along with the encrypted public key
        # in the pubKeyAuth field.

        # Last SPNEGO token calculation
        #ntlmChallenge = ntlm.NTLMAuthChallenge(ts_request['NegoData'])
        type3, exportedSessionKey = ntlm.getNTLMSSPType3(
            auth,
            ts_request['NegoData'],
            username,
            password,
            domain,
            lmhash,
            nthash,
            use_ntlmv2=True)

        # Get server public key
        server_cert = tls.get_peer_certificate()
        pkey = server_cert.get_pubkey()
        dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey)

        # Fix up due to PyOpenSSL lack for exporting public keys
        dump = dump[7:]
        dump = b'\x30' + asn1encode(dump)

        cipher = SPNEGOCipher(type3['flags'], exportedSessionKey)
        signature, cripted_key = cipher.encrypt(dump)
        ts_request['NegoData'] = type3.getData()
        ts_request['pubKeyAuth'] = signature.getData() + cripted_key

        try:
            # Sending the Type 3 NTLM blob
            tls.send(ts_request.getData())
            # The other end is waiting for the pubKeyAuth field, but looks like it's
            # not needed to check whether authentication worked.
            # If auth is unsuccessful, it throws an exception with the previous send().
            # If auth is successful, the server waits for the pubKeyAuth and doesn't answer
            # anything. So, I'm sending garbage so the server returns an error.
            # Luckily, it's a different error so we can determine whether or not auth worked ;)
            buff = tls.recv(1024)
        except Exception as err:
            if str(err).find("denied") > 0:
                # logging.error("Access Denied")
                sys.stdout.write('\r[-] [%s:%s] Access Denied            ' %
                                 (username, password))
            else:
                logging.error(err)
                time.sleep(5)
            return

        # 4. After the server receives the public key in step 3, it first verifies that
        # it has the same public key that it used as part of the TLS handshake in step 1.
        # The server then adds 1 to the first byte representing the public key (the ASN.1
        # structure corresponding to the SubjectPublicKey field, as described in step 3)
        # and encrypts the binary result by using the SPNEGO encryption services.
        # Due to the addition of 1 to the binary data, and encryption of the data as a binary
        # structure, the resulting value may not be valid ASN.1-encoded values.
        # The encrypted binary data is encapsulated in the pubKeyAuth field of the TSRequest
        # structure and is sent over the encrypted TLS channel to the client.
        # The addition of 1 to the first byte of the public key is performed so that the
        # client-generated pubKeyAuth message cannot be replayed back to the client by an
        # attacker.
        #
        # Note During this phase of the protocol, the OPTIONAL authInfo and negoTokens
        # fields are omitted from the TSRequest structure.

        ts_request = TSRequest(buff)

        # Now we're decrypting the certificate + 1 sent by the server. Not worth checking ;)
        signature, plain_text = cipher.decrypt(ts_request['pubKeyAuth'][16:])

        # 5. After the client successfully verifies server authenticity by performing a
        # binary comparison of the data from step 4 to that of the data representing
        # the public key from the server's X.509 certificate (as specified in [RFC3280],
        # section 4.1), it encrypts the user's credentials (either password or smart card
        # PIN) by using the SPNEGO encryption services. The resulting value is
        # encapsulated in the authInfo field of the TSRequest structure and sent over
        # the encrypted TLS channel to the server.
        # The TSCredentials structure within the authInfo field of the TSRequest
        # structure MAY contain either a TSPasswordCreds or a TSSmartCardCreds structure,
        # but MUST NOT contain both.
        #
        # Note During this phase of the protocol, the OPTIONAL pubKeyAuth and negoTokens
        # fields are omitted from the TSRequest structure.
        tsp = TSPasswordCreds()
        tsp['domainName'] = domain
        tsp['userName'] = username
        tsp['password'] = password
        tsc = TSCredentials()
        tsc['credType'] = 1  # TSPasswordCreds
        tsc['credentials'] = tsp.getData()

        signature, cripted_creds = cipher.encrypt(tsc.getData())
        ts_request = TSRequest()
        ts_request['authInfo'] = signature.getData() + cripted_creds
        tls.send(ts_request.getData())
        tls.close()
        # logging.info("\rAccess Granted\n")
        sys.stdout.write('\r[+] [%s:%s] Access Granted\n' %
                         (username, password))
        return True
Example #8
0
    def check_rdp(host, username, password, domain, hashes=None):
        if hashes is not None:
            lmhash, nthash = hashes.split(':')
            lmhash = a2b_hex(lmhash)
            nthash = a2b_hex(nthash)
        else:
            lmhash = ''
            nthash = ''

        tpkt = TPKT()
        tpdu = TPDU()
        rdp_neg = RDP_NEG_REQ()
        rdp_neg['Type'] = TYPE_RDP_NEG_REQ
        rdp_neg['requestedProtocols'] = PROTOCOL_HYBRID | PROTOCOL_SSL
        tpdu['VariablePart'] = rdp_neg.getData()
        tpdu['Code'] = TDPU_CONNECTION_REQUEST
        tpkt['TPDU'] = tpdu.getData()

        s = socket.socket()
        s.connect((host, 3389))  #port default
        s.sendall(tpkt.getData())
        pkt = s.recv(8192)
        tpkt.fromString(pkt)
        tpdu.fromString(tpkt['TPDU'])
        cr_tpdu = CR_TPDU(tpdu['VariablePart'])

        if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE:
            rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart'])
            rdp_failure.dump()
            logging.error(
                "Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials"
            )
            return
        else:
            rdp_neg.fromString(tpdu['VariablePart'])

        ctx = SSL.Context(SSL.TLSv1_2_METHOD)
        ctx.set_cipher_list(b'RC4,AES')
        tls = SSL.Connection(ctx, s)
        tls.set_connect_state()
        tls.do_handshake()

        auth = ntlm.getNTLMSSPType1('', '', True, use_ntlmv2=True)
        ts_request = TSRequest()
        ts_request['NegoData'] = auth.getData()
        tls.send(ts_request.getData())
        buff = tls.recv(4096)
        ts_request.fromString(buff)

        type3, exportedSessionKey = ntlm.getNTLMSSPType3(
            auth,
            ts_request['NegoData'],
            username,
            password,
            domain,
            lmhash,
            nthash,
            use_ntlmv2=True)
        # Get server public key
        server_cert = tls.get_peer_certificate()
        pkey = server_cert.get_pubkey()
        dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey)
        # Fix up due to PyOpenSSL lack for exporting public keys
        dump = dump[7:]
        dump = b'\x30' + asn1encode(dump)
        cipher = SPNEGOCipher(type3['flags'], exportedSessionKey)
        signature, cripted_key = cipher.encrypt(dump)
        ts_request['NegoData'] = type3.getData()
        ts_request['pubKeyAuth'] = signature.getData() + cripted_key
        try:
            # Sending the Type 3 NTLM blob
            tls.send(ts_request.getData())
            buff = tls.recv(1024)
        except Exception as err:
            if str(err).find("denied") > 0:
                # logging.error("Access Denied")
                sys.stdout.write('\r[-] [%s:%s:%s] Access Denied            ' %
                                 (host, username, password))
            else:
                logging.error(err)
                time.sleep(5)
            return

        ts_request = TSRequest(buff)
        signature, plain_text = cipher.decrypt(ts_request['pubKeyAuth'][16:])
        tsp = TSPasswordCreds()
        tsp['domainName'] = domain
        tsp['userName'] = username
        tsp['password'] = password
        tsc = TSCredentials()
        tsc['credType'] = 1  # TSPasswordCreds
        tsc['credentials'] = tsp.getData()
        signature, cripted_creds = cipher.encrypt(tsc.getData())
        ts_request = TSRequest()
        ts_request['authInfo'] = signature.getData() + cripted_creds
        tls.send(ts_request.getData())
        tls.close()
        sys.stdout.write(
            f"\r{colored('[+]', 'green')} {colored('Host:','blue')}{host},{colored('Username:'******'blue')}{username},{colored('Password:'******'blue')}{password},{colored('Domain:','blue')}{domain} [{colored('SUCESS', 'green')}] \n"
        )
        return True
Example #9
0
    #chkField['Flags'] = GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE
    authenticator['cksum']['checksum'] = chkField.getData()
    authenticator['seq-number'] = 0
    encodedAuthenticator = encoder.encode(authenticator)

    # Key Usage 11
    # AP-REQ Authenticator (includes application authenticator
    # subkey), encrypted with the application session key
    # (Section 5.5.1)
    encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None)

    apReq['authenticator'] = noValue
    apReq['authenticator']['etype'] = cipher.enctype
    apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator

    blob['MechToken'] = struct.pack('B', ASN1_AID) + asn1encode( struct.pack('B', ASN1_OID) + asn1encode(
            TypesMech['KRB5 - Kerberos 5'] ) + KRB5_AP_REQ + encoder.encode(apReq))

    return cipher, sessionKey, blob.getData()

class KerberosError(SessionError):
    """
    This is the exception every client should catch regardless of the underlying
    SMB version used. We'll take care of that. NETBIOS exceptions are NOT included,
    since all SMB versions share the same NETBIOS instances.
    """
    def __init__( self, error = 0, packet=0):
        SessionError.__init__(self)
        self.error = error
        self.packet = packet
        if packet != 0:
            self.error = self.packet['error-code']
Example #10
0
    def check_rdp(host, username, password, domain, hashes = None):

       if hashes is not None:
           lmhash, nthash = hashes.split(':')
           lmhash = a2b_hex(lmhash)
           nthash = a2b_hex(nthash)

       else:
           lmhash = ''
           nthash = ''

       tpkt = TPKT()
       tpdu = TPDU()
       rdp_neg = RDP_NEG_REQ()
       rdp_neg['Type'] = TYPE_RDP_NEG_REQ
       rdp_neg['requestedProtocols'] = PROTOCOL_HYBRID | PROTOCOL_SSL
       tpdu['VariablePart'] = str(rdp_neg)
       tpdu['Code'] = TDPU_CONNECTION_REQUEST
       tpkt['TPDU'] = str(tpdu)
   
       s = socket.socket()
       s.connect((host,3389))
       s.sendall(str(tpkt))
       pkt = s.recv(8192)
       tpkt.fromString(pkt)
       tpdu.fromString(tpkt['TPDU'])
       cr_tpdu = CR_TPDU(tpdu['VariablePart'])
       if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE:
           rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart'])
           rdp_failure.dump()
           logging.error("Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials")
           return
       else:
           rdp_neg.fromString(tpdu['VariablePart'])

       # Since we were accepted to talk PROTOCOL_HYBRID, below is its implementation

       # 1. The CredSSP client and CredSSP server first complete the TLS handshake, 
       # as specified in [RFC2246]. After the handshake is complete, all subsequent 
       # CredSSP Protocol messages are encrypted by the TLS channel. 
       # The CredSSP Protocol does not extend the TLS wire protocol. As part of the TLS 
       # handshake, the CredSSP server does not request the client's X.509 certificate 
       # (thus far, the client is anonymous). Also, the CredSSP Protocol does not require 
       # the client to have a commonly trusted certification authority root with the 
       # CredSSP server. Thus, the CredSSP server MAY use, for example, 
       # a self-signed X.509 certificate.

       # Switching to TLS now
       ctx = SSL.Context(SSL.TLSv1_METHOD)
       ctx.set_cipher_list('RC4')
       tls = SSL.Connection(ctx,s)
       tls.set_connect_state()
       tls.do_handshake()

       # If you want to use Python internal ssl, uncomment this and comment 
       # the previous lines
       #tls = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers='RC4')

       # 2. Over the encrypted TLS channel, the SPNEGO handshake between the client 
       # and server completes mutual authentication and establishes an encryption key 
       # that is used by the SPNEGO confidentiality services, as specified in [RFC4178]. 
       # All SPNEGO tokens as well as the underlying encryption algorithms are opaque to 
       # the calling application (the CredSSP client and CredSSP server). 
       # The wire protocol for SPNEGO is specified in [MS-SPNG].
       # The SPNEGO tokens exchanged between the client and the server are encapsulated 
       # in the negoTokens field of the TSRequest structure. Both the client and the 
       # server use this structure as many times as necessary to complete the SPNEGO 
       # exchange.<9>
       #
       # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted 
       # from the TSRequest structure by the client and server; the OPTIONAL pubKeyAuth 
       # field is omitted by the client unless the client is sending the last SPNEGO token. 
       # If the client is sending the last SPNEGO token, the TSRequest structure MUST have 
       # both the negoToken and the pubKeyAuth fields filled in.

       # NTLMSSP stuff
       auth = ntlm.getNTLMSSPType1('','',True, use_ntlmv2 = True)

       ts_request = TSRequest()
       ts_request['NegoData'] = str(auth)

       tls.send(ts_request.getData())
       buff = tls.recv(4096)
       ts_request.fromString(buff)

   
       # 3. The client encrypts the public key it received from the server (contained 
       # in the X.509 certificate) in the TLS handshake from step 1, by using the 
       # confidentiality support of SPNEGO. The public key that is encrypted is the 
       # ASN.1-encoded SubjectPublicKey sub-field of SubjectPublicKeyInfo from the X.509 
       # certificate, as specified in [RFC3280] section 4.1. The encrypted key is 
       # encapsulated in the pubKeyAuth field of the TSRequest structure and is sent over 
       # the TLS channel to the server. 
       #
       # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted 
       # from the TSRequest structure; the client MUST send its last SPNEGO token to the 
       # server in the negoTokens field (see step 2) along with the encrypted public key 
       # in the pubKeyAuth field.

       # Last SPNEGO token calculation
       #ntlmChallenge = ntlm.NTLMAuthChallenge(ts_request['NegoData'])
       type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, ts_request['NegoData'], username, password, domain, lmhash, nthash, use_ntlmv2 = True)

       # Get server public key
       server_cert =  tls.get_peer_certificate()
       pkey = server_cert.get_pubkey()
       dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey)

       # Fix up due to PyOpenSSL lack for exporting public keys
       dump = dump[7:]
       dump = '\x30'+ asn1encode(dump)

       cipher = SPNEGOCipher(type3['flags'], exportedSessionKey)
       signature, cripted_key = cipher.encrypt(dump)
       ts_request['NegoData'] = str(type3)
       ts_request['pubKeyAuth'] = str(signature) + cripted_key

       try:
           # Sending the Type 3 NTLM blob
           tls.send(ts_request.getData())
           # The other end is waiting for the pubKeyAuth field, but looks like it's
           # not needed to check whether authentication worked.
           # If auth is unsuccessful, it throws an exception with the previous send().
           # If auth is successful, the server waits for the pubKeyAuth and doesn't answer 
           # anything. So, I'm sending garbage so the server returns an error. 
           # Luckily, it's a different error so we can determine whether or not auth worked ;)
           buff = tls.recv(1024)
       except Exception, err:
           if str(err).find("denied") > 0:
               logging.error("Access Denied")
           else:
               logging.error(err)
           return
Example #11
0
def clientConnect(host, username, password, domain, connect=True):
    tpkt = TPKT()
    tpdu = TPDU()
    rdp_neg = RDP_NEG_REQ()
    rdp_neg['Type'] = TYPE_RDP_NEG_REQ
    rdp_neg[
        'requestedProtocols'] = PROTOCOL_HYBRID_EX | PROTOCOL_HYBRID | PROTOCOL_SSL
    tpdu['VariablePart'] = rdp_neg.getData()
    tpdu['Code'] = TDPU_CONNECTION_REQUEST
    tpkt['TPDU'] = tpdu.getData()

    s = socket.socket()
    s.connect((host, 3389))
    s.sendall(tpkt.getData())
    pkt = s.recv(8192)
    tpkt.fromString(pkt)
    tpdu.fromString(tpkt['TPDU'])
    cr_tpdu = CR_TPDU(tpdu['VariablePart'])
    if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE:
        rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart'])
        rdp_failure.dump()
        logging.error(
            "Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials"
        )
        return
    else:
        rdp_neg.fromString(tpdu['VariablePart'])

#Here we start the SPNEGO exchange

#Step1 : Start the SSL connection
    ctx = SSL.Context(SSL.TLSv1_2_METHOD)
    ctx.set_cipher_list('RC4,AES')
    tls = SSL.Connection(ctx, s)
    tls.set_connect_state()
    tls.do_handshake()

    #Step2: Send the SPNEGO handshake
    auth = ntlm.getNTLMSSPType1('', '', True, use_ntlmv2=True)

    ts_request = TSRequest()
    ts_request['NegoData'] = auth.getData()

    tls.send(ts_request.getData())
    buff = tls.recv(4096)
    ts_request.fromString(buff)

    #Step3: We should have an NTLM Challenge. Answer the challenge and sign the server pubkey

    lmhash = ''
    nthash = ''
    type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth,
                                                     ts_request['NegoData'],
                                                     username,
                                                     password,
                                                     domain,
                                                     lmhash,
                                                     nthash,
                                                     use_ntlmv2=True)
    # Get server public key
    server_cert = tls.get_peer_certificate()
    pkey = server_cert.get_pubkey()
    dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey)

    # Fix up due to PyOpenSSL lack for exporting public keys
    dump = dump[7:]
    pubKeyStr = b'\x30' + asn1encode(dump)
    clientNonce = "A" * 32
    magic = b"CredSSP Client-To-Server Binding Hash\x00"
    h2 = hashlib.sha256()
    h2.update(magic)
    h2.update(clientNonce)
    h2.update(pubKeyStr)

    cipher = SPNEGOCipher(type3['flags'], exportedSessionKey)
    signature, cripted_key = cipher.clientEncrypt(h2.digest())
    ts_request['NegoData'] = type3.getData()
    ts_request['clientNonce'] = clientNonce
    ts_request['pubKeyAuth'] = signature.getData() + cripted_key
    try:
        # Sending the Type 3 NTLM blob
        tls.send(ts_request.getData())
        buff = tls.recv(1024)
    except Exception as err:
        if str(err).find("denied") > 0:
            logging.error("Access Denied")
        else:
            print(err)
        return

#Step4: Server should send its pubkey signature.

    try:
        ts_request = TSRequest(buff)
        #if password is invalid buff can't be decode
        # Now we're decrypting the certificate + 1 sent by the server. Not worth checking ;)
        signature, plain_text = cipher.decrypt(ts_request['pubKeyAuth'])
        if username != "" and password != "":
            print "Found valid credentials: " + username + ":" + password
    except Exception as err:
        return 0

#Step5: Send the encrypted credentials to the server
    if connect == True:
        tsp = TSPasswordCreds()
        tsp['domainName'] = domain
        tsp['userName'] = username
        tsp['password'] = password
        tsc = TSCredentials()
        tsc['credType'] = 1  # TSPasswordCreds
        tsc['credentials'] = tsp.getData()
        signature, cripted_creds = cipher.clientEncrypt(tsc.getData())
        ts_request = TSRequest()
        ts_request['authInfo'] = signature.getData() + cripted_creds
        tls.send(ts_request.getData())
        print "Credentials sent"
        return tls
    else:
        return 1
Example #12
0
    def getData(self):
        if 'pubKeyAuth' in self.fields:
            pubKeyAuth = pack('B', 0xa3)
            pubKeyAuth += asn1encode(
                pack('B', ASN1_OCTET_STRING) + asn1encode(self['pubKeyAuth']))
        else:
            pubKeyAuth = b''

        if 'authInfo' in self.fields:
            authInfo = pack('B', 0xa2)
            authInfo += asn1encode(
                pack('B', ASN1_OCTET_STRING) + asn1encode(self['authInfo']))
        else:
            authInfo = b''

        if 'NegoData' in self.fields:
            negoData = pack('B', 0xa1)
            negoData += asn1encode(
                pack('B', ASN1_SEQUENCE) + asn1encode(
                    pack('B', ASN1_SEQUENCE) + asn1encode(
                        pack('B', 0xa0) + asn1encode(
                            pack('B', ASN1_OCTET_STRING) +
                            asn1encode(self['NegoData'])))))
        else:
            negoData = b''
        ans = pack('B', ASN1_SEQUENCE)
        ans += asn1encode(
            pack('B', 0xa0) +
            asn1encode(pack('B', 0x02) + asn1encode(pack('B', 0x02))) +
            negoData + authInfo + pubKeyAuth)
        return ans
Example #13
0
   def getData(self):
     # Do we have pubKeyAuth?
     if self.fields.has_key('pubKeyAuth'):
         pubKeyAuth = pack('B',0xa3)
         pubKeyAuth += asn1encode(pack('B', ASN1_OCTET_STRING) +
                       asn1encode(self['pubKeyAuth']))
     else:
         pubKeyAuth = ''

     if self.fields.has_key('authInfo'):
         authInfo = pack('B',0xa2)
         authInfo+= asn1encode(pack('B', ASN1_OCTET_STRING) +
                       asn1encode(self['authInfo']))
     else: 
         authInfo = ''

     if self.fields.has_key('NegoData'):
         negoData = pack('B',0xa1) 
         negoData += asn1encode(pack('B', ASN1_SEQUENCE) +
                    asn1encode(pack('B', ASN1_SEQUENCE) + 
                    asn1encode(pack('B', 0xa0) + 
                    asn1encode(pack('B', ASN1_OCTET_STRING) + 
                    asn1encode(self['NegoData'])))))
     else:
         negoData = ''
     ans = pack('B', ASN1_SEQUENCE)
     ans += asn1encode(pack('B',0xa0) + 
            asn1encode(pack('B',0x02) + asn1encode(pack('B',0x02))) +
            negoData + authInfo + pubKeyAuth)
     
     return ans
Example #14
0
   def getKRBData(self):

     # Do we have pubKeyAuth?
     if 'pubKeyAuth' in self.fields:
         pubKeyAuth = pack('B',0xa3)
         pubKeyAuth += asn1encode(pack('B', ASN1_OCTET_STRING) +
                       asn1encode(self['pubKeyAuth']))
     else:
         pubKeyAuth = b''

     if 'authInfo' in self.fields:
         authInfo = pack('B',0xa2)
         authInfo+= asn1encode(pack('B', ASN1_OCTET_STRING) +
                       asn1encode(self['authInfo']))
     else:
         authInfo = b''

     if 'clientNonce' in self.fields:
         clientNonce = pack('B',0xa5)
         clientNonce+= asn1encode(pack('B', ASN1_OCTET_STRING) +
                       asn1encode(self['clientNonce']))
     else:
         clientNonce = b''

     if 'errorCode' in self.fields:
         errorCode = pack('B',0xa4)
         errorCode+= asn1encode(pack('B', ASN1_OCTET_STRING) +
                       asn1encode(self['errorCode']))
     else:
         errorCode = b''


     if 'NegoData' in self.fields:
         negoData = pack('B',0xa1)
         negoData += asn1encode(pack('B', ASN1_SEQUENCE) +
                    asn1encode(pack('B', ASN1_SEQUENCE) +
                    asn1encode(pack('B', 0xa0) +
                    asn1encode(pack('B', ASN1_OCTET_STRING) +
                    asn1encode(self['NegoData'])))))
     else:
        negoData = b''


     if 'NegoDataKerb' in self.fields:
         negoDataKerb = pack('B',0xa1)
         negoDataKerb += asn1encode(pack('B', ASN1_SEQUENCE) +
                    asn1encode(pack('B', ASN1_SEQUENCE) +
                    asn1encode(pack('B', 0xa0) +
                    asn1encode(pack('B', 0x03) +
                    b"\x0a\x01\x01"))))
     else:
         negoDataKerb = b''

     #insert version
     if 'Version' in self.fields:
         version = asn1encode(pack('B',self['Version']))

     #if version not found, default to version 6 wich is most recent
     else:
         version = asn1encode(pack('B',0x06))

     ans = pack('B', ASN1_SEQUENCE)
     ans += asn1encode(pack('B',0xa0) +
            asn1encode(pack('B',0x0a) + version) +
            authInfo + pubKeyAuth + errorCode + clientNonce)
     realans = pack('B',0xa1) + asn1encode(ans)
     return realans
Example #15
0
   def getData(self):
     # Do we have pubKeyAuth?
     if self.fields.has_key('pubKeyAuth'):
         pubKeyAuth = pack('B',0xa3)
         pubKeyAuth += asn1encode(pack('B', ASN1_OCTET_STRING) +
                       asn1encode(self['pubKeyAuth']))
     else:
         pubKeyAuth = ''

     if self.fields.has_key('authInfo'):
         authInfo = pack('B',0xa2)
         authInfo+= asn1encode(pack('B', ASN1_OCTET_STRING) +
                       asn1encode(self['authInfo']))
     else: 
         authInfo = ''

     if self.fields.has_key('NegoData'):
         negoData = pack('B',0xa1) 
         negoData += asn1encode(pack('B', ASN1_SEQUENCE) +
                    asn1encode(pack('B', ASN1_SEQUENCE) + 
                    asn1encode(pack('B', 0xa0) + 
                    asn1encode(pack('B', ASN1_OCTET_STRING) + 
                    asn1encode(self['NegoData'])))))
     else:
         negoData = ''
     ans = pack('B', ASN1_SEQUENCE)
     ans += asn1encode(pack('B',0xa0) + 
            asn1encode(pack('B',0x02) + asn1encode(pack('B',0x02))) +
            negoData + authInfo + pubKeyAuth)
     
     return ans
Example #16
0
    #chkField['Flags'] = GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE
    authenticator['cksum']['checksum'] = chkField.getData()
    authenticator['seq-number'] = 0
    encodedAuthenticator = encoder.encode(authenticator)

    # Key Usage 11
    # AP-REQ Authenticator (includes application authenticator
    # subkey), encrypted with the application session key
    # (Section 5.5.1)
    encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None)

    apReq['authenticator'] = noValue
    apReq['authenticator']['etype'] = cipher.enctype
    apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator

    blob['MechToken'] = struct.pack('B', ASN1_AID) + asn1encode( struct.pack('B', ASN1_OID) + asn1encode(
            TypesMech['KRB5 - Kerberos 5'] ) + KRB5_AP_REQ + encoder.encode(apReq))

    return cipher, sessionKey, blob.getData()

class KerberosError(SessionError):
    """
    This is the exception every client should catch regardless of the underlying
    SMB version used. We'll take care of that. NETBIOS exceptions are NOT included,
    since all SMB versions share the same NETBIOS instances.
    """
    def __init__( self, error = 0, packet=0):
        SessionError.__init__(self)
        self.error = error
        self.packet = packet
        if packet != 0:
            self.error = self.packet['error-code']
Example #17
0
def check_rdp(host, username, password, domain, port=3389, hashes=None):
    if hashes is not None:
        lmhash, nthash = hashes.split(':')
        lmhash = a2b_hex(lmhash)
        nthash = a2b_hex(nthash)
    else:
        lmhash = ''
        nthash = ''
    tpkt = TPKT()
    tpdu = TPDU()
    rdp_neg = RDP_NEG_REQ()
    rdp_neg['Type'] = 1
    rdp_neg['requestedProtocols'] = 2 | 1
    tpdu['VariablePart'] = rdp_neg.getData()
    tpdu['Code'] = 0xe0
    tpkt['TPDU'] = tpdu.getData()
    s = socket.socket()
    s.connect((host, port))
    s.sendall(tpkt.getData())
    pkt = s.recv(8192)
    tpkt.fromString(pkt)
    tpdu.fromString(tpkt['TPDU'])
    cr_tpdu = CR_TPDU(tpdu['VariablePart'])
    if cr_tpdu['Type'] == 3:
        rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart'])
        rdp_failure.dump()
        logger.error(
            "Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials"
        )
        return
    else:
        rdp_neg.fromString(tpdu['VariablePart'])
    ctx = SSL.Context(SSL.TLSv1_2_METHOD)
    ctx.set_cipher_list(b'RC4,AES')
    tls = SSL.Connection(ctx, s)
    tls.set_connect_state()
    tls.do_handshake()
    auth = ntlm.getNTLMSSPType1('', '', True, use_ntlmv2=True)
    ts_request = TSRequest()
    ts_request['NegoData'] = auth.getData()
    tls.send(ts_request.getData())
    buff = tls.recv(4096)
    ts_request.fromString(buff)
    type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth,
                                                     ts_request['NegoData'],
                                                     username,
                                                     password,
                                                     domain,
                                                     lmhash,
                                                     nthash,
                                                     use_ntlmv2=True)
    server_cert = tls.get_peer_certificate()
    pkey = server_cert.get_pubkey()
    dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey)
    dump = dump[7:]
    dump = b'\x30' + asn1encode(dump)
    cipher = SPNEGOCipher(type3['flags'], exportedSessionKey)
    signature, cripted_key = cipher.encrypt(dump)
    ts_request['NegoData'] = type3.getData()
    ts_request['pubKeyAuth'] = signature.getData() + cripted_key
    try:
        tls.send(ts_request.getData())
        buff = tls.recv(1024)
    except Exception as err:
        if str(err).find("denied") > 0:
            logger.info("rdp Access Denied")
            return
        else:
            logger.warning(err)
        return
    ts_request = TSRequest(buff)
    signature, plain_text = cipher.decrypt(ts_request['pubKeyAuth'][16:])
    tsp = TSPasswordCreds()
    tsp['domainName'] = domain
    tsp['userName'] = username
    tsp['password'] = password
    tsc = TSCredentials()
    tsc['credType'] = 1  # TSPasswordCreds
    tsc['credentials'] = tsp.getData()
    signature, cripted_creds = cipher.encrypt(tsc.getData())
    ts_request = TSRequest()
    ts_request['authInfo'] = signature.getData() + cripted_creds
    tls.send(ts_request.getData())
    tls.close()
    # logger.success("Access Granted")
    logger.success("rdp success: {}/{}:{}@{}:{}".format(
        domain, username, password, host, port))
    return {
        'ip': host,
        'user': username,
        'password': password,
        'port': port,
        'serviceName': 'rdp',
        'detail': {
            'domain': domain,
            'hash': hashes
        }
    }
def getKerberosType1(username,
                     password,
                     domain,
                     lmhash,
                     nthash,
                     aesKey='',
                     TGT=None,
                     TGS=None,
                     targetName='',
                     kdcHost=None,
                     useCache=True):

    # Convert to binary form, just in case we're receiving strings
    if isinstance(lmhash, str):
        try:
            lmhash = unhexlify(lmhash)
        except TypeError:
            pass
    if isinstance(nthash, str):
        try:
            nthash = unhexlify(nthash)
        except TypeError:
            pass
    if isinstance(aesKey, str):
        try:
            aesKey = unhexlify(aesKey)
        except TypeError:
            pass

    if TGT is None and TGS is None:
        if useCache is True:
            try:
                ccache = CCache.loadFile(os.getenv('KRB5CCNAME'))
            except Exception:
                # No cache present
                pass
            else:
                # retrieve domain information from CCache file if needed
                if domain == '':
                    domain = ccache.principal.realm['data'].decode('utf-8')
                    LOG.debug('Domain retrieved from CCache: %s' % domain)

                LOG.debug("Using Kerberos Cache: %s" % os.getenv('KRB5CCNAME'))
                principal = 'host/%s@%s' % (targetName.upper(), domain.upper())
                creds = ccache.getCredential(principal)
                if creds is None:
                    # Let's try for the TGT and go from there
                    principal = 'krbtgt/%s@%s' % (domain.upper(),
                                                  domain.upper())
                    creds = ccache.getCredential(principal)
                    if creds is not None:
                        TGT = creds.toTGT()
                        LOG.debug('Using TGT from cache')
                    else:
                        LOG.debug("No valid credentials found in cache. ")
                else:
                    TGS = creds.toTGS(principal)

                # retrieve user information from CCache file if needed
                if username == '' and creds is not None:
                    username = creds['client'].prettyPrint().split(
                        b'@')[0].decode('utf-8')
                    LOG.debug('Username retrieved from CCache: %s' % username)
                elif username == '' and len(ccache.principal.components) > 0:
                    username = ccache.principal.components[0]['data'].decode(
                        'utf-8')
                    LOG.debug('Username retrieved from CCache: %s' % username)

    # First of all, we need to get a TGT for the user
    userName = Principal(username,
                         type=constants.PrincipalNameType.NT_PRINCIPAL.value)
    while True:
        if TGT is None:
            if TGS is None:
                try:
                    tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(
                        userName, password, domain, lmhash, nthash, aesKey,
                        kdcHost)
                except KerberosError as e:
                    if e.getErrorCode(
                    ) == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                        # We might face this if the target does not support AES
                        # So, if that's the case we'll force using RC4 by converting
                        # the password to lm/nt hashes and hope for the best. If that's already
                        # done, byebye.
                        if lmhash == b'' and nthash == b'' and (
                                aesKey == b'' or aesKey is None
                        ) and TGT is None and TGS is None:
                            from impacket.ntlm import compute_lmhash, compute_nthash
                            LOG.debug(
                                'Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4')
                            lmhash = compute_lmhash(password)
                            nthash = compute_nthash(password)
                            continue
                        else:
                            raise
                    else:
                        raise

        else:
            tgt = TGT['KDC_REP']
            cipher = TGT['cipher']
            sessionKey = TGT['sessionKey']

        # Now that we have the TGT, we should ask for a TGS for cifs

        if TGS is None:
            serverName = Principal(
                'host/%s' % targetName,
                type=constants.PrincipalNameType.NT_SRV_INST.value)
            try:
                tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS(
                    serverName, domain, kdcHost, tgt, cipher, sessionKey)
            except KerberosError as e:
                if e.getErrorCode(
                ) == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                    # We might face this if the target does not support AES
                    # So, if that's the case we'll force using RC4 by converting
                    # the password to lm/nt hashes and hope for the best. If that's already
                    # done, byebye.
                    if lmhash == b'' and nthash == b'' and (
                            aesKey == b''
                            or aesKey is None) and TGT is None and TGS is None:
                        from impacket.ntlm import compute_lmhash, compute_nthash
                        LOG.debug('Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4')
                        lmhash = compute_lmhash(password)
                        nthash = compute_nthash(password)
                    else:
                        raise
                else:
                    raise
            else:
                break
        else:
            tgs = TGS['KDC_REP']
            cipher = TGS['cipher']
            sessionKey = TGS['sessionKey']
            break

    # Let's build a NegTokenInit with a Kerberos REQ_AP

    blob = SPNEGO_NegTokenInit()

    # Kerberos
    blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']]

    # Let's extract the ticket from the TGS
    tgs = decoder.decode(tgs, asn1Spec=TGS_REP())[0]
    ticket = Ticket()
    ticket.from_asn1(tgs['ticket'])

    # Now let's build the AP_REQ
    apReq = AP_REQ()
    apReq['pvno'] = 5
    apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value)

    opts = list()
    opts.append(constants.APOptions.mutual_required.value)
    apReq['ap-options'] = constants.encodeFlags(opts)
    seq_set(apReq, 'ticket', ticket.to_asn1)

    authenticator = Authenticator()
    authenticator['authenticator-vno'] = 5
    authenticator['crealm'] = domain
    seq_set(authenticator, 'cname', userName.components_to_asn1)
    now = datetime.datetime.utcnow()

    authenticator['cusec'] = now.microsecond
    authenticator['ctime'] = KerberosTime.to_asn1(now)

    authenticator['cksum'] = noValue
    authenticator['cksum']['cksumtype'] = 0x8003

    chkField = CheckSumField()
    chkField['Lgth'] = 16

    chkField[
        'Flags'] = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE
    #chkField['Flags'] = GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE
    authenticator['cksum']['checksum'] = chkField.getData()
    authenticator['seq-number'] = 0
    encodedAuthenticator = encoder.encode(authenticator)

    # Key Usage 11
    # AP-REQ Authenticator (includes application authenticator
    # subkey), encrypted with the application session key
    # (Section 5.5.1)
    encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11,
                                                   encodedAuthenticator, None)

    apReq['authenticator'] = noValue
    apReq['authenticator']['etype'] = cipher.enctype
    apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator

    blob['MechToken'] = struct.pack('B', ASN1_AID) + asn1encode(
        struct.pack('B', ASN1_OID) +
        asn1encode(TypesMech['KRB5 - Kerberos 5']) + KRB5_AP_REQ +
        encoder.encode(apReq))

    return cipher, sessionKey, blob.getData()
Example #19
0
    def check_rdp(host, username, password, domain, hashes = None):

       if hashes is not None:
           lmhash, nthash = hashes.split(':')
           lmhash = a2b_hex(lmhash)
           nthash = a2b_hex(nthash)

       else:
           lmhash = ''
           nthash = ''

       tpkt = TPKT()
       tpdu = TPDU()
       rdp_neg = RDP_NEG_REQ()
       rdp_neg['Type'] = TYPE_RDP_NEG_REQ
       rdp_neg['requestedProtocols'] = PROTOCOL_HYBRID | PROTOCOL_SSL
       tpdu['VariablePart'] = str(rdp_neg)
       tpdu['Code'] = TDPU_CONNECTION_REQUEST
       tpkt['TPDU'] = str(tpdu)
   
       s = socket.socket()
       s.connect((host,3389))
       s.sendall(str(tpkt))
       pkt = s.recv(8192)
       tpkt.fromString(pkt)
       tpdu.fromString(tpkt['TPDU'])
       cr_tpdu = CR_TPDU(tpdu['VariablePart'])
       if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE:
           rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart'])
           rdp_failure.dump()
           logging.error("Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials")
           return
       else:
           rdp_neg.fromString(tpdu['VariablePart'])

       # Since we were accepted to talk PROTOCOL_HYBRID, below is its implementation

       # 1. The CredSSP client and CredSSP server first complete the TLS handshake, 
       # as specified in [RFC2246]. After the handshake is complete, all subsequent 
       # CredSSP Protocol messages are encrypted by the TLS channel. 
       # The CredSSP Protocol does not extend the TLS wire protocol. As part of the TLS 
       # handshake, the CredSSP server does not request the client's X.509 certificate 
       # (thus far, the client is anonymous). Also, the CredSSP Protocol does not require 
       # the client to have a commonly trusted certification authority root with the 
       # CredSSP server. Thus, the CredSSP server MAY use, for example, 
       # a self-signed X.509 certificate.

       # Switching to TLS now
       ctx = SSL.Context(SSL.TLSv1_2_METHOD)
       ctx.set_cipher_list('RC4,AES')
       tls = SSL.Connection(ctx,s)
       tls.set_connect_state()
       tls.do_handshake()

       # If you want to use Python internal ssl, uncomment this and comment 
       # the previous lines
       #tls = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers='RC4')

       # 2. Over the encrypted TLS channel, the SPNEGO handshake between the client 
       # and server completes mutual authentication and establishes an encryption key 
       # that is used by the SPNEGO confidentiality services, as specified in [RFC4178]. 
       # All SPNEGO tokens as well as the underlying encryption algorithms are opaque to 
       # the calling application (the CredSSP client and CredSSP server). 
       # The wire protocol for SPNEGO is specified in [MS-SPNG].
       # The SPNEGO tokens exchanged between the client and the server are encapsulated 
       # in the negoTokens field of the TSRequest structure. Both the client and the 
       # server use this structure as many times as necessary to complete the SPNEGO 
       # exchange.<9>
       #
       # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted 
       # from the TSRequest structure by the client and server; the OPTIONAL pubKeyAuth 
       # field is omitted by the client unless the client is sending the last SPNEGO token. 
       # If the client is sending the last SPNEGO token, the TSRequest structure MUST have 
       # both the negoToken and the pubKeyAuth fields filled in.

       # NTLMSSP stuff
       auth = ntlm.getNTLMSSPType1('','',True, use_ntlmv2 = True)

       ts_request = TSRequest()
       ts_request['NegoData'] = str(auth)

       tls.send(ts_request.getData())
       buff = tls.recv(4096)
       ts_request.fromString(buff)

   
       # 3. The client encrypts the public key it received from the server (contained 
       # in the X.509 certificate) in the TLS handshake from step 1, by using the 
       # confidentiality support of SPNEGO. The public key that is encrypted is the 
       # ASN.1-encoded SubjectPublicKey sub-field of SubjectPublicKeyInfo from the X.509 
       # certificate, as specified in [RFC3280] section 4.1. The encrypted key is 
       # encapsulated in the pubKeyAuth field of the TSRequest structure and is sent over 
       # the TLS channel to the server. 
       #
       # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted 
       # from the TSRequest structure; the client MUST send its last SPNEGO token to the 
       # server in the negoTokens field (see step 2) along with the encrypted public key 
       # in the pubKeyAuth field.

       # Last SPNEGO token calculation
       #ntlmChallenge = ntlm.NTLMAuthChallenge(ts_request['NegoData'])
       type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, ts_request['NegoData'], username, password, domain, lmhash, nthash, use_ntlmv2 = True)

       # Get server public key
       server_cert =  tls.get_peer_certificate()
       pkey = server_cert.get_pubkey()
       dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey)

       # Fix up due to PyOpenSSL lack for exporting public keys
       dump = dump[7:]
       dump = '\x30'+ asn1encode(dump)

       cipher = SPNEGOCipher(type3['flags'], exportedSessionKey)
       signature, cripted_key = cipher.encrypt(dump)
       ts_request['NegoData'] = str(type3)
       ts_request['pubKeyAuth'] = str(signature) + cripted_key

       try:
           # Sending the Type 3 NTLM blob
           tls.send(ts_request.getData())
           # The other end is waiting for the pubKeyAuth field, but looks like it's
           # not needed to check whether authentication worked.
           # If auth is unsuccessful, it throws an exception with the previous send().
           # If auth is successful, the server waits for the pubKeyAuth and doesn't answer 
           # anything. So, I'm sending garbage so the server returns an error. 
           # Luckily, it's a different error so we can determine whether or not auth worked ;)
           buff = tls.recv(1024)
       except Exception, err:
           if str(err).find("denied") > 0:
               logging.error("Access Denied")
           else:
               logging.error(err)
           return
Example #20
0
def getKerberosType1(username, password, domain, lmhash, nthash, aesKey='', TGT = None, TGS = None, targetName='', kdcHost = None, useCache = True):
    if TGT is None and TGS is None:
        if useCache is True:
            try:
                ccache = CCache.loadFile(os.getenv('KRB5CCNAME'))
            except Exception:
                # No cache present
                pass
            else:
                # retrieve domain information from CCache file if needed
                if domain == '':
                    domain = ccache.principal.realm['data'].decode('utf-8')
                    LOG.debug('Domain retrieved from CCache: %s' % domain)

                LOG.debug("Using Kerberos Cache: %s" % os.getenv('KRB5CCNAME'))
                principal = 'host/%s@%s' % (targetName.upper(), domain.upper())
                creds = ccache.getCredential(principal)
                if creds is None:
                    # Let's try for the TGT and go from there
                    principal = 'krbtgt/%s@%s' % (domain.upper(),domain.upper())
                    creds =  ccache.getCredential(principal)
                    if creds is not None:
                        TGT = creds.toTGT()
                        LOG.debug('Using TGT from cache')
                    else:
                        LOG.debug("No valid credentials found in cache. ")
                else:
                    TGS = creds.toTGS(principal)

                # retrieve user information from CCache file if needed
                if username == '' and creds is not None:
                    username = creds['client'].prettyPrint().split(b'@')[0]
                    LOG.debug('Username retrieved from CCache: %s' % username)
                elif username == '' and len(ccache.principal.components) > 0:
                    username = ccache.principal.components[0]['data']
                    LOG.debug('Username retrieved from CCache: %s' % username)

    # First of all, we need to get a TGT for the user
    userName = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
    while True:
        if TGT is None:
            if TGS is None:
                try:
                    tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, password, domain, lmhash, nthash, aesKey, kdcHost)
                except KerberosError as e:
                    if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                        # We might face this if the target does not support AES 
                        # So, if that's the case we'll force using RC4 by converting
                        # the password to lm/nt hashes and hope for the best. If that's already
                        # done, byebye.
                        if lmhash is '' and nthash is '' and (aesKey is '' or aesKey is None) and TGT is None and TGS is None:
                            from impacket.ntlm import compute_lmhash, compute_nthash
                            LOG.debug('Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4')
                            lmhash = compute_lmhash(password)
                            nthash = compute_nthash(password) 
                            continue
                        else:
                            raise 
                    else:
                        raise

        else:
            tgt = TGT['KDC_REP']
            cipher = TGT['cipher']
            sessionKey = TGT['sessionKey'] 

        # Now that we have the TGT, we should ask for a TGS for cifs

        if TGS is None:
            serverName = Principal('host/%s' % targetName, type=constants.PrincipalNameType.NT_SRV_INST.value)
            try:
                tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey)
            except KerberosError as e:
                if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                    # We might face this if the target does not support AES 
                    # So, if that's the case we'll force using RC4 by converting
                    # the password to lm/nt hashes and hope for the best. If that's already
                    # done, byebye.
                    if lmhash is '' and nthash is '' and (aesKey is '' or aesKey is None) and TGT is None and TGS is None:
                        from impacket.ntlm import compute_lmhash, compute_nthash
                        LOG.debug('Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4')
                        lmhash = compute_lmhash(password)
                        nthash = compute_nthash(password) 
                    else:
                        raise 
                else:
                    raise 
            else:
                break
        else:
            tgs = TGS['KDC_REP']
            cipher = TGS['cipher']
            sessionKey = TGS['sessionKey'] 
            break

    # Let's build a NegTokenInit with a Kerberos REQ_AP

    blob = SPNEGO_NegTokenInit() 

    # Kerberos
    blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']]

    # Let's extract the ticket from the TGS
    tgs = decoder.decode(tgs, asn1Spec = TGS_REP())[0]
    ticket = Ticket()
    ticket.from_asn1(tgs['ticket'])
    
    # Now let's build the AP_REQ
    apReq = AP_REQ()
    apReq['pvno'] = 5
    apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value)

    opts = list()
    opts.append(constants.APOptions.mutual_required.value)
    apReq['ap-options'] = constants.encodeFlags(opts)
    seq_set(apReq,'ticket', ticket.to_asn1)

    authenticator = Authenticator()
    authenticator['authenticator-vno'] = 5
    authenticator['crealm'] = domain
    seq_set(authenticator, 'cname', userName.components_to_asn1)
    now = datetime.datetime.utcnow()

    authenticator['cusec'] = now.microsecond
    authenticator['ctime'] = KerberosTime.to_asn1(now)

    
    authenticator['cksum'] = noValue
    authenticator['cksum']['cksumtype'] = 0x8003

    chkField = CheckSumField()
    chkField['Lgth'] = 16

    chkField['Flags'] = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE
    #chkField['Flags'] = GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE
    authenticator['cksum']['checksum'] = chkField.getData()
    authenticator['seq-number'] = 0
    encodedAuthenticator = encoder.encode(authenticator)

    # Key Usage 11
    # AP-REQ Authenticator (includes application authenticator
    # subkey), encrypted with the application session key
    # (Section 5.5.1)
    encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None)

    apReq['authenticator'] = noValue
    apReq['authenticator']['etype'] = cipher.enctype
    apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator

    blob['MechToken'] = struct.pack('B', ASN1_AID) + asn1encode( struct.pack('B', ASN1_OID) + asn1encode(
            TypesMech['KRB5 - Kerberos 5'] ) + KRB5_AP_REQ + encoder.encode(apReq))

    return cipher, sessionKey, blob.getData()