I tried some websites, but the page never generates a pdf. So I decided to inspect source code and further. If we inspect the network traffic we know that the server is running a Ruby app with Phusion Passenger (nginx).
If we set up a local python server and input it in the page bar, it asks us to save a generated pdf:
If we save the pdf and inspect it we can see the previous Nmap scan:
Iโll try to find some metadata related to the tool that creates this kind of pdfs using Exiftool ๐ง:
So it seems to be using pdfkit v0.8.6.
Weaponization
I searched for โpdfkit v0.8.6 cveโ and got CVE-2022-25765.
An application could be vulnerable if it tries to render a URL that contains query string parameters with user input:
If the provided parameter happens to contain a URL encoded character and a shell command substitution string, it will be included in the command that PDFKit executes to render the PDF:
Callingย to_pdfย on the instance shows that theย sleepย command is indeed executing:
Of course, if the user can control completely the first argument of the PDFKit constructor, they can also exploit the command injection as long as it starts with โhttpโ:
PDFKit.new("http%20`sleep 5`").to_pdf
Exploitation
Iโll craft my exploit with my python server ip and the linux command I want:
We can observe the output of the command id :D
So now we can craft a reverse shell command to gain remote access:
I tried this ruby shell, but it always closes the connection, so Iโll try to base64 encode it and then decode it and execute it:
Got a reverse shell :D
Lateral Movement
Once I stabilised the shell, I inspected the machine and rubyโs home directory:
So I found henryโs credentials inside /home/ruby/.bundle/config
henry:Q3c1AqGHtoI0aXAYFH
Got user flag :D
Privilege Escalation
If I execute sudo -l:
It seems that we can execute /opt/update_dependecies.rb as root. This file contains the following:
If I execute the the script, it seems that you need a file called dependencies.yml:
I did a quick search for that file:
So I decided to check for โRuby deserializationโ and find some cool information in PayloadsAllTheThings:
Itโs exactly the same code we have, so iโll check the Ruby version installed in the machine:
So we can use the following payload:
So I created a dependencies.yml on /dev/shm and I executed it:
Weโve got command injections :D
Though we could just read the root flag Iโll execute a reverse shell to gain root access (Iโll use the same payload as before):