Example #1
0
    def deriveKeysFromUser(self, sid, password):
        # Will generate two keys, one with SHA1 and another with MD4
        key1 = HMAC.new(SHA1.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest()
        key2 = HMAC.new(MD4.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest()
        # For Protected users
        tmpKey = pbkdf2_hmac('sha256', MD4.new(password.encode('utf-16le')).digest(), sid.encode('utf-16le'), 10000)
        tmpKey2 = pbkdf2_hmac('sha256', tmpKey, sid.encode('utf-16le'), 1)[:16]
        key3 = HMAC.new(tmpKey2, (sid + '\0').encode('utf-16le'), SHA1).digest()[:20]

        return key1, key2, key3
Example #2
0
    def deriveKeysFromUser(self, sid, password):
        # Will generate two keys, one with SHA1 and another with MD4
        key1 = HMAC.new(SHA1.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest()
        key2 = HMAC.new(MD4.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest()
        # For Protected users
        tmpKey = pbkdf2_hmac('sha256', MD4.new(password.encode('utf-16le')).digest(), sid.encode('utf-16le'), 10000)
        tmpKey2 = pbkdf2_hmac('sha256', tmpKey, sid.encode('utf-16le'), 1)[:16]
        key3 = HMAC.new(tmpKey2, (sid + '\0').encode('utf-16le'), SHA1).digest()[:20]

        return key1, key2, key3
def master(master_key, sid, password):

    #master_key
    fp = open(master_key, 'rb')
    data = fp.read()
    mkf = MasterKeyFile(data)
    if DEBUG:
        mkf.dump()

    fp.close()
    data = data[len(mkf):]
    mk = MasterKey(data[:mkf['MasterKeyLen']])

    # Will generate two keys, one with SHA1 and another with MD4
    key1 = HMAC.new(
        SHA1.new(password.encode('utf-16le')).digest(),
        (sid + '\0').encode('utf-16le'), SHA1).digest()
    key2 = HMAC.new(
        MD4.new(password.encode('utf-16le')).digest(),
        (sid + '\0').encode('utf-16le'), SHA1).digest()
    # For Protected users
    tmpKey = pbkdf2_hmac('sha256',
                         MD4.new(password.encode('utf-16le')).digest(),
                         sid.encode('utf-16le'), 10000)
    tmpKey2 = pbkdf2_hmac('sha256', tmpKey, sid.encode('utf-16le'), 1)[:16]
    key3 = HMAC.new(tmpKey2, (sid + '\0').encode('utf-16le'),
                    SHA1).digest()[:20]

    #/key1, key2, key3 = self.deriveKeysFromUser(self.options.sid, password)

    # if mkf['flags'] & 4 ? SHA1 : MD4
    decryptedKey = mk.decrypt(key3)
    if decryptedKey:
        print('Decrypted key with User Key (MD4 protected)')
        print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
        return decryptedKey

    decryptedKey = mk.decrypt(key2)
    if decryptedKey:
        print('Decrypted key with User Key (MD4)')
        print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
        return decryptedKey

    decryptedKey = mk.decrypt(key1)
    if decryptedKey:
        print('Decrypted key with User Key (SHA1)')
        print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
        return decryptedKey
Example #4
0
def NTOWFv2(password, user, userdom):
    nt_passwd = password.encode("utf-16-le")
    nt_hash_passwd = MD4.new(nt_passwd).digest()
    nt_userdom = (user.upper() + userdom).encode("utf-16-le")
    return HMAC.new(nt_hash_passwd,
                    nt_userdom,
                    MD5).digest()
Example #5
0
def generate_password():
    characters = string.printable
    characters = characters[:-5]
    password_length = int(5 + 10 * random.random())
    password = ''.join(random.choice(characters) for _ in range(password_length))
    print("Generated password:"******"utf-8")).hexdigest()
    print("Hashed password:", hashed, '\n')
    return hashed
Example #6
0
    def deriveKeysFromUser(self, sid, password):
        # Will generate two keys, one with SHA1 and another with MD4
        key1 = HMAC.new(
            SHA1.new(password.encode('utf-16le')).digest(),
            (sid + '\0').encode('utf-16le'), SHA1).digest()
        key2 = HMAC.new(
            MD4.new(password.encode('utf-16le')).digest(),
            (sid + '\0').encode('utf-16le'), SHA1).digest()

        return key1, key2
Example #7
0
def compute_nthash(password):
    # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
    try:
        password = str(password).encode('utf_16le')
    except UnicodeDecodeError:
        import sys
        password = password.decode(sys.getfilesystemencoding()).encode('utf_16le')

    hash = MD4.new()
    hash.update(password)
    return hash.digest()
Example #8
0
def compute_nthash(password):
    # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
    try:
        password = unicode(password).encode('utf_16le')
    except UnicodeDecodeError:
        import sys
        password = password.decode(sys.getfilesystemencoding()).encode('utf_16le')

    hash = MD4.new()
    hash.update(password)
    return hash.digest()
Example #9
0
def ComputeResponsev1(NegFlg, ResponseKeyNT, ResponseKeyLM, ServerChallenge,
                      ClientChallenge, Time=None, ServerName=None):
    if NegFlg & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
        NtChallengeResponse = DESL(ResponseKeyNT,
                                   MD5.new(ServerChallenge + \
                                           ClientChallenge).digest()[:8])
        LmChallengeResponse = ClientChallenge + "\0"*16
    else:
        NtChallengeResponse = DESL(ResponseKeyNT, ServerChallenge)
        LmChallengeResponse = DESL(ResponseKeyLM, ServerChallenge)
    SessionBaseKey = MD4.new(ResponseKeyNT).digest()
    return NtChallengeResponse, LmChallengeResponse, SessionBaseKey
Example #10
0
def pycrypto():
    import Crypto
    from Crypto.Hash import MD2
    from Crypto.Hash import MD4
    from Crypto.Hash import MD5
    from Crypto.Hash import SHA
    from Crypto.Hash import SHA224
    from Crypto.Hash import SHA256
    from Crypto.Hash import SHA384
    from Crypto.Hash import SHA512
    from Crypto.Hash import HMAC

    Crypto.Hash.MD2.new()  # Noncompliant
    MD2.new()  # Noncompliant
    MD4.new()  # Noncompliant
    MD5.new()  # Noncompliant
    SHA.new()  # Noncompliant
    SHA224.new()  # Noncompliant
    SHA256.new()  # Noncompliant
    SHA384.new()  # Noncompliant
    SHA512.new()  # Noncompliant
    HMAC.new(b"\x00")  # Noncompliant
Example #11
0
def cryptodome():
    import Cryptodome
    from Cryptodome.Hash import MD2
    from Cryptodome.Hash import MD4
    from Cryptodome.Hash import MD5
    from Cryptodome.Hash import SHA1
    from Cryptodome.Hash import SHA224
    from Cryptodome.Hash import SHA256
    from Cryptodome.Hash import SHA384
    from Cryptodome.Hash import SHA512
    from Cryptodome.Hash import HMAC

    Cryptodome.Hash.MD2.new()  # Noncompliant
    MD2.new()  # Noncompliant
    MD4.new()  # Noncompliant
    MD5.new()  # Noncompliant
    SHA1.new()  # Noncompliant
    SHA224.new()  # Noncompliant
    SHA256.new()  # OK
    SHA384.new()  # OK
    SHA512.new()  # OK
    HMAC.new(b"\x00")  # OK
Example #12
0
def otp(password, seed, sequence):
    """
    Calculates a one-time password hash using the given password, seed, and
    sequence number and returns it.
    Uses the MD4/sixword algorithm as supported by TACACS+ servers.

    :type  password: str
    :param password: A password.
    :type  seed: str
    :param seed: A cryptographic seed.
    :type  sequence: int
    :param sequence: A sequence number.
    :rtype:  string
    :return: A hash.
    """
    if len(password) not in list(range(4, 64)):
        raise ValueError('passphrase length')
    if len(seed) not in list(range(1, 17)):
        raise ValueError('seed length')
    for x in seed:
        if not x in _VALIDSEEDCHARACTERS:
            raise ValueError('seed composition')
    if sequence < 0:
        raise ValueError('sequence')

    # Pycryptodome only supports byte strings.
    seed = seed.encode('utf-8')
    password = password.encode('utf-8')

    # Discard the first <sequence> keys
    thehash = MD4.new(seed + password).digest()
    thehash = _fold_md4_or_md5(thehash)
    for i in range(0, sequence):
        thehash = _fold_md4_or_md5(MD4.new(thehash).digest())

    # Generate the result
    return _sixword_from_raw(thehash)
Example #13
0
def otp(password, seed, sequence):
    """
    Calculates a one-time password hash using the given password, seed, and
    sequence number and returns it.
    Uses the MD4/sixword algorithm as supported by TACACS+ servers.

    :type  password: str
    :param password: A password.
    :type  seed: str
    :param seed: A cryptographic seed.
    :type  sequence: int
    :param sequence: A sequence number.
    :rtype:  string
    :return: A hash.
    """
    if len(password) not in list(range(4, 64)):
        raise ValueError('passphrase length')
    if len(seed) not in list(range(1, 17)):
        raise ValueError('seed length')
    for x in seed:
        if not x in _VALIDSEEDCHARACTERS:
            raise ValueError('seed composition')
    if sequence < 0:
        raise ValueError('sequence')

    # Pycryptodome only supports byte strings.
    seed = seed.encode('utf-8')
    password = password.encode('utf-8')

    # Discard the first <sequence> keys
    thehash = MD4.new(seed + password).digest()
    thehash = _fold_md4_or_md5(thehash)
    for i in range(0, sequence):
        thehash = _fold_md4_or_md5(MD4.new(thehash).digest())

    # Generate the result
    return _sixword_from_raw(thehash)
Example #14
0
def ComputeResponsev1(NegFlg,
                      ResponseKeyNT,
                      ResponseKeyLM,
                      ServerChallenge,
                      ClientChallenge,
                      Time=None,
                      ServerName=None):
    if NegFlg & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
        NtChallengeResponse = DESL(ResponseKeyNT,
                                   MD5.new(ServerChallenge + \
                                           ClientChallenge).digest()[:8])
        LmChallengeResponse = ClientChallenge + "\0" * 16
    else:
        NtChallengeResponse = DESL(ResponseKeyNT, ServerChallenge)
        LmChallengeResponse = DESL(ResponseKeyLM, ServerChallenge)
    SessionBaseKey = MD4.new(ResponseKeyNT).digest()
    return NtChallengeResponse, LmChallengeResponse, SessionBaseKey
Example #15
0
 def string_to_key(cls, string, salt, params):
     utf16string = string.encode('UTF-16LE')
     return Key(cls.enctype, MD4.new(utf16string).digest())
Example #16
0
 def string_to_key(cls, string, salt, params):
     utf16string = string.encode('UTF-16LE')
     return Key(cls.enctype, MD4.new(utf16string).digest())
Example #17
0
from Crypto.Hash import MD4 as pycrypto_md4
from Crypto.Hash import MD5 as pycrypto_md5
from Crypto.Hash import SHA as pycrypto_sha
from Cryptodome.Hash import MD2 as pycryptodomex_md2
from Cryptodome.Hash import MD4 as pycryptodomex_md4
from Cryptodome.Hash import MD5 as pycryptodomex_md5
from Cryptodome.Hash import SHA as pycryptodomex_sha
import hashlib

hashlib.md5(1)
hashlib.md5(1).hexdigest()

abc = str.replace(hashlib.md5("1"), "###")

print(hashlib.md5("1"))

hashlib.sha1(1)

pycrypto_md2.new()
pycrypto_md4.new()
pycrypto_md5.new()
pycrypto_sha.new()

pycryptodomex_md2.new()
pycryptodomex_md4.new()
pycryptodomex_md5.new()
pycryptodomex_sha.new()

hashes.MD5()
hashes.SHA1()
Example #18
0
File: ntlm.py Project: szaydel/pike
def NTOWFv2(password, user, userdom):
    nt_passwd = password.encode("utf-16-le")
    nt_hash_passwd = MD4.new(nt_passwd).digest()
    nt_userdom = (user.upper() + userdom).encode("utf-16-le")
    return HMAC.new(nt_hash_passwd, nt_userdom, MD5).digest()
Example #19
0
File: ntlm.py Project: szaydel/pike
def NTOWFv1(password):
    nt_passwd = password.encode("utf-16-le")
    return MD4.new(nt_passwd).digest()
Example #20
0
from cryptography.hazmat.primitives import hashes
from Crypto.Hash import MD2 as pycrypto_md2
from Crypto.Hash import MD4 as pycrypto_md4
from Crypto.Hash import MD5 as pycrypto_md5
from Cryptodome.Hash import MD2 as pycryptodomex_md2
from Cryptodome.Hash import MD4 as pycryptodomex_md4
from Cryptodome.Hash import MD5 as pycryptodomex_md5
import hashlib

hashlib.md5(1)
hashlib.md5(1).hexdigest()

abc = str.replace(hashlib.md5("1"), "###")

print(hashlib.md5("1"))

pycrypto_md2.new()
pycrypto_md4.new()
pycrypto_md5.new()

pycryptodomex_md2.new()
pycryptodomex_md4.new()
pycryptodomex_md5.new()

hashes.MD5()
Example #21
0
def get_kerberos_loot(token, options):
    from pyasn1 import debug
    # debug.setLogger(debug.Debug('all'))
    # Do we have a Krb ticket?
    blob = decoder.decode(token, asn1Spec=GSSAPIHeader_SPNEGO_Init())[0]
    # print str(blob)

    data = blob['innerContextToken']['negTokenInit']['mechToken']

    try:
        payload = decoder.decode(data, asn1Spec=GSSAPIHeader_KRB5_AP_REQ())[0]
    except PyAsn1Error:
        raise Exception('Error obtaining Kerberos data')
    # print payload
    # It is an AP_REQ
    decodedTGS = payload['apReq']
    # print decodedTGS

    # Get ticket data

    cipherText = decodedTGS['ticket']['enc-part']['cipher']

    # Key Usage 2
    # AS-REP Ticket and TGS-REP Ticket (includes tgs session key or
    #  application session key), encrypted with the service key
    #  (section 5.4.2)

    newCipher = _enctype_table[int(decodedTGS['ticket']['enc-part']['etype'])]

    # Create decryption keys from specified Kerberos keys
    if options.hashes is not None:
        nthash = options.hashes.split(':')[1]
    else:
        nthash = ''

    aesKey = options.aeskey or ''

    allciphers = [
        int(constants.EncryptionTypes.rc4_hmac.value),
        int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value),
        int(constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value)
    ]

    # Store Kerberos keys
    # TODO: get the salt from preauth info (requires us to send AS_REQs to the DC)
    keys = {}

    if nthash != '':
        keys[int(constants.EncryptionTypes.rc4_hmac.value)] = unhexlify(nthash)
    if aesKey != '':
        if len(aesKey) == 64:
            keys[int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value
                     )] = unhexlify(aesKey)
        else:
            keys[int(constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value
                     )] = unhexlify(aesKey)

    ekeys = {}
    for kt, key in keys.items():
        ekeys[kt] = Key(kt, key)

    # Calculate Kerberos keys from specified password/salt
    if options.password and options.salt:
        for cipher in allciphers:
            if cipher == 23 and options.israwpassword:
                # RC4 calculation is done manually for raw passwords
                md4 = MD4.new()
                md4.update(options.password)
                ekeys[cipher] = Key(cipher, md4.digest())
            else:
                # Do conversion magic for raw passwords
                if options.israwpassword:
                    rawsecret = options.password.decode(
                        'utf-16-le', 'replace').encode('utf-8', 'replace')
                else:
                    # If not raw, it was specified from the command line, assume it's not UTF-16
                    rawsecret = options.password
                ekeys[cipher] = string_to_key(cipher, rawsecret, options.salt)
            LOG.debug('Calculated type %d Kerberos key: %s', cipher,
                      hexlify(ekeys[cipher].contents))

    # Select the correct encryption key
    try:
        key = ekeys[decodedTGS['ticket']['enc-part']['etype']]
    # This raises a KeyError (pun intended) if our key is not found
    except KeyError:
        LOG.error(
            'Could not find the correct encryption key! Ticket is encrypted with keytype %d, but keytype(s) %s were supplied',
            decodedTGS['ticket']['enc-part']['etype'],
            ', '.join([str(enctype) for enctype in ekeys.keys()]))
        return None

    # Recover plaintext info from ticket
    try:
        plainText = newCipher.decrypt(key, 2, cipherText)
    except InvalidChecksum:
        LOG.error(
            'Ciphertext integrity failed. Most likely the account password or AES key is incorrect'
        )
        if options.salt:
            LOG.info(
                'You specified a salt manually. Make sure it has the correct case.'
            )
        return
    LOG.debug('Ticket decrypt OK')
    encTicketPart = decoder.decode(plainText, asn1Spec=EncTicketPart())[0]
    sessionKey = Key(encTicketPart['key']['keytype'],
                     bytes(encTicketPart['key']['keyvalue']))

    # Key Usage 11
    # AP-REQ Authenticator (includes application authenticator
    # subkey), encrypted with the application session key
    # (Section 5.5.1)

    # print encTicketPart
    flags = encTicketPart['flags'].asBinary()
    # print flags
    # for flag in TicketFlags:
    #     if flags[flag.value] == '1':
    #         print flag
    # print flags[TicketFlags.ok_as_delegate.value]
    cipherText = decodedTGS['authenticator']['cipher']
    newCipher = _enctype_table[int(decodedTGS['authenticator']['etype'])]
    # Recover plaintext info from authenticator
    plainText = newCipher.decrypt(sessionKey, 11, cipherText)

    authenticator = decoder.decode(plainText, asn1Spec=Authenticator())[0]
    # print authenticator

    # The checksum may contain the delegated ticket
    cksum = authenticator['cksum']
    if cksum['cksumtype'] != 32771:
        raise Exception('Checksum is not KRB5 type: %d' % cksum['cksumtype'])

    # Checksum as in 4.1.1 [RFC4121]
    # Fields:
    # 0-3 Length of channel binding info (fixed at 16)
    # 4-19 channel binding info
    # 20-23 flags
    # 24-25 delegation option identifier
    # 26-27 length of deleg field
    # 28..(n-1) KRB_CRED message if deleg is used (n = length of deleg + 28)
    # n..last  extensions
    flags = struct.unpack('<L', bytes(cksum['checksum'])[20:24])[0]
    # print flags
    if not flags & GSS_C_DELEG_FLAG:
        LOG.error('Delegate info not set, cannot extract ticket!')
        LOG.error(
            'Make sure the account you use has unconstrained delegation rights'
        )
        return

    dlen = struct.unpack('<H', bytes(cksum['checksum'])[26:28])[0]
    deldata = bytes(cksum['checksum'])[28:28 + dlen]
    creds = decoder.decode(deldata, asn1Spec=KRB_CRED())[0]
    # print creds
    subkey = Key(authenticator['subkey']['keytype'],
                 bytes(authenticator['subkey']['keyvalue']))
    newCipher = _enctype_table[int(creds['enc-part']['etype'])]

    plainText = newCipher.decrypt(sessionKey, 14,
                                  bytes(creds['enc-part']['cipher']))
    # print plainText
    # Now we got the EncKrbCredPart
    enc_part = decoder.decode(plainText, asn1Spec=EncKrbCredPart())[0]

    for i, tinfo in enumerate(enc_part['ticket-info']):
        # This is what we are after :)
        username = '******'.join(
            [str(item) for item in tinfo['pname']['name-string']])
        realm = str(tinfo['prealm'])
        fullname = '%s@%s' % (username, realm)
        sname = Principal(
            [str(item) for item in tinfo['sname']['name-string']])
        LOG.info('Got ticket for %s [%s]', fullname, sname)
        ticket = creds['tickets'][i]
        filename = '%s_%s' % (fullname, sname)
        saveformat = options.format
        LOG.info('Saving ticket in %s.%s', filename, saveformat)
        ccache = KrbCredCCache()
        ccache.fromKrbCredTicket(ticket, tinfo)
        if saveformat == 'ccache':
            ccache.saveFile(filename + '.ccache')
        else:
            # Save as Kirbi
            oc = KRB_CRED()
            oc['tickets'].append(ticket)
            oc['enc-part']['etype'] = 0
            new_enc_part = EncKrbCredPart()
            new_enc_part['ticket-info'].append(tinfo)
            oc['enc-part']['cipher'] = encoder.encode(new_enc_part)
            ocdata = encoder.encode(oc)
            with open(filename + '.kirbi', 'wb') as outfile:
                outfile.write(ocdata)

    data = {
        'username': username,
        'domain': realm,
        # We take it from the ccache since this already has a helper function to get
        # it in the right format.
        'tgt': ccache.credentials[0].toTGT()
    }
    return data
Example #22
0
def NTOWFv1(password):
    nt_passwd = password.encode("utf-16-le")
    return MD4.new(nt_passwd).digest()
Example #23
0
def generateSessionKeyV1(password, lmhash, nthash):
    hash = MD4.new()
    hash.update(NTOWFv1(password, lmhash, nthash))
    return hash.digest()
Example #24
0
    def deriveKeysFromUser(self, sid, password):
        # Will generate two keys, one with SHA1 and another with MD4
        key1 = HMAC.new(SHA1.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest()
        key2 = HMAC.new(MD4.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest()

        return key1, key2
Example #25
0
def format_managedpassword(raw_value):
    blob = MSDS_MANAGEDPASSWORD_BLOB()
    blob.fromString(raw_value)
    return binascii.hexlify(MD4.new(blob['CurrentPassword'][:-2]).digest()).decode('utf8')
Example #26
0
def generateSessionKeyV1(password, lmhash, nthash):
    hash = MD4.new()
    hash.update(NTOWFv1(password, lmhash, nthash))
    return hash.digest()
Example #27
0
    def run(self):
        #self.client.search('dc=vulnerable,dc=contoso,dc=com', '(objectclass=person)')
        #print self.client.entries
        global dumpedDomain
        # Set up a default config
        domainDumpConfig = ldapdomaindump.domainDumpConfig()

        # Change the output directory to configured rootdir
        domainDumpConfig.basepath = self.config.lootdir

        # Create new dumper object
        domainDumper = ldapdomaindump.domainDumper(self.client.server,
                                                   self.client,
                                                   domainDumpConfig)

        if self.config.interactive:
            if self.tcp_shell is not None:
                LOG.info(
                    'Started interactive Ldap shell via TCP on 127.0.0.1:%d' %
                    self.tcp_shell.port)
                # Start listening and launch interactive shell.
                self.tcp_shell.listen()
                ldap_shell = LdapShell(self.tcp_shell, domainDumper,
                                       self.client)
                ldap_shell.cmdloop()
                return

        # If specified validate the user's privileges. This might take a while on large domains but will
        # identify the proper containers for escalating via the different techniques.
        if self.config.validateprivs:
            LOG.info(
                'Enumerating relayed user\'s privileges. This may take a while on large domains'
            )
            userSid, privs = self.validatePrivileges(self.username,
                                                     domainDumper)
            if privs['create']:
                LOG.info('User privileges found: Create user')
            if privs['escalateViaGroup']:
                name = privs['escalateGroup'].split(',')[0][3:]
                LOG.info(
                    'User privileges found: Adding user to a privileged group (%s)'
                    % name)
            if privs['aclEscalate']:
                LOG.info('User privileges found: Modifying domain ACL')

        # If validation of privileges is not desired, we assumed that the user has permissions to escalate
        # an existing user via ACL attacks.
        else:
            LOG.info(
                'Assuming relayed user has privileges to escalate a user via ACL attack'
            )
            privs = dict()
            privs['create'] = False
            privs['aclEscalate'] = True
            privs['escalateViaGroup'] = False

        # We prefer ACL escalation since it is more quiet
        if self.config.aclattack and privs['aclEscalate']:
            LOG.debug('Performing ACL attack')
            if self.config.escalateuser:
                # We can escalate an existing user
                result = self.getUserInfo(domainDumper,
                                          self.config.escalateuser)
                # Unless that account does not exist of course
                if not result:
                    LOG.error('Unable to escalate without a valid user.')
                else:
                    userDn, userSid = result
                    # Perform the ACL attack
                    self.aclAttack(userDn, domainDumper)
            elif privs['create']:
                # Create a nice shiny new user for the escalation
                userDn = self.addUser(privs['createIn'], domainDumper)
                if not userDn:
                    LOG.error('Unable to escalate without a valid user.')
                # Perform the ACL attack
                else:
                    self.aclAttack(userDn, domainDumper)
            else:
                LOG.error('Cannot perform ACL escalation because we do not have create user '\
                    'privileges. Specify a user to assign privileges to with --escalate-user')

        # If we can't ACL escalate, try adding us to a privileged group
        if self.config.addda and privs['escalateViaGroup']:
            LOG.debug('Performing Group attack')
            if self.config.escalateuser:
                # We can escalate an existing user
                result = self.getUserInfo(domainDumper,
                                          self.config.escalateuser)
                # Unless that account does not exist of course
                if not result:
                    LOG.error('Unable to escalate without a valid user.')
                # Perform the Group attack
                else:
                    userDn, userSid = result
                    self.addUserToGroup(userDn, domainDumper,
                                        privs['escalateGroup'])

            elif privs['create']:
                # Create a nice shiny new user for the escalation
                userDn = self.addUser(privs['createIn'], domainDumper)
                if not userDn:
                    LOG.error(
                        'Unable to escalate without a valid user, aborting.')
                # Perform the Group attack
                else:
                    self.addUserToGroup(userDn, domainDumper,
                                        privs['escalateGroup'])

            else:
                LOG.error('Cannot perform ACL escalation because we do not have create user '\
                          'privileges. Specify a user to assign privileges to with --escalate-user')

        # Dump LAPS Passwords
        if self.config.dumplaps:
            LOG.info("Attempting to dump LAPS passwords")

            success = self.client.search(
                domainDumper.root,
                '(&(objectCategory=computer))',
                search_scope=ldap3.SUBTREE,
                attributes=['DistinguishedName', 'ms-MCS-AdmPwd'])

            if success:

                fd = None
                filename = "laps-dump-" + self.username + "-" + str(
                    random.randint(0, 99999))
                count = 0

                for entry in self.client.response:
                    try:
                        dn = "DN:" + entry['attributes']['distinguishedname']
                        passwd = "Password:"******"a+")

                        count += 1

                        LOG.debug(dn)
                        LOG.debug(passwd)

                        fd.write(dn)
                        fd.write("\n")
                        fd.write(passwd)
                        fd.write("\n")

                    except:
                        continue

                if fd is None:
                    LOG.info(
                        "The relayed user %s does not have permissions to read any LAPS passwords"
                        % self.username)
                else:
                    LOG.info(
                        "Successfully dumped %d LAPS passwords through relayed account %s"
                        % (count, self.username))
                    fd.close()

        #Dump gMSA Passwords
        if self.config.dumpgmsa:
            LOG.info("Attempting to dump gMSA passwords")
            success = self.client.search(
                domainDumper.root,
                '(&(ObjectClass=msDS-GroupManagedServiceAccount))',
                search_scope=ldap3.SUBTREE,
                attributes=['sAMAccountName', 'msDS-ManagedPassword'])
            if success:
                fd = None
                filename = "gmsa-dump-" + self.username + "-" + str(
                    random.randint(0, 99999))
                count = 0
                for entry in self.client.response:
                    try:
                        sam = entry['attributes']['sAMAccountName']
                        data = entry['attributes']['msDS-ManagedPassword']
                        blob = MSDS_MANAGEDPASSWORD_BLOB()
                        blob.fromString(data)
                        hash = MD4.new()
                        hash.update(blob['CurrentPassword'][:-2])
                        passwd = binascii.hexlify(
                            hash.digest()).decode("utf-8")
                        userpass = sam + ':::' + passwd
                        LOG.info(userpass)
                        count += 1
                        if fd is None:
                            fd = open(filename, "a+")
                        fd.write(userpass)
                        fd.write("\n")
                    except:
                        continue
                if fd is None:
                    LOG.info(
                        "The relayed user %s does not have permissions to read any gMSA passwords"
                        % self.username)
                else:
                    LOG.info(
                        "Successfully dumped %d gMSA passwords through relayed account %s"
                        % (count, self.username))
                    fd.close()

        # Perform the Delegate attack if it is enabled and we relayed a computer account
        if self.config.delegateaccess and self.username[-1] == '$':
            self.delegateAttack(self.config.escalateuser, self.username,
                                domainDumper, self.config.sid)
            return

        # Add a new computer if that is requested
        # privileges required are not yet enumerated, neither is ms-ds-MachineAccountQuota
        if self.config.addcomputer:
            self.client.search(domainDumper.root,
                               "(ObjectClass=domain)",
                               attributes=['wellKnownObjects'])
            # Computer well-known GUID
            # https://social.technet.microsoft.com/Forums/windowsserver/en-US/d028952f-a25a-42e6-99c5-28beae2d3ac3/how-can-i-know-the-default-computer-container?forum=winservergen
            computerscontainer = [
                entry.decode('utf-8').split(":")[-1]
                for entry in self.client.entries[0]["wellKnownObjects"]
                if b"AA312825768811D1ADED00C04FD8D5CD" in entry
            ][0]
            LOG.debug("Computer container is {}".format(computerscontainer))
            self.addComputer(computerscontainer, domainDumper)
            return

        # Last attack, dump the domain if no special privileges are present
        if not dumpedDomain and self.config.dumpdomain:
            # Do this before the dump is complete because of the time this can take
            dumpedDomain = True
            LOG.info('Dumping domain info for first time')
            domainDumper.domainDump()
            LOG.info('Domain info dumped into lootdir!')
Example #28
0
    def __printSecret(self, name, secretItem):
        # Based on [MS-LSAD] section 3.1.1.4

        # First off, let's discard NULL secrets.
        if len(secretItem) == 0:
            logger.debug('Discarding secret %s, NULL Data' % name)
            return

        # We might have secrets with zero
        if secretItem.startswith('\x00\x00'):
            logger.debug('Discarding secret %s, all zeros' % name)
            return

        upperName = name.upper()

        logger.info('%s ' % name)

        secret = ''

        if upperName.startswith('_SC_'):
            # Service name, a password might be there
            # Let's first try to decode the secret
            try:
                strDecoded = secretItem.decode('utf-16le')
            except:
                pass
            else:
                # We have to get the account the service
                # runs under
                account = self.get_service_account(name[4:])

                if account is None:
                    secret = '(Unknown User) '
                else:
                    secret = "%s " % account

                secret += strDecoded

        elif upperName.startswith('DEFAULTPASSWORD'):
            # defaults password for winloggeron
            # Let's first try to decode the secret
            try:
                strDecoded = secretItem.decode('utf-16le')
            except:
                pass
            else:
                # We have to get the account this password is for
                account = self.get_default_loggerin_account()

                if account is None:
                    secret = '(Unknown User) '
                else:
                    secret = "%s " % account

                secret += strDecoded

        elif upperName.startswith('ASPNET_WP_PASSWORD'):
            try:
                strDecoded = secretItem.decode('utf-16le')
            except:
                pass
            else:
                secret = 'ASPNET %s' % strDecoded

        elif upperName.startswith('$MACHINE.ACC'):
            # Compute MD4 of the secret.. yes.. that is the nthash
            md4 = MD4.new()
            md4.update(secretItem)
            secret = "%s\\%s$:%s:%s:::" % (
                DataStore.server_domain, DataStore.server_name,
                ntlm.LMOWFv1('', '').encode('hex'), md4.digest().encode('hex'))

        if secret != '':
            print secret
            self.__secretItems.append(secret)
        else:
            # Default print, hexdump
            self.__secretItems.append('%s %s' %
                                      (name, secretItem.encode('hex')))
            hexdump(secretItem)
Example #29
0
def encode_password(password):
    return MD4.new(password.encode("utf-8")).hexdigest()