Nocturnal
Enumeration
Nmap scan of the target:
No UDP services are running on the target.
The web server on port 80 appears to be a kind of file hosting service:
The application is written in PHP.
Once registered, users can upload and retrieve their documents:
Only a few file formats are accepted, and attempting to upload files with non-approved extensions results in an error:
The filtering is done on the server side. Only the file extension is being validated, as it's possible to upload an arbitrary file as long as it has the correct extension. The application even allows uploading files with a completely different MIME type than the file extension:
Despite this, there isn't any way of tricking the application into accepting a file that contains a malicious payload.
Foothold
Uploaded files are downloaded from the dashboard through the /view.php
endpoint in the form of the following GET request:
Crucially, the application allows users to view other user's files by simply changing the username
parameter. For instance, user admin
's files can be viewed without authentication:
For non-existing usernames, the application returns the error message User not found., which makes it easy to fuzz for valid usernames.
Used FFuF with a list of common usernames to discover additional valid usernames:
Of the two usernames found above, only amanda
has a single file stored:
privacy.odt
appears to be a letter from Nocturnal's IT team regarding a password change:
The password is valid for logging in to the application as user amanda
. From the dashboard, there is a link to the application admin panel:
The admin panel includes a viewer for the application source code, as well as a backup utility that backs up the application and uploaded files.
Creating a backup requires setting a password. The actual backup is handled by the following code in admin.php
:
The files are added to a .zip
archive by a call to the OS zip
command. Before the command is run, the application checks if the password contains any restricted characters by calling the cleanEntry()
function:
The highlighted line above lists all restricted characters, which includes a number of common characters used for chaining shell commands. Nevertheless, "
is not a restricted character, which means it can be used to end the password input early and inject an OS command like ls
:
The payload 123"ls
works because it ends the password input early by setting it to 123
, then hijacks the command input and runs ls
.
The backup command looks like so:
Substituting the payload for $password
gives the following:
Which effectively becomes:
As space is among the characters blocked in cleanEntry()
, adding spaces to commands is impossible. However, since the input sanitization is performed on the backend after it has been processed by the web browser, it's possible to trick the filter using URL encoded characters that resolve to whitespace when decoded. This still exludes the space character, but tab (%09
) is not blocked and can be used to encode whitespace in payloads.
There are no good payloads for a reverse shell that doesn't include any blocked characters, so the best approach foward is to look for files to exfiltrate.
A good candidate is the SQLite database for the application. The path is defined in dashboard.php
:
Used the following payload to copy the database from its current location to the working directory:
Created a backup in the admin panel UI with the database file included, then downloaded and opened it in sqlite3
.
The database contains a users
table with MD5 hashed passwords:
Cracked the hash for user tobias
with Hashcat in mode 0:
Used the obtained password to connect to the target over SSH as user tobias
.
Got the user flag.
Privilege Escalation
Enumerated network services running on the target with netstat
. Found a HTTP server listening on 127.0.0.1:8080
:
Used SSH port forwarding to forward the port to the attack host:
Navigated to http://127.0.0.1:8000
on the attack host and found an instance of ISPConfig:
Attempted to log in with default credentials (admin:admin
), but got an incorrect username or password error.
The application log in /var/log/ispconfig/auth.log
confirms that the username is admin
:
Tried logging in as admin
with the password found for tobias
earlier and got access to the admin panel:
Searching for recent vulnerabilities in ISPConfig turned up CVE-2023-46818, a PHP code injection vulnerability.
Used a previously published Python PoC to exploit the vulnerability:
Got the root flag.