Machine Information Table#
Field | Details |
---|---|
Machine Name | Nocturnal |
Operating System | Linux |
Difficulty | Easy |
Release Date | 12 Apr 2025 |
Creators | FisMatHack |
Introduction#
Today we’re tackling Nocturnal, a machine that provides a great learning path through several common vulnerabilities. We’ll start with a subtle username enumeration flaw, escalate our privileges through a classic command injection, and finally achieve root by exploiting a known vulnerability in an internally hosted web service. Let’s dive in!
Initial Reconnaissance: Nmap#
As always, we begin with a thorough nmap scan to identify open ports and running services. This initial step is crucial for mapping out our attack surface.
nmap -p- -sC -sV -oN nmap-initial 10.129.165.238
The scan reveals two primary services:
# Nmap 7.95 scan initiated Wed Jul 9 21:37:52 2025
Nmap scan report for 10.129.165.238
Host is up (0.037s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.12 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://nocturnal.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
The results are straightforward:
- Port 22: Running OpenSSH 8.2p1. This is a standard entry point, but we’ll need credentials to proceed.
- Port 80: Running nginx 1.18.0. The nmap script output gives us a critical piece of information: a redirect to http://nocturnal.htb .
This tells us the web server is configured for virtual hosting. To access the web application correctly, we need to add this domain to our /etc/hosts file.
#/etc/hosts file
10.129.165.238 nocturnal.htb
With that configured, let’s explore the web application.
Foothold: Upload file & Parameter Fuzzing#
Navigating to http://nocturnal.htb presents a file upload utility. The application allows users to create an account and upload documents with specific extensions: pdf, doc, docx, xls, xlsx, odt.
My first instinct, was to test the upload functionality for a potential Remote Code Execution (RCE) vulnerability. I tried various bypass techniques to upload a PHP shell (e.g., using double extensions like shell.php.pdf, manipulating content-types), but the server-side validation was robust enough to block these attempts or not allow to run the file, only download it.
The real vulnerability became apparent when I analyzed how uploaded files were accessed. After uploading a file, it could be viewed using a URL with two parameters:
http://nocturnal.htb/view.php?username=[YOUR_USERNAME]&file=[FILENAME]
This structure immediately suggests a potential Local File Inclusion (LFI) vulnerability. However, standard LFI and path traversal payloads like ../../../../etc/passwd didn’t work. The application seemed to correctly sanitize the file parameter.
This led me to investigate the username parameter. When I changed username to admin and it worked file error “File does not exist”. What happens if we provide an invalid username?
Invalid username (?username=invaliduser&file=test.pdf): The server returns a “User not found” message.
Valid username (?username=myuser&file=nonexistent.pdf): The server returns a “File does not exist” message.
This difference in response is a Username Enumeration vulnerability. We can abuse this to build a list of valid users on the system. I used Hydra to automate this, using a common username list and filtering out for the “User not found” Content-Length.
This brute-force attack quickly identified a valid users.
With a amanda account, I could read privacy.odt file on her account, which contained her password! After logging in as amanda, we gain access to an admin dashboard.
I tried also to spray this password through ssh but without success.
Lateral Movement: Command Injection in the Backup Utility#
The admin dashboard allow to read server files even the admin.php console itself. Inside the dashboard I found the database of service.
Another feature is “backup” feature. Analyzing the application’s admin.php exposed the command used to create the backup:
This is a Command Injection vulnerability. The user-supplied $password parameter is concatenated directly into a system() call without any sanitization. This means we can break out of the zip command and execute arbitrary commands on the server.
A tried with diffrent techniques with no success. Semicolon or && not work as we are in the middle of the command. I needed to break the command and run my own command.
I tried with zip parameter that allow to run system commands like that:
username=password -T -tt 'ls'&
But it didn’t work either.
The final way to do this is to break command with \n and \t. The idea behind using \n or \t is a form of argument injection. You’re not using a shell metacharacter like ; or && to chain commands. Instead, you’re hoping that the shell (/bin/sh or /bin/bash) that receives the final command string will interpret the newline or tab character as a delimiter, causing it to see what follows as a new, separate command.
If you injected mypassword\nls -la, the hope is the shell would process it as two separate lines:
- zip -x … -P mypassword
- ls -la …
And this worked out here, but you need to send it as URL-encoded like that: password%0als%09
Before trying to run reverse shell, I made a try to read datbase, but the access was denied.
Create a reverse shell payload#
First, I tried with running shell directly from parameter but it failed, then I used two steps. Download script and run it.
And with ls I could check if file was uploaded.
Triggering the backup function executed the payload, and a reverse shell connected back to my listener as the www-data user!
Privilege Escalation: From www-data to tobias#
Now on the system as www-data, the next goal is to escalate to a user shell. I began with checking a SQLite database file already founded in website files: database.db.
This database likely contains user credentials. I transferred it to my local machine to analyze it.
Before I started to crack all of accounts I checked /home
So I cracked the password for tobias with rockyou.txt
Then I got access as tobias
Root: Abusing an Outdated ISPConfig Instance#
The final step is to get root. I found the kernel version I try this vulnerability.
But it didn’t work for me. Then I started further enumeration. I checked for running processes and network connections with ss -tulpn
This revealed a service running locally on port 8080. Since this port isn’t exposed externally, I used SSH local port forwarding to access it from my machine.
Forward local port 8080 to the remote port 8080#
Navigating to http://localhost:9090 on my browser revealed a login page for ISPConfig 3. I tried the credentials for tobias on the admin user account, and it worked!
The dashboard footer showed the version: ISPConfig 3.2.10p1. A quick search revealed this version is vulnerable to an authenticated Remote Code Execution (RCE).
The exploit works by injecting PHP code into a client’s cron job configuration. Since the ISPConfig panel is running with root privileges, the injected code will also execute as root.
I found a public exploit script, configured it with the target details (URL, username, password), and ran it. The script automated the process of logging in, creating a malicious cron job, and triggering it.
A few moments later, a root shell connected back to my final netcat listener.
Conclusion & Key Takeaways#
Nocturnal was a fantastic box that demonstrated a realistic attack chain.
Information Disclosure is Dangerous: Even a subtle difference in error messages can lead to a full user list, providing attackers with valid targets.
Always Sanitize Input: The command injection vulnerability was a direct result of trusting user input. All data coming from a user must be treated as hostile and be properly sanitized or parameterized.
Patch: The final step to root was possible only because an outdated version of ISPConfig with a known public RCE exploit was running. Keeping software up-to-date is one of the most effective security controls.