
Era
26th Jul 2025
Difficulty: Medium
Machine Author(s): yurivich
Successfully Pwned Era
nquangit has successfully completed and pwned this machine on Hack The Box.

Machine Information
None.
Enumeration
Enumeration is the first step in our journey to pwn the machine. We will start with some scans to identify potential vulnerabilities and then proceed with manual inspection of the application.
Nmap Scan
# Nmap 7.95 scan initiated Sat Aug 2 13:42:39 2025 as: /usr/lib/nmap/nmap --privileged -F -vv -sV -sC -Pn -oN nmap.txt 10.10.11.79
Nmap scan report for 10.10.11.79
Host is up, received user-set (0.046s latency).
Scanned at 2025-08-02 13:42:39 +07 for 11s
Not shown: 98 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 62 vsftpd 3.0.5
80/tcp open http syn-ack ttl 62 nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD OPTIONS
|_http-title: Did not follow redirect to http://era.htb/
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Aug 2 13:42:50 2025 -- 1 IP address (1 host up) scanned in 11.44 seconds
With the Nmap scan, we can see that the machine has two open ports: FTP on port 21 and HTTP on port 80. The HTTP service is running Nginx version 1.18.0.
Bonus information from the scan includes the FTP service version (vsftpd 3.0.5) and the HTTP server is redirecting to http://era.htb/
.
We need to add the domain era.htb
to our /etc/hosts
file to access the web application.
Nuclei scan
[waf-detect:nginxgeneric] [http] [info] http://era.htb/
[http-missing-security-headers:strict-transport-security] [http] [info] http://era.htb/
[http-missing-security-headers:permissions-policy] [http] [info] http://era.htb/
[http-missing-security-headers:referrer-policy] [http] [info] http://era.htb/
[http-missing-security-headers:cross-origin-embedder-policy] [http] [info] http://era.htb/
[http-missing-security-headers:cross-origin-opener-policy] [http] [info] http://era.htb/
[http-missing-security-headers:cross-origin-resource-policy] [http] [info] http://era.htb/
[http-missing-security-headers:content-security-policy] [http] [info] http://era.htb/
[http-missing-security-headers:x-frame-options] [http] [info] http://era.htb/
[http-missing-security-headers:x-content-type-options] [http] [info] http://era.htb/
[http-missing-security-headers:x-permitted-cross-domain-policies] [http] [info] http://era.htb/
[http-missing-security-headers:clear-site-data] [http] [info] http://era.htb/
[nginx-version] [http] [info] http://era.htb/ ["nginx/1.18.0"]
[tech-detect:font-awesome] [http] [info] http://era.htb/
[tech-detect:animate.css] [http] [info] http://era.htb/
[tech-detect:bootstrap] [http] [info] http://era.htb/
[tech-detect:nginx] [http] [info] http://era.htb/
[caa-fingerprint] [dns] [info] era.htb
The Nuclei scan reveals several security issues with the web application, including missing security headers such as Strict-Transport-Security
, Content-Security-Policy
, and X-Frame-Options
. It also detects the Nginx version and some technologies used in the application, such as Font Awesome and Bootstrap.
But it does not provide any direct vulnerabilities or misconfigurations that we can exploit at this stage.
Scan for hidden directories
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://era.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/Web-Content/common.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
css [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 191ms]
fonts [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 192ms]
img [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 176ms]
index.html [Status: 200, Size: 19493, Words: 3922, Lines: 447, Duration: 176ms]
js [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 176ms]
:: Progress: [4744/4744] :: Job [1/1] :: 227 req/sec :: Duration: [0:00:23] :: Errors: 0 ::
The fuzzing scan reveals several directories, including css
, fonts
, img
, js
, and an index.html
file. The presence of these directories suggests that the web application is using a standard structure for serving static files.
It isn’t very useful at this point, but it confirms that the web application is built with a typical structure.
Scan for subdomains
ffuf -u http://FUZZ.era.htb/ -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -o ffuf-subdomain.era.htb.txt
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://FUZZ.era.htb/
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
:: Output file : ffuf-subdomain.era.htb.txt
:: File format : json
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
file [Status: 200, Size: 6765, Words: 2608, Lines: 234, Duration: 176ms]
:: Progress: [4989/4989] :: Job [1/1] :: 913 req/sec :: Duration: [0:00:06] :: Errors: 4988 ::
The subdomain scan reveals a subdomain file.era.htb
that returns a 200 status code. This indicates that the subdomain is active and serving content.
Nuclei scan for subdomains
[cookies-without-httponly] [javascript] [info] file.era.htb ["PHPSESSID"]
[missing-sri] [http] [info] http://file.era.htb/ ["https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap","https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"]
[cookies-without-secure] [javascript] [info] file.era.htb ["PHPSESSID"]
[waf-detect:nginxgeneric] [http] [info] http://file.era.htb/
[http-missing-security-headers:clear-site-data] [http] [info] http://file.era.htb/
[http-missing-security-headers:cross-origin-opener-policy] [http] [info] http://file.era.htb/
[http-missing-security-headers:x-frame-options] [http] [info] http://file.era.htb/
[http-missing-security-headers:x-permitted-cross-domain-policies] [http] [info] http://file.era.htb/
[http-missing-security-headers:cross-origin-embedder-policy] [http] [info] http://file.era.htb/
[http-missing-security-headers:cross-origin-resource-policy] [http] [info] http://file.era.htb/
[http-missing-security-headers:strict-transport-security] [http] [info] http://file.era.htb/
[http-missing-security-headers:content-security-policy] [http] [info] http://file.era.htb/
[http-missing-security-headers:permissions-policy] [http] [info] http://file.era.htb/
[http-missing-security-headers:x-content-type-options] [http] [info] http://file.era.htb/
[http-missing-security-headers:referrer-policy] [http] [info] http://file.era.htb/
[nginx-version] [http] [info] http://file.era.htb/ ["nginx/1.18.0"]
[php-detect] [http] [info] http://file.era.htb/
[tech-detect:nginx] [http] [info] http://file.era.htb/
[tech-detect:php] [http] [info] http://file.era.htb/
[tech-detect:font-awesome] [http] [info] http://file.era.htb/
[tech-detect:google-font-api] [http] [info] http://file.era.htb/
[caa-fingerprint] [dns] [info] file.era.htb
The Nuclei scan for the subdomain file.era.htb
also has the same missing security headers as the main domain. It also detects the Nginx version and some technologies used in the application, such as Font Awesome and Google Fonts. And it confirms that the subdomain is running PHP.
FFUF scan for hidden files/directories on subdomains
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://file.era.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/Web-Content/common.txt
:: Extensions : .php
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 6765
________________________________________________
.hta [Status: 403, Size: 162, Words: 4, Lines: 8, Duration: 206ms]
.htaccess [Status: 403, Size: 162, Words: 4, Lines: 8, Duration: 207ms]
.htpasswd [Status: 403, Size: 162, Words: 4, Lines: 8, Duration: 206ms]
LICENSE [Status: 200, Size: 34524, Words: 5707, Lines: 663, Duration: 183ms]
assets [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 179ms]
download.php [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 188ms]
files [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 175ms]
images [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 176ms]
layout.php [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 181ms]
login.php [Status: 200, Size: 9214, Words: 3701, Lines: 327, Duration: 179ms]
logout.php [Status: 200, Size: 70, Words: 6, Lines: 1, Duration: 177ms]
manage.php [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 176ms]
register.php [Status: 200, Size: 3205, Words: 1094, Lines: 106, Duration: 180ms]
upload.php [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 177ms]
:: Progress: [9488/9488] :: Job [1/1] :: 222 req/sec :: Duration: [0:00:43] :: Errors: 0 ::
With the FFUF scan for hidden files and directories on the subdomain, we find several interesting files and directories that we can explore further.
Manual inspection of the website
After some scanning, we can access the web application at 2 URLs: http://era.htb/
and http://file.era.htb/
for further exploration.
The main page of the web application is just a static page with some information about the application. It does not provide any direct functionality or features that we can exploit.
The subdomain file.era.htb
is a storage service that allows users to upload and manage files. The main page shows us some information about the service and provides links to the login page.
From the home page, we can access 2 pages/functions: login.php
and security_login.php
. The login.php
page is the login page for the application, and the security_login.php
page is allows users to login with their security questions/answers.
But from the previous scan, we can see that the register.php
page is accessible, which allows us to create a new user account. Then we can register a new user account and login to the application.
Exploitation
Now we have access to the web application, we can start exploiting it to gain access to the shell and the user flag.
We can try to use all functions of the web application, and after uploading a file, we can see that the application returns an URL to download that includes an ID for the uploaded file. From this link we can download the file that we just uploaded.
With the id
parameter, we can try to brute force the ID of the uploaded file to find the file that we just uploaded. We can use a simple ffuf command with a wordlist to find the ID of the uploaded file.
# Generate a list of numbers from 0 to 9999
seq -f "%04g" 0 9999 > numbers.txt
# Use ffuf to brute force the id parameter
# Replace <replace cookie> with the actual PHPSESSID cookie value from your browser
ffuf -u http://file.era.htb/download.php\?id\=FUZZ -w numbers.txt -H "Cookie: PHPSESSID=<replace cookie>" -fs 7686
After brute forcing the ID, we find that the ID 54
and 150
might be useful. The ID 54
is the site backup file, and the ID 150
is a zip contain some signing information (key.pem
and x509.genkey
file).
With the ID 54
, we can download the site backup file, which contains the source code of the web application. We can analyze the source code to find potential vulnerabilities or misconfigurations that we can exploit.
Also from the site backup file, we have a database file filedb.sqlite
that contains the user accounts and their passwords hashed with bcrypt.
Read the source code of the application, we can realize that it has an vulnerability in the change security answer function - IDOR - We can change the security answer of any user.
From there, we can change the security answer and logged in as user admin_ef01cab31aa
.
From the admin account, we can see that it contains 2 files that we found by fuzzing ID above (signing.zip and a site backup file).
Get a reverse shell
After logged in as admin user, now we need to find a way to get a reverse shell because from the nmap
scan the SSH port isn’t open.
Within the database file filedb.sqlite
, from the password hash we can perform a crack password attack with John-The-Ripper
and we can crack the password of 2 user: eric
& yuri
.
With the cracked credentials, we can use the username and password of the user yuri to access the FTP
service that we have scanned in the nmap
scan.
In there, we could access 2 directories apache2_conf
and php8.1_conf
and we doesn’t have permission to write on that shares.
But in the php8.1conf
directory, we realize that it has a file ssh2.so
that belongs/related to the ssh2
extension for the PHP - we could perform the SSH connection with the PHP code/syntax.
And now, we need to find a position that we can use to exploit with the SSH2 extension.
From the download.php
file in the source code site backup, we got a note for a BETA function that only available for admin user.
Read the code and we got that it calls a fopen
function to read the file uploaded and return it to the user.
It has a special point here is it receive a param format
from the user GET
parameter input (as the prefix) and concatenate with the file name then pass it to the fopen
function.
From here, we can perform a simple injection to perform some checks like use another scheme, use PHP wrapped.
SSH2 extension Stream Wrappers
And it the SSH2
extension we have discovered above, read the documentation and we can see that it support PHP stream wrapped and we can use the ssh2.exec
to make a connection to the local SSH service and run a reverse shell.
Part of this article is encrypted with password:
❌ This box is still active on HackTheBox. Once retired, this article will be published for public access as per HackTheBox’s policy on publishing content from their platform.
For more hints and assistance, come chat with me and the rest of your peers in the HackTheBox Discord server.
Good luck!
Leave a comment